Now most browsers support getBoundingClientRect method, which has become the best practice.(现在, 大多数浏览器都支持getBoundingClientRect方法,这已成为最佳实践。)
Using an old answer is very slow , not accurate and has several bugs .(使用旧的答案非常慢 , 不够准确,并且存在多个错误 。)
The solution selected as correct is almost never precise .(选择正确的解决方案几乎永远都不是精确的 。)
You can read more about its bugs.(您可以阅读有关其错误的更多信息。)
This solution was tested on IE7+, iOS5+ Safari, Android2+, Blackberry, Opera Mobile, and IE Mobile 10 .(此解决方案已在IE7 +,iOS5 + Safari,Android2 +,Blackberry,Opera Mobile和IE Mobile 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() */
);
}
How to use:(如何使用:)
You can be sure that the function given above returns correct answer at the moment of time when it is called, but what about tracking element's visibility as an event?(您可以确定上面给出的函数在被调用时会返回正确的答案,但是作为事件跟踪元素的可见性又如何呢?)
Place the following code at the bottom of your <body>
tag:(将以下代码放在<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);
}
*/
If you do any DOM modifications, they can change your element's visibility of course.(如果您进行任何DOM修改,它们当然可以更改元素的可见性。)
Guidelines and common pitfalls:(准则和常见陷阱:)
Maybe you need to track page zoom / mobile device pinch?(也许您需要跟踪页面缩放/移动设备挤压?)
jQuery should handle zoom/pinch cross browser, otherwise first or second link should help you.(jQuery应该处理缩放/收缩交叉浏览器,否则第一个或第二个链接应该会对您有所帮助。)
If you modify DOM , it can affect the element's visibility.(如果您修改DOM ,则可能会影响元素的可见性。)
You should take control over that and call handler()
manually.(您应该对此进行控制并手动调用handler()
。) Unfortunately, we have no cross browser onrepaint
event.(不幸的是,我们没有跨浏览器的onrepaint
事件。) On the other hand that allows us to make optimizations and perform re-check only on DOM modifications that can change element's visibility.(另一方面,这使我们可以进行优化并仅对可以更改元素可见性的DOM修改执行重新检查。)
Never Ever use it inside jQuery $(document).ready() only, because there is no warranty CSS has been applied in this moment.(永远不要只在jQuery $(document).ready()中使用它,因为目前没有担保CSS 。)
Your code can work locally with your CSS on hard drive, but once put on remote server it will fail.(您的代码可以与硬盘驱动器上的CSS在本地一起使用,但是一旦放在远程服务器上,它将失败。)
After DOMContentLoaded
is fired, styles are applied , but the images are not loaded yet .(触发DOMContentLoaded
后, 将应用样式 ,但尚未加载图像 。)
So, we should add window.onload
event listener.(因此,我们应该添加window.onload
事件监听器。)
We can't catch zoom/pinch event yet.(我们尚无法捕获缩放事件。)
The last resort could be the following code:(最后的办法可能是以下代码:)
/* TODO: this looks like a very bad code */
setInterval(handler, 600);
You can use awesome feature pageVisibiliy HTML5 API if you care if the tab with your web page is active and visible.(如果您关心网页上的标签是否处于活动状态且可见,则可以使用功能强大的pageVisibiliy HTML5 API。)
TODO: this method does not handle two situations:(TODO:此方法不能处理两种情况:)