如何检查滚动后元素是否可见?

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

861946 次浏览

我的应用程序中有这样一个方法,但它不使用jQuery:

/* Get the TOP position of a given element. */function getPositionTop(element){var offset = 0;while(element) {offset += element["offsetTop"];element = element.offsetParent;}return offset;}
/* Is a given element is visible or not? */function isElementVisible(eltId) {var elt = document.getElementById(eltId);if (!elt) {// Element not found.return false;}// Get the top and bottom position of the given element.var posTop = getPositionTop(elt);var posBottom = posTop + elt.offsetHeight;// Get the top and bottom position of the *visible* part of the window.var visibleTop = document.body.scrollTop;var visibleBottom = visibleTop + document.documentElement.offsetHeight;return ((posBottom >= visibleTop) && (posTop <= visibleBottom));}

编辑:此方法适用于I. E.(至少版本6)。阅读注释以了解与FF的兼容性。

WebResourcesDepot前段时间写了滚动时加载的脚本,使用了jQuery。你可以查看他们的现场演示。他们的功能是这样的:

$(window).scroll(function(){if  ($(window).scrollTop() == $(document).height() - $(window).height()){lastAddedLiveFunc();}});
function lastAddedLiveFunc() {$('div#lastPostsLoader').html('<img src="images/bigLoader.gif">');$.post("default.asp?action=getLastPosts&lastPostID="+$(".wrdLatest:last").attr("id"),function(data){if (data != "") {$(".wrdLatest:last").after(data);}$('div#lastPostsLoader').empty();});};

这应该做的伎俩:

function isScrolledIntoView(elem){var docViewTop = $(window).scrollTop();var docViewBottom = docViewTop + $(window).height();
var elemTop = $(elem).offset().top;var elemBottom = elemTop + $(elem).height();
return ((elemBottom <= docViewBottom) && (elemTop >= docViewTop));}

简单实用函数这将允许您调用一个实用函数,该函数接受您要查找的元素,以及您希望该元素完全或部分显示。

function Utils() {
}
Utils.prototype = {constructor: Utils,isElementInView: function (element, fullyInView) {var pageTop = $(window).scrollTop();var pageBottom = pageTop + $(window).height();var elementTop = $(element).offset().top;var elementBottom = elementTop + $(element).height();
if (fullyInView === true) {return ((pageTop < elementTop) && (pageBottom > elementBottom));} else {return ((elementTop <= pageBottom) && (elementBottom >= pageTop));}}};
var Utils = new Utils();

用法

var isElementInView = Utils.isElementInView($('#flyout-left-container'), false);
if (isElementInView) {console.log('in view');} else {console.log('out of view');}
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 visiblereturn ((elemTop + ((elemBottom - elemTop)/2)) >= docViewTop && ((elemTop + ((elemBottom - elemTop)/2)) <= docViewBottom));}

更新:使用交叉观察器


到目前为止,我发现的最好的方法是jQuery出现插件

模仿自定义“出现”事件,当元素滚动到视图中或以其他方式对用户可见时触发。

$('#foo').appear(function() {$(this).text('Hello world');});

此插件可用于防止对隐藏或超出可视区域的内容的不必要请求。

jQuery航点插件在这里非常好。

$('.entry').waypoint(function() {alert('You have scrolled to an entry.');});

插件的站点上有一些例子。

有一个用于jQuery的插件,名为inview添加了一个新的“inview”事件。


以下是不使用事件的jQuery插件的一些代码:

$.extend($.expr[':'],{inView: function(a) {var st = (document.documentElement.scrollTop || document.body.scrollTop),ot = $(a).offset().top,wh = (window.innerHeight && window.innerHeight < $(window).height()) ? window.innerHeight : $(window).height();return ot > st && ($(a).height() + ot) < (st + wh);}});
(function( $ ) {$.fn.inView = function() {var st = (document.documentElement.scrollTop || document.body.scrollTop),ot = $(this).offset().top,wh = (window.innerHeight && window.innerHeight < $(window).height()) ? window.innerHeight : $(window).height();
return ot > st && ($(this).height() + ot) < (st + wh);};})( jQuery );

我在一个叫詹姆斯的家伙的评论中发现了这个(http://remysharp.com/2009/01/26/element-in-view-event-plugin/

如果您想调整此项以在另一个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));}

