如何告诉我们,如果一个DOM元是可见在目前的视?
-
02-07-2019 - |
题
是否有一个有效的方式来告诉我们,如果一个DOM元(HTML文档中)是目前可见(将出现在 视)?
(该问题是指火狐)
解决方案
更新:时间推移,我们的浏览器也是如此。 不再推荐使用此技术,您应该使用下面的@ Dan解决方案( https://stackoverflow.com/ a / 7557433/5628 )如果您不需要支持IE <!> lt; 7.
原始解决方案(现已过时):
这将检查元素在当前视口中是否完全可见:
function elementInViewport(el) {
var top = el.offsetTop;
var left = el.offsetLeft;
var width = el.offsetWidth;
var height = el.offsetHeight;
while(el.offsetParent) {
el = el.offsetParent;
top += el.offsetTop;
left += el.offsetLeft;
}
return (
top >= window.pageYOffset &&
left >= window.pageXOffset &&
(top + height) <= (window.pageYOffset + window.innerHeight) &&
(left + width) <= (window.pageXOffset + window.innerWidth)
);
}
您可以简单地修改它以确定元素的任何部分是否在视口中可见:
function elementInViewport2(el) {
var top = el.offsetTop;
var left = el.offsetLeft;
var width = el.offsetWidth;
var height = el.offsetHeight;
while(el.offsetParent) {
el = el.offsetParent;
top += el.offsetTop;
left += el.offsetLeft;
}
return (
top < (window.pageYOffset + window.innerHeight) &&
left < (window.pageXOffset + window.innerWidth) &&
(top + height) > window.pageYOffset &&
(left + width) > window.pageXOffset
);
}
其他提示
现在 大多数的浏览器 支持 getBoundingClientRect 方法,这已成为最佳做法。使用旧的答案是 非常慢, 不准确的 和 有几个错误.
该解决方案选定的作为是正确的 几乎从来没有精确的.你可以 阅读更多 关于其错误。
这个解决方案进行测试IE7+,iOS5+野生动物园,Android2+、黑莓、歌剧的移动,即移动 10.
function isElementInViewport (el) {
//special bonus for those using jQuery
if (typeof jQuery === "function" && el instanceof jQuery) {
el = el[0];
}
var rect = el.getBoundingClientRect();
return (
rect.top >= 0 &&
rect.left >= 0 &&
rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) && /*or $(window).height() */
rect.right <= (window.innerWidth || document.documentElement.clientWidth) /*or $(window).width() */
);
}
如何使用:
你可以确信的功能给予上述返回正确答案的时刻的时候,它是所谓,但是,关于跟踪元的可见度作为一个事件?
将以下代码放在底部的 <body>
标签:
function onVisibilityChange(el, callback) {
var old_visible;
return function () {
var visible = isElementInViewport(el);
if (visible != old_visible) {
old_visible = visible;
if (typeof callback == 'function') {
callback();
}
}
}
}
var handler = onVisibilityChange(el, function() {
/* your code go here */
});
//jQuery
$(window).on('DOMContentLoaded load resize scroll', handler);
/* //non-jQuery
if (window.addEventListener) {
addEventListener('DOMContentLoaded', handler, false);
addEventListener('load', handler, false);
addEventListener('scroll', handler, false);
addEventListener('resize', handler, false);
} else if (window.attachEvent) {
attachEvent('onDOMContentLoaded', handler); // IE9+ :(
attachEvent('onload', handler);
attachEvent('onscroll', handler);
attachEvent('onresize', handler);
}
*/
如果你做任何DOM修改,它们可以改变你的元件的可见性的课程。
指导方针和共同缺陷:
也许你需要跟踪页焦/移动设备捏? jQuery应该处理 焦/捏 跨浏览器,否则 第一 或 第二 链接,应该帮助你。
如果你 修改DOM, 它可以影响元的可见性。你应该把控制权,并呼叫 handler()
手动。不幸的是,我们没有交的浏览器 onrepaint
事件。另一方面,允许我们作出的优化,和执行重新检查只有在DOM修改,可以改变元件的能见度。
永远不会 使用它的内部jQuery $(文件)。准备() 只因为 没有担保CSS已经应用 在这一时刻。你的代码可以在本地工作与你CSS硬盘驱动器上,但是一旦穿上远程服务器就会失败。
后 DOMContentLoaded
被解雇了, 样式应用, 但 图像是装不呢.因此,我们应该加入 window.onload
事件的听众。
我们不能赶上缩小/捏事件。
最后手段可能是下列代码:
/* TODO: this looks like a very bad code */
setInterval(handler, 600);
你可以用真棒功能 pageVisibiliy HTML5API如果你关心,如果该标签与网页是活动和可见的。
TODO:这种方法不处理两种情况:
- 重叠的使用
z-index
使用
overflow-scroll
在元件的容器尝试新的东西 https://pawelgrzybek.com/the-intersection-observer-api-explained/
更新
在现代浏览器,你可能会想看看的 交观察员API 它提供了以下福利:
- 更好的性能比听滚动事件
- 工作交叉域内部框架
- 可以告诉我们,如果一个元件是阻碍/交叉另一个
交观察员正在路上被一个全面的标准和已经支持在铬51+、边缘15+和Firefox55岁以上和正在发展为野生动物园。还有一个 提供填充代码 可用。
先前的答案
有一些问题 答复提供的Dan 这可能会使它不适合的办法对于一些情况。这些问题中的一些指出在他的回答近底,他的代码会给假阳性元素是:
- 另一个元件是在前一个正在测试
- 外部可见的地区的父母或祖先元素
- 一个元素或其子隐藏的通过使用CSS
clip
酒店
这些局限性表明在下列结果中的一个 简单的测试:
该解决方案: isElementVisible()
这里有一个解决这些问题,与所测试的结果下面,一个解释的一些零部件的编码。
function isElementVisible(el) {
var rect = el.getBoundingClientRect(),
vWidth = window.innerWidth || doc.documentElement.clientWidth,
vHeight = window.innerHeight || doc.documentElement.clientHeight,
efp = function (x, y) { return document.elementFromPoint(x, y) };
// Return false if it's not in the viewport
if (rect.right < 0 || rect.bottom < 0
|| rect.left > vWidth || rect.top > vHeight)
return false;
// Return true if any of its four corners are visible
return (
el.contains(efp(rect.left, rect.top))
|| el.contains(efp(rect.right, rect.top))
|| el.contains(efp(rect.right, rect.bottom))
|| el.contains(efp(rect.left, rect.bottom))
);
}
并的结果:
附加说明
这种方法不是没有它自己的局限性,但是。例如,一个元素正在测试一下z指数比另一种元素的同位将被确定为隐藏甚至如果元素在前实际上并没有隐藏任何它的一部分。仍然,这种方法有其用途在某些情况下,丹的解决方案不复盖。
既 element.getBoundingClientRect()
和 document.elementFromPoint()
是的一部分CSSOM工作的规范草案,并支持在至少即6和后 大多数 桌面浏览器很长一段时间(尽管不是完全).看看 Quirksmode在这些功能 更多的信息。
contains()
是用来看看如果元素返回的 document.elementFromPoint()
是一个儿童节点的元素,我们正在测试为可见性。它还回真的如果这件返回是一样的元素。这只是使得检查更加坚固。它支持在所有主要的浏览器、火狐9.0是他们最后来加入它。老年Firefox的支持,检查这个答案的历史。
如果你想测试更点周围的元素可见性―即使确定的元素不涵盖通过多,说,50%的―它不会需要很多调整的最后答案的一部分。但是,要知道,它可能会非常缓慢的,如果你检查了每一像素,以确保它是100%可见。
我尝试 Dan的回答 然而用于确定边界的代数意味着该元素必须同时<!># 8804;视口大小并完全在视口内部获取true
,容易导致漏报。如果要确定元素是否在视口中, ryanve的答案已关闭,但正在测试的元素应与视口重叠,请尝试以下操作:
function isElementInViewport(el) {
var rect = el.getBoundingClientRect();
return rect.bottom > 0 &&
rect.right > 0 &&
rect.left < (window.innerWidth || document.documentElement.clientWidth) /* or $(window).width() */ &&
rect.top < (window.innerHeight || document.documentElement.clientHeight) /* or $(window).height() */;
}
作为公共服务:
Dan的回答是正确的计算(元素可以是<!> gt;窗口,特别是在手机屏幕上),正确的jQuery测试,以及添加isElementPartiallyInViewport:
顺便说一句,window.innerWidth和document.documentElement.clientWidth之间的差异就是clientWidth / clientHeight不包括滚动条,而window.innerWidth / Height则包含滚动条。
function isElementPartiallyInViewport(el)
{
//special bonus for those using jQuery
if (typeof jQuery !== 'undefined' && el instanceof jQuery) el = el[0];
var rect = el.getBoundingClientRect();
// DOMRect { x: 8, y: 8, width: 100, height: 100, top: 8, right: 108, bottom: 108, left: 8 }
var windowHeight = (window.innerHeight || document.documentElement.clientHeight);
var windowWidth = (window.innerWidth || document.documentElement.clientWidth);
// http://stackoverflow.com/questions/325933/determine-whether-two-date-ranges-overlap
var vertInView = (rect.top <= windowHeight) && ((rect.top + rect.height) >= 0);
var horInView = (rect.left <= windowWidth) && ((rect.left + rect.width) >= 0);
return (vertInView && horInView);
}
// http://stackoverflow.com/questions/123999/how-to-tell-if-a-dom-element-is-visible-in-the-current-viewport
function isElementInViewport (el)
{
//special bonus for those using jQuery
if (typeof jQuery !== 'undefined' && el instanceof jQuery) el = el[0];
var rect = el.getBoundingClientRect();
var windowHeight = (window.innerHeight || document.documentElement.clientHeight);
var windowWidth = (window.innerWidth || document.documentElement.clientWidth);
return (
(rect.left >= 0)
&& (rect.top >= 0)
&& ((rect.left + rect.width) <= windowWidth)
&& ((rect.top + rect.height) <= windowHeight)
);
}
function fnIsVis(ele)
{
var inVpFull = isElementInViewport(ele);
var inVpPartial = isElementPartiallyInViewport(ele);
console.clear();
console.log("Fully in viewport: " + inVpFull);
console.log("Partially in viewport: " + inVpPartial);
}
试验情况下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="">
<meta name="author" content="">
<title>Test</title>
<!--
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<script src="scrollMonitor.js"></script>
-->
<script type="text/javascript">
function isElementPartiallyInViewport(el)
{
//special bonus for those using jQuery
if (typeof jQuery !== 'undefined' && el instanceof jQuery) el = el[0];
var rect = el.getBoundingClientRect();
// DOMRect { x: 8, y: 8, width: 100, height: 100, top: 8, right: 108, bottom: 108, left: 8 }
var windowHeight = (window.innerHeight || document.documentElement.clientHeight);
var windowWidth = (window.innerWidth || document.documentElement.clientWidth);
// http://stackoverflow.com/questions/325933/determine-whether-two-date-ranges-overlap
var vertInView = (rect.top <= windowHeight) && ((rect.top + rect.height) >= 0);
var horInView = (rect.left <= windowWidth) && ((rect.left + rect.width) >= 0);
return (vertInView && horInView);
}
// http://stackoverflow.com/questions/123999/how-to-tell-if-a-dom-element-is-visible-in-the-current-viewport
function isElementInViewport (el)
{
//special bonus for those using jQuery
if (typeof jQuery !== 'undefined' && el instanceof jQuery) el = el[0];
var rect = el.getBoundingClientRect();
var windowHeight = (window.innerHeight || document.documentElement.clientHeight);
var windowWidth = (window.innerWidth || document.documentElement.clientWidth);
return (
(rect.left >= 0)
&& (rect.top >= 0)
&& ((rect.left + rect.width) <= windowWidth)
&& ((rect.top + rect.height) <= windowHeight)
);
}
function fnIsVis(ele)
{
var inVpFull = isElementInViewport(ele);
var inVpPartial = isElementPartiallyInViewport(ele);
console.clear();
console.log("Fully in viewport: " + inVpFull);
console.log("Partially in viewport: " + inVpPartial);
}
// var scrollLeft = (window.pageXOffset !== undefined) ? window.pageXOffset : (document.documentElement || document.body.parentNode || document.body).scrollLeft,
// var scrollTop = (window.pageYOffset !== undefined) ? window.pageYOffset : (document.documentElement || document.body.parentNode || document.body).scrollTop;
</script>
</head>
<body>
<div style="display: block; width: 2000px; height: 10000px; background-color: green;">
<br /><br /><br /><br /><br /><br />
<br /><br /><br /><br /><br /><br />
<br /><br /><br /><br /><br /><br />
<input type="button" onclick="fnIsVis(document.getElementById('myele'));" value="det" />
<br /><br /><br /><br /><br /><br />
<br /><br /><br /><br /><br /><br />
<br /><br /><br /><br /><br /><br />
<div style="background-color: crimson; display: inline-block; width: 800px; height: 500px;" ></div>
<div id="myele" onclick="fnIsVis(this);" style="display: inline-block; width: 100px; height: 100px; background-color: hotpink;">
t
</div>
<br /><br /><br /><br /><br /><br />
<br /><br /><br /><br /><br /><br />
<br /><br /><br /><br /><br /><br />
<input type="button" onclick="fnIsVis(document.getElementById('myele'));" value="det" />
</div>
<!--
<script type="text/javascript">
var element = document.getElementById("myele");
var watcher = scrollMonitor.create( element );
watcher.lock();
watcher.stateChange(function() {
console.log("state changed");
// $(element).toggleClass('fixed', this.isAboveViewport)
});
</script>
-->
</body>
</html>
有一个名为 inview 的jQuery插件做的工作
请参阅边缘的来源,其中使用 getBoundingClientRect 。就像:
function inViewport (el) {
var r, html;
if ( !el || 1 !== el.nodeType ) { return false; }
html = document.documentElement;
r = el.getBoundingClientRect();
return ( !!r
&& r.bottom >= 0
&& r.right >= 0
&& r.top <= html.clientHeight
&& r.left <= html.clientWidth
);
}
如果元素的任何部分位于视口中,则返回true
。
我更短更快的版本。
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/
我发现很麻烦,因为没有jQuery
中心版本的功能可用。当我遇到 Dan的解决方案时,我发现有机会为那些喜欢以<=> OO风格编程的人提供一些东西。请务必向上滚动并在Dan的代码上保留一个upvote。它漂亮而活泼,对我来说就像是一种魅力。
bada bing bada boom
$.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
//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
}
});
我发现这里接受的答案对于大多数用例而言过于复杂。此代码可以很好地完成工作(使用JQuery),并区分完全可见和部分可见的元素。
var element = $("#element");
var topOfElement = element.offset().top;
var bottomOfElement = element.offset().top + element.outerHeight(true);
var $window = $(window);
$window.bind('scroll', function() {
var scrollTopPosition = $window.scrollTop()+$window.height();
var windowScrollTop = $window.scrollTop()
if( windowScrollTop > topOfElement && windowScrollTop < bottomOfElement) {
// Element is partially visible (above viewable area)
console.log("Element is partially visible (above viewable area)");
}else if( windowScrollTop > bottomOfElement && windowScrollTop > topOfElement ) {
// Element is hidden (above viewable area)
console.log("Element is hidden (above viewable area)");
}else if( scrollTopPosition < topOfElement && scrollTopPosition < bottomOfElement ) {
// Element is hidden (below viewable area)
console.log("Element is hidden (below viewable area)");
}else if( scrollTopPosition < bottomOfElement && scrollTopPosition > topOfElement ) {
// Element is partially visible (below viewable area)
console.log("Element is partially visible (below viewable area)");
}else{
// Element is completely visible
console.log("Element is completely visible");
}
});
我在这里遇到的所有答案只检查元素是否位于当前视口内。但并不意味着它是可见的。
如果给定元素位于具有溢出内容的div内,并且它被滚动到视图之外怎么办?
要解决这个问题,您必须检查所有父母是否包含该元素 我的解决方案就是这样做的:
它还允许您指定要显示的元素数量。
Element.prototype.isVisible = function(percentX, percentY){
var tolerance = 0.01; //needed because the rects returned by getBoundingClientRect provide the position up to 10 decimals
if(percentX == null){
percentX = 100;
}
if(percentY == null){
percentY = 100;
}
var elementRect = this.getBoundingClientRect();
var parentRects = [];
var element = this;
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;
};
此解决方案忽略了由于其他事实而导致元素可能不可见的事实,例如opacity: 0
。
我已在Chrome和Internet Explorer 11中测试过此解决方案。
新的 Intersection Observer API 非常适合这个问题直接
这个解决方案需要一个polyfill作为Safari,Opera和IE还不支持这个。 (polyfill包含在解决方案中)。
在此解决方案中,有一个视图中的框是目标(观察到的)。当它进入视图时,标题顶部的按钮被隐藏。一旦框离开视图,就会显示。
const buttonToHide = document.querySelector('button');
const hideWhenBoxInView = new IntersectionObserver((entries) => {
if (entries[0].intersectionRatio <= 0) { // If not in view
buttonToHide.style.display = "inherit";
} else {
buttonToHide.style.display = "none";
}
});
hideWhenBoxInView.observe(document.getElementById('box'));
header {
position: fixed;
top: 0;
width: 100vw;
height: 30px;
background-color: lightgreen;
}
.wrapper {
position: relative;
margin-top: 600px;
}
#box {
position: relative;
left: 175px;
width: 150px;
height: 135px;
background-color: lightblue;
border: 2px solid;
}
<script src="https://polyfill.io/v2/polyfill.min.js?features=IntersectionObserver"></script>
<header>
<button>NAVIGATION BUTTON TO HIDE</button>
</header>
<div class="wrapper">
<div id="box">
</div>
</div>
我认为这是一种更实用的方法。 Dan的答案在递归上下文中不起作用。
当你的元素在其他人可滚动的div中时,通过以递归方式测试HTML标记的任何级别来解决问题,并在第一个false中停止。
/**
* fullVisible=true only returns true if the all object rect is visible
*/
function isReallyVisible(el, fullVisible) {
if ( el.tagName == "HTML" )
return true;
var parentRect=el.parentNode.getBoundingClientRect();
var rect = arguments[2] || el.getBoundingClientRect();
return (
( fullVisible ? rect.top >= parentRect.top : rect.bottom > parentRect.top ) &&
( fullVisible ? rect.left >= parentRect.left : rect.right > parentRect.left ) &&
( fullVisible ? rect.bottom <= parentRect.bottom : rect.top < parentRect.bottom ) &&
( fullVisible ? rect.right <= parentRect.right : rect.left < parentRect.right ) &&
isReallyVisible(el.parentNode, fullVisible, rect)
);
};
基于@ dan的上述解决方案( https://stackoverflow.com/a/7557433/5628 ),我有一个清理实现,以便在同一页面上多次使用它更容易:
$(function() {
$(window).on('load resize scroll', function() {
addClassToElementInViewport($('.bug-icon'), 'animate-bug-icon');
addClassToElementInViewport($('.another-thing'), 'animate-thing');
// 👏 repeat as needed ...
});
function addClassToElementInViewport(element, newClass) {
if (inViewport(element)) {
element.addClass(newClass);
}
}
function inViewport(element) {
if (typeof jQuery === "function" && element instanceof jQuery) {
element = element[0];
}
var elementBounds = element.getBoundingClientRect();
return (
elementBounds.top >= 0 &&
elementBounds.left >= 0 &&
elementBounds.bottom <= $(window).height() &&
elementBounds.right <= $(window).width()
);
}
});
我使用它的方式是当元素滚动到视图中时,我添加了一个触发css关键帧动画的类。它非常简单,当您在页面上有条件地设置动画时,可以使用10多个内容。
希望它有所帮助!
这是我的解决方案,如果元素隐藏在可滚动容器中,它将起作用。
这是一个演示(尝试重新调整窗口大小)
var visibleY = function(el){
var top = el.getBoundingClientRect().top, rect, el = el.parentNode;
do {
rect = el.getBoundingClientRect();
if (top <= rect.bottom === false)
return false;
el = el.parentNode;
} while (el != document.body);
// Check its within the document viewport
return top <= document.documentElement.clientHeight;
};
我只需要检查它是否在Y轴上可见(对于滚动ajax加载更多记录功能)。
对我有用的简单小巧的解决方案。
示例您想要查看元素在具有溢出滚动的父元素中是否可见。
$(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');
}
})
更好的解决方案:
function getViewportSize(w) {
var w = w || window;
if(w.innerWidth != null) return {w:w.innerWidth, h:w.innerHeight};
var d = w.document;
if (document.compatMode == "CSS1Compat") {
return {
w: d.documentElement.clientWidth,
h: d.documentElement.clientHeight
};
}
return { w: d.body.clientWidth, h: d.body.clientWidth };
}
function isViewportVisible(e) {
var box = e.getBoundingClientRect();
var height = box.height || (box.bottom - box.top);
var width = box.width || (box.right - box.left);
var viewport = getViewportSize();
if(!height || !width) return false;
if(box.top > viewport.h || box.bottom < 0) return false;
if(box.right < 0 || box.left > viewport.w) return false;
return true;
}
检查元素是否至少部分在视图中(垂直尺寸):
function inView(element) {
var box = element.getBoundingClientRect();
return inViewBox(box);
}
function inViewBox(box) {
return ((box.bottom < 0) || (box.top > getWindowSize().h)) ? false : true;
}
function getWindowSize() {
return { w: document.body.offsetWidth || document.documentElement.offsetWidth || window.innerWidth, h: document.body.offsetHeight || document.documentElement.offsetHeight || window.innerHeight}
}
我有同样的问题,并通过使用getBoundingClientRect()来计算出来。此代码完全是“通用的”,只需编写一次即可使用(您不必为要知道的每个元素在视口中写出来)。此代码仅检查视口中是否垂直非水平。在这种情况下,变量(数组)'elements'保存您在视口中垂直检查的所有元素,因此在任何地方抓取您想要的任何元素并将它们存储在那里。 'for循环'循环遍历每个元素并检查它是否在视口中是垂直的。此代码执行每次用户滚动!如果getBoudingClientRect()。top小于视口的3/4(该元素在视口中是四分之一),则它将注册为“在视口中”。由于代码是通用的,因此您需要知道视口中的“哪个”元素。要找到它,您可以通过自定义属性,节点名称,ID,类名称等来确定它。这是我的代码(告诉我,如果它不起作用,它已经在IE 11,FireFox 40.0.3,Chrome版本45.0.2454.85 m,Opera 31.0.1889.174和Edge与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.');
}
};
希望这有助于某人: - )
这是一个函数,它告诉一个元素在父元素的当前视口中是否可见:
function inParentViewport(el, pa) {
if (typeof jQuery === "function"){
if (el instanceof jQuery)
el = el[0];
if (pa instanceof jQuery)
pa = pa[0];
}
var e = el.getBoundingClientRect();
var p = pa.getBoundingClientRect();
return (
e.bottom >= p.top &&
e.right >= p.left &&
e.top <= p.bottom &&
e.left <= p.right
);
}
尽可能简单到IMO:
function isVisible(elem) {
var coords = elem.getBoundingClientRect();
return Math.abs(coords.top) <= coords.height;
}
我使用这个功能(它只检查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;
}
}
对于类似的挑战,我非常喜欢这个要点,它公开了一个polyfill scrollIntoViewIfNeeded()。
所有必要的功夫都需要回答:
var parent = this.parentNode,
parentComputedStyle = window.getComputedStyle(parent, null),
parentBorderTopWidth = parseInt(parentComputedStyle.getPropertyValue('border-top-width')),
parentBorderLeftWidth = parseInt(parentComputedStyle.getPropertyValue('border-left-width')),
overTop = this.offsetTop - parent.offsetTop < parent.scrollTop,
overBottom = (this.offsetTop - parent.offsetTop + this.clientHeight - parentBorderTopWidth) > (parent.scrollTop + parent.clientHeight),
overLeft = this.offsetLeft - parent.offsetLeft < parent.scrollLeft,
overRight = (this.offsetLeft - parent.offsetLeft + this.clientWidth - parentBorderLeftWidth) > (parent.scrollLeft + parent.clientWidth),
alignWithTop = overTop && !overBottom;
this
是指您想知道的元素,如果它是overTop
或overBottom
- 只是应该得到漂移......