有没有一种有效的方法来判断 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 修改进行优化和执行重新检查。
永远不会仅在 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/34744653/