我只是想分享我将它与我的脚本相结合来移动div,以便它始终保持在视图中:

    $("#accordion").on('click', '.subLink', function(){var url = $(this).attr('src');updateFrame(url);scrollIntoView();});
$(window).scroll(function(){changePos();});
function scrollIntoView(){var docViewTop = $(window).scrollTop();var docViewBottom = docViewTop + $(window).height();var elemTop = $("#divPos").offset().top;var elemBottom = elemTop + $("#divPos").height();if (elemTop < docViewTop){$("#divPos").offset({top:docViewTop});}}
function changePos(){var scrTop = $(window).scrollTop();var frmHeight = $("#divPos").height()if ((scrTop < 200) || (frmHeight > 800)){$("#divPos").attr("style","position:absolute;");}else{$("#divPos").attr("style","position:fixed;top:5px;");}}

我需要检查可滚动DIV容器内元素的可见性

    //p = DIV container scrollable//e = elementfunction visible_in_container(p, e) {var z = p.getBoundingClientRect();var r = e.getBoundingClientRect();
// Check style visiblilty and off-limitsreturn e.style.opacity > 0 && e.style.display !== 'none' &&e.style.visibility !== 'hidden' &&!(r.top > z.bottom || r.bottom < z.top ||r.left > z.right || r.right < z.left);}

为我的要求推了Scott Dowding的酷功能-这用于查找元素是否刚刚滚动到屏幕中,即它的顶部边缘。

function isScrolledIntoView(elem){var docViewTop = $(window).scrollTop();var docViewBottom = docViewTop + $(window).height();var elemTop = $(elem).offset().top;return ((elemTop <= docViewBottom) && (elemTop >= docViewTop));}

修改了已接受的答案,以便元素必须将其显示属性设置为“无”以外的内容,以使质量可见。

function isScrolledIntoView(elem) {var docViewTop = $(window).scrollTop();var docViewBottom = docViewTop + $(window).height();
var elemTop = $(elem).offset().top;var elemBottom = elemTop + $(elem).height();var elemDisplayNotNone = $(elem).css("display") !== "none";
return ((elemBottom <= docViewBottom) && (elemTop >= docViewTop) && elemDisplayNotNone);}

是否滚动显示是一个非常必要的函数,所以我试了一下,它适用于不比视口高的元素,但是如果元素比视口大,它就不起作用。要轻松修复此问题,请更改条件

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

对此:

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

在此处查看演示:http://jsfiddle.net/RRSmQ/

这是我的纯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 pageif (rect.bottom < 0) return false// Check its within the document viewportif (top > document.documentElement.clientHeight) return falsedo {rect = el.getBoundingClientRect()if (top <= rect.bottom === false) return false// Check if the element is out of view due to a container scrollingif ((top + height) <= rect.top) return falseel = el.parentNode} while (el != document.body)return true};

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

这里有另一个解决方案:

