jQuery - 检测元素是否在视口中

12
我正在编写一个脚本,当元素出现在屏幕中时,为它们添加不同的动画效果。第一步是检测它们何时出现在屏幕中,但这似乎不起作用。
我尝试过:
- 使用.visible()选择器,但我很快发现这在jQuery中有其他作用。
- 不同的插件,但我发现它们做的比我需要的要多,因此我决定自己编写/查找一些东西。
- 我目前的脚本(我在某个论坛上找到它并决定根据我的需求进行编辑),但它的工作有点奇怪。
$.fn.isInViewport = function () {
    let elementTop = $(this).offset().top;
    let elementBottom = elementTop + $(this).outerHeight();

    let viewportTop = $(window).scrollTop();
    let viewportBottom = viewportTop + $(window).height();

    return elementBottom > viewportTop && elementTop < viewportBottom;
};

$(window).scroll(function () {
    if ($('.blogcard ').isInViewport()) {
        $(this).addClass("test");
        console.log('success.')
    } else {
        console.log('No success.')
    }
});

不幸的是,这似乎没有将类添加到我的 <div class='blogcard'> 中。


你的逻辑缺少几个场景。请尝试Roko在这里的答案。 - Rory McCrossan
首先尝试获取视口位置范围和元素位置范围?然后,计算该元素是否在范围内。 - Samson
使用Intersection Observer API来检测元素是否在视口中,详细信息请参见此处 - https://frontendguruji.com/blog/how-to-detect-if-element-is-in-viewport-intersection-observer-api/ - Mandeep Pasbola
4个回答

11

您使用的 "this" 目标是窗口而不是 .blogcard 元素:

$(window).scroll(function () {
    if ($('.blogcard ').isInViewport()) {
        //  Use .blogcard instead of this
        $('.blogcard').addClass('test');
        console.log('success.')
    } else {
        //  Remove class
        $('.blogcard').removeClass('test');
        console.log('No success.')
    }
});

谢谢,我没有注意到。还有一个问题;现在它只是给所有的.blogcards添加了test类,即使它们已经超出了视口范围。 - mike
如果它们不在视口中,你需要移除这些类。 - jacobdo
我得到了“Uncaught TypeError: $(...).isInViewport is not a function”错误,这是我的Jquery版本问题吗?如果是,我需要使用哪个版本才能使用此函数?提前感谢您的帮助。 - dita

2
你需要将'this'上下文传入到$(window).scroll函数中。我通过循环元素来实现,而不是仅检查.class isInViewport()。"最初的回答"
$(window).scroll(function () {
   $('.blogcard').each(function(i, el){

      if ($(this).isInViewport()) {
          $(this).addClass('test');
          console.log('content block is in viewport.', $(this))
      } 
   })

});

移除该类会导致内容动画效果过于明显,因此我将其取消了。

新的回答

1

给未来的谷歌用户。这个发布的函数有一个bug,$(window).height()没有提供viewport高度,而是整个文档的高度。这个isInViewport函数总是返回true。这是正确的实现:

$.fn.isInViewport = function () {
  let elementTop = $(this).offset().top;
  let elementBottom = elementTop + $(this).outerHeight();

  let viewportTop = $(window).scrollTop();
  let viewportBottom = viewportTop + window.innerHeight; // <-- here

  return elementBottom > viewportTop && elementTop < viewportBottom;
};

1

Please try this code ...

$(window).scroll(function () {
    if ($('.section3 ').isInViewport()) {
        $('.section3').addClass('its-now-view');
        alert('sction 3 is now in viewport');
    } else {
        $('.section3').addClass('its-now-view');
       alert('sction 3 is not in viewport');
    }
});
.section{
 height:400px;
}
.section1{
  background-color: #333;
}
.section2{
  background-color: red;
}
.section3{
  background-color: yellow;
}
.section4{
  background-color: green;
}
<html>
<head>
<title>Viewport demo</title>
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/1.7/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/is-in-viewport/3.0.4/isInViewport.min.js"></script>
</head>
<body>
<div class="content-wrapper">
<div class="section section1">
  <p>Content of section 1</p>
</div>
<div class="section section2">
  <p>Content of section 2</p>
</div>
<div class="section section3">
  <p>Content of section 3</p>
</div>
<div class="section section4">
  <p>Content of section 4</p>
</div>

</div>

</body>
</html>


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