是否有一种有效的方法来判断DOM元素(在HTML文档中)当前是否可见(出现在视口中)?
(这个问题指的是Firefox。)
是否有一种有效的方法来判断DOM元素(在HTML文档中)当前是否可见(出现在视口中)?
(这个问题指的是Firefox。)
当前回答
这检查元素是否至少部分在视图中(垂直维度):
function inView(element) {
var box = element.getBoundingClientRect();
return inViewBox(box);
}
function inViewBox(box) {
return ((box.bottom < 0) || (box.top > getWindowSize().h)) ? false : true;
}
function getWindowSize() {
return { w: document.body.offsetWidth || document.documentElement.offsetWidth || window.innerWidth, h: document.body.offsetHeight || document.documentElement.offsetHeight || window.innerHeight}
}
其他回答
这里所有的答案都是确定元素是否完全包含在视口中,而不仅仅是以某种方式可见。例如,如果在视图的底部只有图像的一半可见,这里的解决方案将失败,考虑到“外部”。
我有一个用例,我正在通过IntersectionObserver进行惰性加载,但由于弹出过程中发生的动画,我不想观察任何已经在页面加载上交叉的图像。为此,我使用了以下代码:
const bounding = el.getBoundingClientRect();
const isVisible = (0 < bounding.top && bounding.top < (window.innerHeight || document.documentElement.clientHeight)) ||
(0 < bounding.bottom && bounding.bottom < (window.innerHeight || document.documentElement.clientHeight));
这基本上是检查顶部或底部边界是否在视口中独立。另一端可能在外面,但只要一端在里面,它至少是部分“可见”的。
下面是一个函数,它告诉你一个元素在父元素的当前视口中是否可见:
function inParentViewport(el, pa) {
if (typeof jQuery === "function"){
if (el instanceof jQuery)
el = el[0];
if (pa instanceof jQuery)
pa = pa[0];
}
var e = el.getBoundingClientRect();
var p = pa.getBoundingClientRect();
return (
e.bottom >= p.top &&
e.right >= p.left &&
e.top <= p.bottom &&
e.left <= p.right
);
}
我尝试了Dan的答案,然而,用于确定边界的代数意味着元素必须既≤视口大小,又完全在视口内才能为真,很容易导致假否定。如果你想确定一个元素是否在视口中,ryanve的答案是接近的,但被测试的元素应该与视口重叠,所以试试这个:
function isElementInViewport(el) {
var rect = el.getBoundingClientRect();
return rect.bottom > 0 &&
rect.right > 0 &&
rect.left < (window.innerWidth || document.documentElement.clientWidth) /* or $(window).width() */ &&
rect.top < (window.innerHeight || document.documentElement.clientHeight) /* or $(window).height() */;
}
查看verge的源代码,它使用getBoundingClientRect。这就像:
function inViewport (element) {
if (!element) return false;
if (1 !== element.nodeType) return false;
var html = document.documentElement;
var rect = element.getBoundingClientRect();
return !!rect &&
rect.bottom >= 0 &&
rect.right >= 0 &&
rect.left <= html.clientWidth &&
rect.top <= html.clientHeight;
}
如果元素的任何部分在视口中,则返回true。
我发现这里公认的答案对于大多数用例来说过于复杂。这段代码很好地完成了工作(使用jQuery),并区分了完全可见和部分可见的元素:
var element = $("#element");
var topOfElement = element.offset().top;
var bottomOfElement = element.offset().top + element.outerHeight(true);
var $window = $(window);
$window.bind('scroll', function() {
var scrollTopPosition = $window.scrollTop()+$window.height();
var windowScrollTop = $window.scrollTop()
if (windowScrollTop > topOfElement && windowScrollTop < bottomOfElement) {
// Element is partially visible (above viewable area)
console.log("Element is partially visible (above viewable area)");
} else if (windowScrollTop > bottomOfElement && windowScrollTop > topOfElement) {
// Element is hidden (above viewable area)
console.log("Element is hidden (above viewable area)");
} else if (scrollTopPosition < topOfElement && scrollTopPosition < bottomOfElement) {
// Element is hidden (below viewable area)
console.log("Element is hidden (below viewable area)");
} else if (scrollTopPosition < bottomOfElement && scrollTopPosition > topOfElement) {
// Element is partially visible (below viewable area)
console.log("Element is partially visible (below viewable area)");
} else {
// Element is completely visible
console.log("Element is completely visible");
}
});