我通过AJAX加载元素。其中一些只有当你向下滚动页面时才能看到。有什么方法可以知道元素现在是否在页面的可见部分?


当前回答

这个问题有超过30个答案,没有一个使用我一直在使用的令人惊讶的简单的纯JS解决方案。没有必要仅仅为了解决这个问题而加载jQuery,因为许多人都在推动这个问题。

为了判断元素是否在视口中,我们必须首先确定元素在主体中的位置。我们不需要像我以前想的那样递归地做这个。相反,我们可以使用element.getBoundingClientRect()。

pos = elem.getBoundingClientRect().top - document.body.getBoundingClientRect().top;

这个值是物体顶部和主体顶部之间的Y差。

然后我们必须判断元素是否在视图中。大多数实现都会询问完整的元素是否在视口中,所以这就是我们将要讨论的内容。

首先,窗口的顶部位置是:window. scrolly。

我们可以通过将窗口的高度加到窗口的顶部位置来获得窗口的底部位置:

var window_bottom_position = window.scrollY + window.innerHeight;

让我们创建一个简单的函数来获取元素的顶部位置:

function getElementWindowTop(elem){
    return elem && typeof elem.getBoundingClientRect === 'function' ? elem.getBoundingClientRect().top - document.body.getBoundingClientRect().top : 0;
}

这个函数将返回元素在窗口中的顶部位置,或者如果你通过. getboundingclientrect()方法传递给它的不是元素,它将返回0。这个方法已经存在很长时间了,所以您不必担心浏览器不支持它。

现在,元素的顶部位置是:

var element_top_position = getElementWindowTop(element);

And或元素的底部位置为:

var element_bottom_position = element_top_position + element.clientHeight;

现在我们可以通过检查元素的底部位置是否低于viewport的顶部位置,以及检查元素的顶部位置是否高于viewport的底部位置来确定元素是否在viewport中:

if(element_bottom_position >= window.scrollY 
&& element_top_position <= window_bottom_position){
    //element is in view
else
    //element is not in view

从那里,您可以执行逻辑来在元素上添加或删除视图内类,然后您可以稍后在CSS中使用过渡效果处理该类。

我非常惊讶,我没有在其他地方找到这个解决方案,但我相信这是最干净和最有效的解决方案,而且它不需要您加载jQuery!

其他回答

简单修改可滚动的div(容器)

var isScrolledIntoView = function(elem, container) {
    var containerHeight = $(container).height();
    var elemTop = $(elem).position().top;
    var elemBottom = elemTop + $(elem).height();
    return (elemBottom > 0 && elemTop < containerHeight);
}

注意:如果元素大于可滚动的div,则此方法无效。

更新:使用IntersectionObserver


目前为止我发现的最好的方法是jQuery appear插件。效果非常好。

模仿自定义的“appear”事件,该事件在元素滚动到视图或以其他方式对用户可见时触发。 $ (' # foo) .appear(函数(){ (美元)。文本(“Hello world”); }); 这个插件可以用来防止对隐藏的或在可视区域之外的内容的不必要请求。

如果你想在另一个div中滚动项目,

function isScrolledIntoView (elem, divID) 

{

    var docViewTop = $('#' + divID).scrollTop();


    var docViewBottom = docViewTop + $('#' + divID).height();

    var elemTop = $(elem).offset().top;
    var elemBottom = elemTop + $(elem).height();

    return ((elemBottom <= docViewBottom) && (elemTop >= docViewTop)); 
}

这是我的纯JavaScript解决方案,如果它隐藏在一个可滚动的容器。

演示在这里(尝试调整窗口的大小)

var visibleY = function(el){
  var rect = el.getBoundingClientRect(), top = rect.top, height = rect.height, 
    el = el.parentNode
  // Check if bottom of the element is off the page
  if (rect.bottom < 0) return false
  // Check its within the document viewport
  if (top > document.documentElement.clientHeight) return false
  do {
    rect = el.getBoundingClientRect()
    if (top <= rect.bottom === false) return false
    // Check if the element is out of view due to a container scrolling
    if ((top + height) <= rect.top) return false
    el = el.parentNode
  } while (el != document.body)
  return true
};

编辑2016-03-26:我已经更新了解决方案,以考虑滚动过去的元素,所以它隐藏在可滚动容器的顶部。 编辑2018-10-08:更新到当滚动到屏幕上方的视图外时处理。

function isScrolledIntoView(elem) {
    var docViewTop = $(window).scrollTop(),
        docViewBottom = docViewTop + $(window).height(),
        elemTop = $(elem).offset().top,
     elemBottom = elemTop + $(elem).height();
   //Is more than half of the element visible
   return ((elemTop + ((elemBottom - elemTop)/2)) >= docViewTop && ((elemTop + ((elemBottom - elemTop)/2)) <= docViewBottom));
}