Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
545 views
in Technique[技术] by (71.8m points)

javascript - 如何判断DOM元素在当前视口中是否可见?(How to tell if a DOM element is visible in the current viewport?)

Is there an efficient way to tell if a DOM element (in an HTML document) is currently visible (appears in the viewport )?

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

(The question refers to Firefox)

((问题是指Firefox))

  ask by benzaita translate from so

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Now most browsers support getBoundingClientRect method, which has become the best practice.

(现在, 大多数浏览器都支持getBoundingClientRect方法,这已成为最佳实践。)

Using an old answer is very slow , not accurate and has several bugs .

(使用旧的答案非常慢不够准确,并且存在多个错误 。)

The solution selected as correct is almost never precise .

(选择正确的解决方案几乎永远都不是精确的 。)

You can read more about its bugs.

(您可以阅读有关其错误的更多信息。)


This solution was tested on IE7+, iOS5+ Safari, Android2+, Blackberry, Opera Mobile, and IE Mobile 10 .

(此解决方案已在IE7 +,iOS5 + Safari,Android2 +,Blackberry,Opera Mobile和IE Mobile 10上进行了测试 。)


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() */
    );
}

How to use: (如何使用:)

You can be sure that the function given above returns correct answer at the moment of time when it is called, but what about tracking element's visibility as an event?

(您可以确定上面给出的函数在被调用时会返回正确的答案,但是作为事件跟踪元素的可见性又如何呢?)

Place the following code at the bottom of your <body> tag:

(将以下代码放在<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); // IE9+ :(
    attachEvent('onload', handler);
    attachEvent('onscroll', handler);
    attachEvent('onresize', handler);
}
*/

If you do any DOM modifications, they can change your element's visibility of course.

(如果您进行任何DOM修改,它们当然可以更改元素的可见性。)

Guidelines and common pitfalls:

(准则和常见陷阱:)

Maybe you need to track page zoom / mobile device pinch?

(也许您需要跟踪页面缩放/移动设备挤压?)

jQuery should handle zoom/pinch cross browser, otherwise first or second link should help you.

(jQuery应该处理缩放/收缩交叉浏览器,否则第一个第二个链接应该会对您有所帮助。)

If you modify DOM , it can affect the element's visibility.

(如果您修改DOM ,则可能会影响元素的可见性。)

You should take control over that and call handler() manually.

(您应该对此进行控制并手动调用handler() 。)

Unfortunately, we have no cross browser onrepaint event.

(不幸的是,我们没有跨浏览器的onrepaint事件。)

On the other hand that allows us to make optimizations and perform re-check only on DOM modifications that can change element's visibility.

(另一方面,这使我们可以进行优化并仅对可以更改元素可见性的DOM修改执行重新检查。)

Never Ever use it inside jQuery $(document).ready() only, because there is no warranty CSS has been applied in this moment.

(永远不要只在jQuery $(document).ready()中使用它,因为目前没有担保CSS 。)

Your code can work locally with your CSS on hard drive, but once put on remote server it will fail.

(您的代码可以与硬盘驱动器上的CSS在本地一起使用,但是一旦放在远程服务器上,它将失败。)

After DOMContentLoaded is fired, styles are applied , but the images are not loaded yet .

(触发DOMContentLoaded后, 将应用样式 ,但尚未加载图像 。)

So, we should add window.onload event listener.

(因此,我们应该添加window.onload事件监听器。)

We can't catch zoom/pinch event yet.

(我们尚无法捕获缩放事件。)

The last resort could be the following code:

(最后的办法可能是以下代码:)

/* TODO: this looks like a very bad code */
setInterval(handler, 600); 

You can use awesome feature pageVisibiliy HTML5 API if you care if the tab with your web page is active and visible.

(如果您关心网页上的标签是否处于活动状态且可见,则可以使用功能强大的pageVisibiliy HTML5 API。)

TODO: this method does not handle two situations:

(TODO:此方法不能处理两种情况:)


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...