<script type="text/javascript">$.fn.is_on_screen = function(){var win = $(window);var viewport = {top : win.scrollTop(),left : win.scrollLeft()};viewport.right = viewport.left + win.width();viewport.bottom = viewport.top + win.height();
var bounds = this.offset();bounds.right = bounds.left + this.outerWidth();bounds.bottom = bounds.top + this.outerHeight();
return (!(viewport.right < bounds.left || viewport.left > bounds.right ||    viewport.bottom < bounds.top || viewport.top > bounds.bottom));};
if( $('.target').length > 0 ) { // if target element exists in DOMif( $('.target').is_on_screen() ) { // if target element is visible on screen after DOM loaded$('.log').html('<div class="alert alert-success">target element is visible on screen</div>'); // log info} else {$('.log').html('<div class="alert">target element is not visible on screen</div>'); // log info}}$(window).on('scroll', function(){ // bind window scroll eventif( $('.target').length > 0 ) { // if target element exists in DOMif( $('.target').is_on_screen() ) { // if target element is visible on screen after DOM loaded$('.log').html('<div class="alert alert-success">target element is visible on screen</div>'); // log info} else {$('.log').html('<div class="alert">target element is not visible on screen</div>'); // log info}}});</script>

JSFiddle中看到它

这个答案香草:

function isScrolledIntoView(el) {var rect = el.getBoundingClientRect();var elemTop = rect.top;var elemBottom = rect.bottom;
// Only completely visible elements return true:var isVisible = (elemTop >= 0) && (elemBottom <= window.innerHeight);// Partially visible elements return true://isVisible = elemTop < window.innerHeight && elemBottom >= 0;return isVisible;}

怎么样

function isInView(elem){return $(elem).offset().top - $(window).scrollTop() < $(elem).height() ;}

之后,一旦元素像这样进入视图,您就可以触发任何您想要的东西

$(window).scroll(function(){if (isInView($('.classOfDivToCheck')))//fire whatever you whatdothis();})

这对我来说还不错

这里有一个方法可以实现同样的事情使用Moools,水平,垂直或两者兼而有之。

Element.implement({inVerticalView: function (full) {if (typeOf(full) === "null") {full = true;}
if (this.getStyle('display') === 'none') {return false;}
// Window Size and Scrollvar windowScroll = window.getScroll();var windowSize = window.getSize();// Element Size and Scrollvar elementPosition = this.getPosition();var elementSize = this.getSize();
// Calculation Variablesvar docViewTop = windowScroll.y;var docViewBottom = docViewTop + windowSize.y;var elemTop = elementPosition.y;var elemBottom = elemTop + elementSize.y;
if (full) {return ((elemBottom >= docViewTop) && (elemTop <= docViewBottom)&& (elemBottom <= docViewBottom) && (elemTop >= docViewTop) );} else {return ((elemBottom <= docViewBottom) && (elemTop >= docViewTop));}},inHorizontalView: function(full) {if (typeOf(full) === "null") {full = true;}
if (this.getStyle('display') === 'none') {return false;}
// Window Size and Scrollvar windowScroll = window.getScroll();var windowSize = window.getSize();// Element Size and Scrollvar elementPosition = this.getPosition();var elementSize = this.getSize();
// Calculation Variablesvar docViewLeft = windowScroll.x;var docViewRight = docViewLeft + windowSize.x;var elemLeft = elementPosition.x;var elemRight = elemLeft + elementSize.x;
if (full) {return ((elemRight >= docViewLeft) && (elemLeft <= docViewRight)&& (elemRight <= docViewRight) && (elemLeft >= docViewLeft) );} else {return ((elemRight <= docViewRight) && (elemLeft >= docViewLeft));}},inView: function(full) {return this.inHorizontalView(full) && this.inVerticalView(full);}});

如果元素的任何部分在页面上可见,此方法将返回true。它在我的情况下效果更好,可能会帮助其他人。

function isOnScreen(element) {var elementOffsetTop = element.offset().top;var elementHeight = element.height();
var screenScrollTop = $(window).scrollTop();var screenHeight = $(window).height();
var scrollIsAboveElement = elementOffsetTop + elementHeight - screenScrollTop >= 0;var elementIsVisibleOnScreen = screenScrollTop + screenHeight - elementOffsetTop >= 0;
return scrollIsAboveElement && elementIsVisibleOnScreen;}

可滚动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,这将不起作用。

这会考虑元素具有的任何填充、边框或边距以及大于视口本身的元素。

function inViewport($ele) {var lBound = $(window).scrollTop(),uBound = lBound + $(window).height(),top = $ele.offset().top,bottom = top + $ele.outerHeight(true);
return (top > lBound && top < uBound)|| (bottom > lBound && bottom < uBound)|| (lBound >= top && lBound <= bottom)|| (uBound >= top && uBound <= bottom);}

要调用它,请使用这样的内容:

var $myElement = $('#my-element'),canUserSeeIt = inViewport($myElement);
console.log(canUserSeeIt); // true, if element is visible; false otherwise

我改编了这个简短的jQuery函数扩展,您可以随意使用(MIT许可证)。

/*** returns true if an element is visible, with decent performance* @param [scope] scope of the render-window instance; default: window* @returns {boolean}*/jQuery.fn.isOnScreen = function(scope){var element = this;if(!element){return;}var target = $(element);if(target.is(':visible') == false){return false;}scope = $(scope || window);var top = scope.scrollTop();var bot = top + scope.height();var elTop = target.offset().top;var elBot = elTop + target.height();
return ((elBot <= bot) && (elTop >= top));};

我更喜欢使用jQuery exr

jQuery.extend(jQuery.expr[':'], {inview: function (elem) {var t = $(elem);var offset = t.offset();var win = $(window);var winST = win.scrollTop();var elHeight = t.outerHeight(true);
if ( offset.top > winST - elHeight && offset.top < winST + elHeight + win.height()) {return true;}return false;}});

所以你可以这样使用它

$(".my-elem:inview"); //returns only element that is in view$(".my-elem").is(":inview"); //check if element is in view$(".my-elem:inview").length; //check how many elements are in view

您可以轻松地在scroll事件函数等中添加此类代码,以便每次用户滚动视图时检查它。

您可以使用jQuery插件“onScreen”来检查滚动时元素是否在当前视口中。当选择器出现在屏幕上时,插件将选择器的“: onScreen”设置为true。这是您可以包含在项目中的插件的链接。"http://benpickles.github.io/onScreen/jquery.onscreen.min.js"

你可以试试下面的例子,这对我很有效。

$(document).scroll(function() {if($("#div2").is(':onScreen')) {console.log("Element appeared on Screen");//do all your stuffs here when element is visible.}else {console.log("Element not on Screen");//do all your stuffs here when element is not visible.}});

超文本标记语言代码:

<div id="div1" style="width: 400px; height: 1000px; padding-top: 20px; position: relative; top: 45px"></div> <br><hr /> <br><div id="div2" style="width: 400px; height: 200px"></div>

css:

#div1 {background-color: red;}#div2 {background-color: green;}

我为任务编写了一个组件,旨在处理大量元素非常快(对于1000个元素在慢速移动,<10ms)。

它适用于您可以访问的每种类型的滚动容器-窗口,超文本标记语言元素,嵌入式ifram,生成的子窗口-并且在检测到的内容(全部或部分可见性边框或内容框,自定义公差区)方面非常灵活。

一个巨大的,大部分是自动生成的测试套件确保它像广告一样工作,跨浏览器

如果你喜欢,就试一试:jQuery.isInView。否则,你可能会在源代码中找到灵感,例如这里

一个基于这个答案的示例,用于检查元素是否有75%可见(即不到25%的元素不在屏幕上)。

function isScrolledIntoView(el) {// check for 75% visiblevar percentVisible = 0.75;var elemTop = el.getBoundingClientRect().top;var elemBottom = el.getBoundingClientRect().bottom;var elemHeight = el.getBoundingClientRect().height;var overhang = elemHeight * (1 - percentVisible);
var isVisible = (elemTop >= -overhang) && (elemBottom <= window.innerHeight + overhang);return isVisible;}

唯一对我来说一直有效的插件是:https://github.com/customd/jquery-visible

我最近将此插件移植到GWT,因为我不想仅仅为了使用该插件而添加jQuery作为依赖项。这是我的(简单)端口(只是包括我用例所需的功能):

public static boolean isVisible(Element e){//vp = viewPort, b = bottom, l = left, t = top, r = rightint vpWidth   = Window.getClientWidth();int vpHeight = Window.getClientHeight();

boolean tViz = ( e.getAbsoluteTop() >= 0 && e.getAbsoluteTop()<  vpHeight);boolean bViz = (e.getAbsoluteBottom() >  0 && e.getAbsoluteBottom() <= vpHeight);boolean lViz = (e.getAbsoluteLeft() >= 0 && e.getAbsoluteLeft() < vpWidth);boolean rViz = (e.getAbsoluteRight()  >  0 && e.getAbsoluteRight()  <= vpWidth);
boolean vVisible   = tViz && bViz;boolean hVisible   = lViz && rViz;
return hVisible && vVisible;}

检查元素是否完全在屏幕上,而不是接受的答案的方法来检查div是否完全在屏幕上(如果div比屏幕大,这将不起作用)。在纯Javascript中:

/*** Checks if element is on the screen (Y axis only), returning true* even if the element is only partially on screen.** @param element* @returns {boolean}*/function isOnScreenY(element) {var screen_top_position = window.scrollY;var screen_bottom_position = screen_top_position + window.innerHeight;
var element_top_position = element.offsetTop;var element_bottom_position = element_top_position + element.offsetHeight;
return (inRange(element_top_position, screen_top_position, screen_bottom_position)|| inRange(element_bottom_position, screen_top_position, screen_bottom_position));}
/*** Checks if x is in range (in-between) the* value of a and b (in that order). Also returns true* if equal to either value.** @param x* @param a* @param b* @returns {boolean}*/function inRange(x, a, b) {return (x >= a && x <= b);}

我正在寻找一种方法来查看该元素是否会很快进入视野,因此通过扩展上面的片段,我设法做到了这一点

elm=是您要检查的元素在视图中

scrollElement=您可以传递窗口或具有滚动的父元素

偏移=如果您希望它在元素在屏幕中之前200px离开时触发,则传递200

function isScrolledIntoView(elem, scrollElement, offset){var $elem = $(elem);var $window = $(scrollElement);var docViewTop = $window.scrollTop();var docViewBottom = docViewTop + $window.height();var elemTop = $elem.offset().top;var elemBottom = elemTop + $elem.height();            
return (((elemBottom+offset) >= docViewBottom) && ((elemTop-offset) <= docViewTop)) || (((elemBottom-offset) <= docViewBottom) && ((elemTop+offset) >= docViewTop));}

做了一个简单的插件,检测元素是否在可滚动容器中可见

    $.fn.isVisible = function(){
var win;if(!arguments[0]){console.error('Specify a target;');return false;}else{win = $(arguments[0]);}var viewport = {};var bounds = this.offset();bounds.right = bounds.left + this.outerWidth();bounds.bottom = bounds.top + this.outerHeight();viewport.bottom = win.height() + win.offset().top;return (!( bounds.top > viewport.bottom) && (win.offset().top < bounds.bottom));};

像这样叫它$('elem_to_check').isVisible('scrollable_container');

希望会有帮助。

这里的大多数答案都没有考虑到一个元素也可以被隐藏,因为它被滚动到div的视图之外,而不仅仅是整个页面。

为了覆盖这种可能性,您基本上必须检查元素是否位于其每个父元素的边界内。

这个解决方案正是这样做的:

function(element, percentX, percentY){var tolerance = 0.01;   //needed because the rects returned by getBoundingClientRect provide the position up to 10 decimalsif(percentX == null){percentX = 100;}if(percentY == null){percentY = 100;}
var elementRect = element.getBoundingClientRect();var parentRects = [];
while(element.parentElement != null){parentRects.push(element.parentElement.getBoundingClientRect());element = element.parentElement;}
var visibleInAllParents = parentRects.every(function(parentRect){var visiblePixelX = Math.min(elementRect.right, parentRect.right) - Math.max(elementRect.left, parentRect.left);var visiblePixelY = Math.min(elementRect.bottom, parentRect.bottom) - Math.max(elementRect.top, parentRect.top);var visiblePercentageX = visiblePixelX / elementRect.width * 100;var visiblePercentageY = visiblePixelY / elementRect.height * 100;return visiblePercentageX + tolerance > percentX && visiblePercentageY + tolerance > percentY;});return visibleInAllParents;};

它还允许您指定在每个方向上可见的百分比。
它不包括由于其他因素而隐藏的可能性,例如display: hidden

这应该适用于所有主流浏览器,因为它只使用#0。我个人在Chrome和Internet Explorer 11中测试过它。

这个问题有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 or元素的底部位置是:

var element_bottom_position = element_top_position + element.clientHeight;

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

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

从那里,您可以执行逻辑以在元素上添加或删除in-view类,然后您可以稍后在CSS中使用转换效果来处理。

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

纯香草检查元素(el)是否在可滚动div(holder)中可见

function isElementVisible (el, holder) {holder = holder || document.bodyconst { top, bottom, height } = el.getBoundingClientRect()const holderRect = holder.getBoundingClientRect()
return top <= holderRect.top? holderRect.top - top <= height: bottom - holderRect.bottom <= height}

使用jQuery:

var el = $('tr:last').get(0);var holder = $('table').get(0);var isVisible = isScrolledIntoView(el, holder);

基于这个伟大的答案,您可以使用ES2015+进一步简化它:

function isScrolledIntoView(el) {const { top, bottom } = el.getBoundingClientRect()return top >= 0 && bottom <= window.innerHeight}

如果你不关心顶部从窗口出来,只关心底部已经被查看过,这可以简化为

function isSeen(el) {return el.getBoundingClientRect().bottom <= window.innerHeight}

甚至是一句话

const isSeen = el => el.getBoundingClientRect().bottom <= window.innerHeight

仅限Javascript:)

function isInViewport(element) {var rect = element.getBoundingClientRect();var html = document.documentElement;return (rect.top >= 0 &&rect.left >= 0 &&rect.bottom <= (window.innerHeight || html.clientHeight) &&rect.right <= (window.innerWidth || html.clientWidth));}

使用交叉点观察者 API

(在现代浏览器中原生)


通过使用观察员,可以轻松有效地确定元素是否在视口或任何可滚动容器中可见。

无需附加scroll事件并手动检查事件回调,效率更高:

// define an observer instancevar observer = new IntersectionObserver(onIntersection, {root: null,   // default is the viewportthreshold: .5 // percentage of target's visible area. Triggers "onIntersection"})
// callback is called on intersection changefunction onIntersection(entries, opts){entries.forEach(entry =>entry.target.classList.toggle('visible', entry.isIntersecting))}
// Use the observer to observe an elementobserver.observe( document.querySelector('.box') )
// To stop observing:// observer.unobserve(entry.target)
span{ position:fixed; top:0; left:0; }.box{ width:100px; height:100px; background:red; margin:1000px; transition:.75s; }.box.visible{ background:green; border-radius:50%; }
<span>Scroll both Vertically &amp; Horizontally...</span><div class='box'></div>


现代浏览器支持,包括移动浏览器。IE不支持-查看浏览器支持表

在徒劳地运行并使用了几个不起作用的代码之后。这就是我使用JQuery在垂直滚动可见性方面起作用的原因。用你想垂直跟踪的元素回复“#foterplace”。

jQuery.expr.filters.offscreen = function(el) {var rect = el.getBoundingClientRect();console.log(rect)console.log('window height', $(window).height());
return ((rect.top <= $(window).height()) && (rect.bottom <= $(window).height()));};$(document).scroll(function(){if ($('#footerplace').is(':offscreen')){console.log('this is true');$('#footerplace').is(':offscreen');} else {console.log('this is false');$('#footerplace').is(':offscreen');
}

这个答案的更有效版本:

 /*** Is element within visible region of a scrollable container* @param {HTMLElement} el - element to test* @returns {boolean} true if within visible region, otherwise false*/function isScrolledIntoView(el) {var rect = el.getBoundingClientRect();return (rect.top >= 0) && (rect.bottom <= window.innerHeight);}

我们可以使用ES6在现代浏览器中做这样的事情:

const isFullySeen = el => el &&typeof el.getBoundingClientRect === 'function' &&el.getBoundingClientRect()['bottom'] + window.scrollY <=window.innerHeight + window.scrollY &&el.getBoundingClientRect()['top'] + window.scrollY <=window.innerHeight + window.scrollY;

我找到的最简单的解决方案是交叉点观察者API

var observer = new IntersectionObserver(function(entries) {if(entries[0].isIntersecting === true)console.log('Element has just become visible in screen');}, { threshold: [0] });
observer.observe(document.querySelector("#main-container"));

jQuery scroll间谍插件将允许您轻松完成此操作。https://github.com/thesmart/jquery-scrollspy

$('.tile').on('scrollSpy:enter', function() {console.log('enter:', $(this).attr('id'));});
$('.tile').on('scrollSpy:exit', function() {console.log('exit:', $(this).attr('id'));});
$('.tile').scrollSpy();

我添加了我的代码改造。不幸的是,我可以看到每个人都在他们的版本中,每个人都省略了债务函数的使用。哪个答案是让你的事件不触发,例如,滚动时每秒200次。

$(window).scroll(function(){if (isInView($('.class'))){debounce(someFunction(), 5)}});function isInView(elem){if(document.documentElement.clientWidth > 991){return $(elem).offset().top - $(window).scrollTop() < $(elem).height();}else {doSometing;}}

对我有效的唯一解决方案是(当$(“#elementToCheck”)可见时返回true):

$(文档). scrollTop()+window.innerHeight+$("#elementToCheck")

打字稿

  private readonly isElementInViewPort = (el: HTMLElement): boolean => {const rect = el.getBoundingClientRect();const elementTop = rect.top;const elementBottom = rect.bottom;const scrollPosition = el?.scrollTop || document.body.scrollTop;return (elementBottom >= 0 &&elementTop <= document.documentElement.clientHeight &&elementTop + rect.height > elementTop &&elementTop <= elementBottom &&elementTop >= scrollPosition);

};

Javascript代码可以写成:

window.addEventListener('scroll', function() {var element = document.querySelector('#main-container');var position = element.getBoundingClientRect();
// checking whether fully visibleif(position.top >= 0 && position.bottom <= window.innerHeight) {console.log('Element is fully visible in screen');}
// checking for partial visibilityif(position.top < window.innerHeight && position.bottom >= 0) {console.log('Element is partially visible in screen');}});

在React js中写成:

    componentDidMount() {window.addEventListener('scroll', this.isScrolledIntoView);}
componentWillUnmount() {window.removeEventListener('scroll', this.isScrolledIntoView);}  
isScrolledIntoView() {var element = document.querySelector('.element');var position = element.getBoundingClientRect();
// checking whether fully visibleif (position.top >= 0 && position.bottom <= window.innerHeight) {console.log('Element is fully visible in screen');}// checking for partial visibilityif (position.top < window.innerHeight && position.bottom >= 0) {console.log('Element is partially visible in screen');}}

其他答案通常不会检查元素是否沿着X轴处于视图中,即可能在当前视口Y范围内,但超出X范围。如果项目的任何部分显示在视口中,此函数会检查X和Y:

function checkElInView(el) {if (!el || !typeof el.getBoundingClientRect === "function") return false;const r = el.getBoundingClientRect();const vw = document.documentElement.clientWidth;const vh = document.documentElement.clientHeight;const inViewX = (r.left > 0 && r.left < vw) || (r.right < vw && r.right > 0);const inViewY = (r.top > 0 && r.top < vh) || (r.bottom < vh && r.bottom > 0);return inViewX && inViewY;}