是否有一种有效的方法来判断 DOM 元素(在 HTML 文档中)当前是否可见(出现在视口(viewport)中)?
(问题是指Firefox。)
最佳答案
现在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 修改执行重新检查。
Never Ever 仅在 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:此方法不处理两种情况:
- 使用
z-index
重叠。 - 在元素的容器中使用
overflow-scroll
。 - 尝试新事物 - The Intersection Observer API explained 。
关于javascript - 如何判断 DOM 元素在当前视口(viewport)中是否可见?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14733132/