javascript - 如何判断 DOM 元素在当前视口(viewport)中是否可见?

标签 javascript html firefox dom browser

有没有一种有效的方法来判断 DOM 元素(在 HTML 文档中)当前是否可见(出现在视口(viewport)中)?

(问题涉及 Firefox。)

最佳答案

现在 most browsers 支持 getBoundingClientRect 方法,这已成为最佳实践。使用旧答案非常慢, not accuratehas 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 跨浏览器,否则 firstsecond 链接应该可以帮助您。

如果修改 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:此方法不处理两种情况:

关于javascript - 如何判断 DOM 元素在当前视口(viewport)中是否可见?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34744653/

相关文章:

javascript - Firefox Iframe 问题

css - 奇怪的页脚行为

html - 向右浮动,将左侧内容向下推

火狐插件 : extension icon not showing

javascript - TypeError : this. 元素在 Firefox 22.0 中未定义,导致我的网站关闭

javascript - 使用带有 document.addEventListener 的 JavaScript DOMContentLoaded 时,Firefox 不会报告异常

javascript - 如何在 Angular JS 的弹出窗口外单击时隐藏 uib-popover?

javascript - 记住页面导航之间展开的节点

javascript - axios.get() 请求返回未定义

javascript - 如何从 ComboBox (ExtJS) 中的商店中选择特定记录