当用户滚动到特定元素时触发事件 - 使用jQuery

99

我在页面下方有一个 h1 标题..

<h1 id="scroll-to">TRIGGER EVENT WHEN SCROLLED TO.</h1>

我希望当用户滚动到h1标签或该标签在其浏览器视图中时,能够触发警报。

$('#scroll-to').scroll(function() {
     alert('you have scrolled to the h1!');
});

我该怎么做?

14个回答

172

你可以计算元素的offset,然后将其与scroll值进行比较,例如:

$(window).scroll(function() {
   var hT = $('#scroll-to').offset().top,
       hH = $('#scroll-to').outerHeight(),
       wH = $(window).height(),
       wS = $(this).scrollTop();
   if (wS > (hT+hH-wH)){
       console.log('H1 on the view!');
   }
});

查看此演示 Fiddle


更新了演示 Fiddle,没有弹出提示框--相反,淡入(FadeIn())元素


更新代码以检查元素是否在视口内。因此,无论您向上滚动还是向下滚动,都会向if语句添加一些规则,使其有效:

   if (wS > (hT+hH-wH) && (hT > wS) && (wS+wH > hT+hH)){
       //Do something
   }

演示Fiddle


15
请为这个去抖动! - Joe Frambach
1
有没有像jQuery Waypoint那样的函数库包可以实现这个功能? - kaycee49
1
谢谢@DaniP。很棒的代码片段! - Ana DEV
3
你可以使用.off()来解绑事件。http://jsfiddle.net/n4pdx/543/ - DaniP
1
@DaniP 我刚刚完成了,谢谢!还有感谢你的答案,帮了我很多 :) - Paolo
显示剩余6条评论

32

将这个问题与jQuery触发动作当用户滚动页面的某个部分时的最佳答案结合起来:

var element_position = $('#scroll-to').offset().top;

$(window).on('scroll', function() {
    var y_scroll_pos = window.pageYOffset;
    var scroll_pos_test = element_position;

    if(y_scroll_pos > scroll_pos_test) {
        //do stuff
    }
});

更新

我已经改进了代码,使得它在元素滚动到屏幕中间时触发,而不是在顶部触发。如果用户滚动到屏幕底部时函数还没有触发,它也会触发代码。

var element_position = $('#scroll-to').offset().top;
var screen_height = $(window).height();
var activation_offset = 0.5;//determines how far up the the page the element needs to be before triggering the function
var activation_point = element_position - (screen_height * activation_offset);
var max_scroll_height = $('body').height() - screen_height - 5;//-5 for a little bit of buffer

//Does something when user scrolls to it OR
//Does it when user has reached the bottom of the page and hasn't triggered the function yet
$(window).on('scroll', function() {
    var y_scroll_pos = window.pageYOffset;

    var element_in_view = y_scroll_pos > activation_point;
    var has_reached_bottom_of_page = max_scroll_height <= y_scroll_pos && !element_in_view;

    if(element_in_view || has_reached_bottom_of_page) {
        //Do something
    }
});

请注意,'pageYOffset'已被弃用。 - undefined

9

1
我已经尝试过这个方法了。它只有在你滚动到元素之后才会触发。还有其他的解决方案吗? - kaycee49
这个解决方案很好地获取了推荐,并且我已经在生产中使用它。请参考博客:https://liyao13.wordpress.com/2017/05/11/8-html-css-javascript-and-mongodb-tips/ - Yao Li

7

7

滚动成功后只触发一次

注意:所谓的成功滚动是指当用户滚动到所需元素或者说所需元素在视图中时。

这个答案对我来说有效率达到了90%,所以我稍微调整了一下,使其真正只在成功滚动时触发一次。

$(window).on('scroll',function() {
    var hT = $('#comment-box-section').offset().top,
    hH = $('#comment-box-section').outerHeight(),
    wH = $(window).height(),
    wS = $(this).scrollTop();
    if (wS > ((hT+hH-wH)-500)){
        console.log('comment box section arrived! eh');
        // This detaches the scroll so doStuff() won't run more than once
        $(window).off('scroll');
        doStuff();
    }
});

5
您可以在所有设备上使用此功能。
$(document).on('scroll', function() {
    if( $(this).scrollTop() >= $('#target_element').position().top ){
        do_something();
    }
});

4

Intersection Observer(交叉观察器)可以说是我认为最好的东西了,它不需要任何外部库,就能非常出色地完成工作。

const options = {
            root: null,
            threshold: 0.25, // 0 - 1 this work as a trigger. 
            rootMargin: '150px'
        };

        const target = document.querySelector('h1#scroll-to');
        const observer = new IntersectionObserver(
           entries => { // each entry checks if the element is the view or not and if yes trigger the function accordingly
            entries.forEach(() => {
                alert('you have scrolled to the h1!')
            });
        }, options);
        observer.observe(target);

不幸的是,这会显示两次警报 - 一次在观察器初始化时,一次在目标出现时。解决此问题的一种方法是使用isVisible,但是该函数仅在IntersectionObserver V2中实现,而该版本仅由Chrome 支持 - clayRay

3

2

这应该是你需要的。

Javascript:

$(window).scroll(function() {
    var hT = $('#circle').offset().top,
        hH = $('#circle').outerHeight(),
        wH = $(window).height(),
        wS = $(this).scrollTop();
    console.log((hT - wH), wS);
    if (wS > (hT + hH - wH)) {
        $('.count').each(function() {
            $(this).prop('Counter', 0).animate({
                Counter: $(this).text()
            }, {
                duration: 900,
                easing: 'swing',
                step: function(now) {
                    $(this).text(Math.ceil(now));
                }
            });
        }); {
            $('.count').removeClass('count').addClass('counted');
        };
    }
});

CSS:

#circle
{
    width: 100px;
    height: 100px;
    background: blue;
    -moz-border-radius: 50px;
    -webkit-border-radius: 50px;
    border-radius: 50px;
    float:left;
    margin:5px;
}
.count, .counted
{
  line-height: 100px;
  color:white;
  margin-left:30px;
  font-size:25px;
}
#talkbubble {
   width: 120px;
   height: 80px;
   background: green;
   position: relative;
   -moz-border-radius:    10px;
   -webkit-border-radius: 10px;
   border-radius:         10px;
   float:left;
   margin:20px;
}
#talkbubble:before {
   content:"";
   position: absolute;
   right: 100%;
   top: 15px;
   width: 0;
   height: 0;
   border-top: 13px solid transparent;
   border-right: 20px solid green;
   border-bottom: 13px solid transparent;
}

HTML:

<div id="talkbubble"><span class="count">145</span></div>
<div style="clear:both"></div>
<div id="talkbubble"><span class="count">145</span></div>
<div style="clear:both"></div>
<div id="circle"><span class="count">1234</span></div>

请查看这个 Bootply: http://www.bootply.com/atin_agarwal2/cJBywxX5Qp


2
如果您正在寻找JavaScript版本。您可以在滚动事件监听器上调用此方法。
  showScrollTop = () =>{
    const currentScrollPosition = window.pageYOffset; 
    let elementID = 'service-selector'
    const elementOffsetTop = document.getElementById(elementID).offsetTop

    if ( currentScrollPosition > elementOffsetTop){
     // place your logic here 
    } else {
      // place your logic here 
    }
  }

  window.addEventListener('scroll', showScrollTop)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接