现在most browsers 支持getBoundingClientRect 方法,这已成为最佳实践。使用旧答案非常慢, not accurate 和 has several bugs 。
选择正确的解决方案是 almost never precise 。
此解决方案已在 Internet Explorer 7(及更高版本)、iOS 5(及更高版本)Safari、Android 2.0 (Eclair) 及更高版本、BlackBerry、Opera Mobile 和 Internet Explorer Mobile 9 上进行了测试。
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); // Internet Explorer 9+ :(
attachEvent('onload', handler);
attachEvent('onscroll', handler);
attachEvent('onresize', handler);
}
*/
如果您进行任何 DOM 修改,它们当然可以改变您元素的可见性。
指南和常见陷阱:
也许您需要跟踪页面缩放/移动设备捏合? jQuery 应该处理 zoom/pinch 跨浏览器,否则 first 或 second 链接应该可以帮助您。
如果您修改 DOM,它会影响元素的可见性。您应该控制它并手动调用 handler()
。不幸的是,我们没有任何跨浏览器 onrepaint
事件。另一方面,这允许我们进行优化并仅对可能改变元素可见性的 DOM 修改执行重新检查。
永远不会仅在 jQuery $(document).ready() 中使用它,因为此时 there is no warranty CSS has been applied。您的代码可以在本地与硬盘上的 CSS 一起工作,但一旦放在远程服务器上,它就会失败。
在 DOMContentLoaded
被触发后, styles are applied ,但是 the images are not loaded yet 。所以,我们应该添加 window.onload
事件监听器。
我们还不能捕捉缩放/捏合事件。
最后的手段可能是以下代码:
/* TODO: this looks like a very bad code */
setInterval(handler, 600);
如果您关心您的网页的选项卡是否处于事件状态且可见,您可以使用 HTML5 API 的出色功能 pageVisibiliy。
TODO:此方法不处理两种情况:
我是一名优秀的程序员,十分优秀!