是否有一种有效的方法来判断DOM元素(在HTML文档中)当前是否可见(出现在视口中)?

(这个问题指的是Firefox。)


当前回答

这是一个简单而简单的解决方法,对我来说很有效。

示例:您想查看元素在具有溢出滚动的父元素中是否可见。

$(window).on('scroll', function () {

     var container = $('#sidebar');
     var containerHeight = container.height();
     var scrollPosition = $('#row1').offset().top - container.offset().top;

     if (containerHeight < scrollPosition) {
         console.log('not visible');
     } else {
         console.log('visible');
     }
})

其他回答

下面是检查给定元素在其父元素中是否完全可见的代码片段:

export const visibleInParentViewport = (el) => {
  const elementRect = el.getBoundingClientRect();
  const parentRect = el.parentNode.getBoundingClientRect();

  return (
    elementRect.top >= parentRect.top &&
    elementRect.right >= parentRect.left &&
    elementRect.top + elementRect.height <= parentRect.bottom &&
    elementRect.left + elementRect.width <= parentRect.right
  );
}

我的更短更快的版本:

function isElementOutViewport(el){
    var rect = el.getBoundingClientRect();
    return rect.bottom < 0 || rect.right < 0 || rect.left > window.innerWidth || rect.top > window.innerHeight;
}

和一个jsFiddle按要求:https://jsfiddle.net/on1g619L/1/

我使用这个函数(它只检查y是否在屏幕上,因为大多数时候x是不需要的)

function elementInViewport(el) {
    var elinfo = {
        "top":el.offsetTop,
        "height":el.offsetHeight,
    };

    if (elinfo.top + elinfo.height < window.pageYOffset || elinfo.top > window.pageYOffset + window.innerHeight) {
        return false;
    } else {
        return true;
    }

}

我有同样的问题,并通过使用getBoundingClientRect()来解决。

这段代码完全是“通用的”,只需要写一次就可以工作(你不需要为你想知道的每个元素都写出来)。

这段代码只检查它在视口中是否垂直,而不是水平。在本例中,变量(array)'elements'保存了所有你要检查的垂直在视口中的元素,所以在任何地方抓取任何你想要的元素并将它们存储在那里。

for循环遍历每个元素并检查它是否垂直地位于视口中。这段代码在用户每次滚动时执行!如果getBoudingClientRect()。Top小于viewport的3/4(元素在viewport中的四分之一),它注册为“在viewport中”。

因为代码是通用的,你会想知道“哪个”元素在视口中。要找出这一点,可以通过自定义属性、节点名、id、类名等确定。

这是我的代码(如果它不起作用,请告诉我;它已在Internet Explorer 11、Firefox 40.0.3、Chrome Version 45.0.2454.85 m、Opera 31.0.1889.174和Edge with Windows 10(还没有Safari)上测试……

// Scrolling handlers...
window.onscroll = function(){
  var elements = document.getElementById('whatever').getElementsByClassName('whatever');
  for(var i = 0; i != elements.length; i++)
  {
   if(elements[i].getBoundingClientRect().top <= window.innerHeight*0.75 &&
      elements[i].getBoundingClientRect().top > 0)
   {
      console.log(elements[i].nodeName + ' ' +
                  elements[i].className + ' ' +
                  elements[i].id +
                  ' is in the viewport; proceed with whatever code you want to do here.');
   }
};

让我感到困扰的是,该功能没有以jquery为中心的版本可用。当我看到Dan的解决方案时,我发现有机会为那些喜欢用jQuery OO风格编程的人提供一些东西。它很漂亮,很时髦,对我来说很有魅力。

哒哒,哒哒,嘣

$.fn.inView = function(){
    if(!this.length) 
        return false;
    var rect = this.get(0).getBoundingClientRect();

    return (
        rect.top >= 0 &&
        rect.left >= 0 &&
        rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
        rect.right <= (window.innerWidth || document.documentElement.clientWidth)
    );

};

// Additional examples for other use cases
// Is true false whether an array of elements are all in view
$.fn.allInView = function(){
    var all = [];
    this.forEach(function(){
        all.push( $(this).inView() );
    });
    return all.indexOf(false) === -1;
};

// Only the class elements in view
$('.some-class').filter(function(){
    return $(this).inView();
});

// Only the class elements not in view
$('.some-class').filter(function(){
    return !$(this).inView();
});

使用

$(window).on('scroll',function(){

    if( $('footer').inView() ) {
        // Do cool stuff
    }
});