如何判断 DOM 元素在当前视口中是否可见?
有没有一种有效的方法来判断DOM元素(在HTML文档中)当前是否可见(出现在视口中)?
(这个问题指的是Firefox。
有没有一种有效的方法来判断DOM元素(在HTML文档中)当前是否可见(出现在视口中)?
(这个问题指的是Firefox。
现在大多数浏览器都支持getBoundingClientRect方法,这已经成为最佳实践。使用旧答案非常慢,不准确,并且有几个错误。
选择为正确的解决方案几乎从不精确。
此解决方案在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应该处理缩放/捏合跨浏览器,否则第一个或第二个链接应该对你有所帮助。
如果修改 DOM,则会影响元素的可见性。您应该控制它并手动调用。很抱歉,我们没有任何跨浏览器事件。另一方面,它允许我们进行优化并仅对可以更改元素可见性的DOM修改执行重新检查。handler()
onrepaint
永远不要只在jQuery $(document).ready()中使用它,因为目前没有保证CSS已经应用。您的代码可以在硬盘驱动器上与CSS一起本地工作,但是一旦放在远程服务器上,它就会失败。
触发后,将应用样式,但尚未加载图像。因此,我们应该添加事件侦听器。DOMContentLoaded
window.onload
我们还无法捕捉缩放/捏合事件。
最后的手段可能是以下代码:
/* TODO: this looks like a very bad code */
setInterval(handler, 600);
您可以使用HTML5 API的精彩功能页面,如果您关心网页的选项卡是否处于活动状态且可见。
TODO:此方法不处理两种情况:
z-index
overflow-scroll
更新:时间在流逝,我们的浏览器也是如此。不再建议使用此技术,如果您不需要支持 7 之前的 Internet Explorer 版本,则应使用 Dan 的解决方案。
原始解决方案(现已过时):
这将检查该元素在当前视口中是否完全可见:
function elementInViewport(el) {
var top = el.offsetTop;
var left = el.offsetLeft;
var width = el.offsetWidth;
var height = el.offsetHeight;
while(el.offsetParent) {
el = el.offsetParent;
top += el.offsetTop;
left += el.offsetLeft;
}
return (
top >= window.pageYOffset &&
left >= window.pageXOffset &&
(top + height) <= (window.pageYOffset + window.innerHeight) &&
(left + width) <= (window.pageXOffset + window.innerWidth)
);
}
您可以简单地修改此参数,以确定元素的任何部分在视口中是否可见:
function elementInViewport2(el) {
var top = el.offsetTop;
var left = el.offsetLeft;
var width = el.offsetWidth;
var height = el.offsetHeight;
while(el.offsetParent) {
el = el.offsetParent;
top += el.offsetTop;
left += el.offsetLeft;
}
return (
top < (window.pageYOffset + window.innerHeight) &&
left < (window.pageXOffset + window.innerWidth) &&
(top + height) > window.pageYOffset &&
(left + width) > window.pageXOffset
);
}