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 修改执行重新检查。

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

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

相关文章:

javascript - Fengyuanchen Datepicker - 箭头上一个/下一个

javascript - 使用 window.showmodaldialog 时如何在 firefox 中禁用调整大小

html - 图片提交表单

javascript - 将JS分离到多个文件

javascript - 错误: Unable to find module 'opennebula' (Meteor.JS)

javascript - fullPage.js onLoad 回调?

html - 如果不是 child ,如何不让元素刹车

javascript - 如何仅更改页面内 vaadin-select 中 vaadin-select-text-field 的颜色?

html - 从 html 表中提取链接

python - 在 GeckoDriver Selenium 和 Python 的 headless 模式下使用 Firefox 68.9.0esr 时出现 504 网关超时错误