Javascript 如何判断DOM元素在当前视口中是否可见?
有没有一种有效的方法来判断HTML文档中的DOM元素当前是否在视口中可见 这个问题涉及到Firefox。更新:时间在流逝,我们的浏览器也在前进。不再推荐使用此技术,如果您不需要支持InternetExplorer 7之前的版本,则应使用此技术 原始解决方案现已过时: 这将检查元素在当前视口中是否完全可见:Javascript 如何判断DOM元素在当前视口中是否可见?,javascript,html,firefox,dom,browser,Javascript,Html,Firefox,Dom,Browser,有没有一种有效的方法来判断HTML文档中的DOM元素当前是否在视口中可见 这个问题涉及到Firefox。更新:时间在流逝,我们的浏览器也在前进。不再推荐使用此技术,如果您不需要支持InternetExplorer 7之前的版本,则应使用此技术 原始解决方案现已过时: 这将检查元素在当前视口中是否完全可见: function elementInViewport(el) { var top = el.offsetTop; var left = el.offsetLeft; var wid
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
);
}
您可以对其进行修改,以确定元素的任何部分是否在视口中可见:
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
);
}
现在支持方法,这已成为最佳实践。使用一个旧的答案是非常缓慢的,而且
选择为正确的解决方案为
此解决方案在Internet Explorer 7及更高版本、iOS 5及更高版本Safari、Eclair及更高版本、黑莓、Opera Mobile和Internet Explorer Mobile上进行了测试
如果您进行任何DOM修改,它们当然可以更改元素的可见性
准则和常见陷阱:
也许您需要跟踪页面缩放/移动设备收缩?jQuery应该处理跨浏览器的问题,否则,link应该可以帮助您
如果修改DOM,它会影响元素的可见性。您应该控制它并手动调用处理程序。不幸的是,我们没有任何跨浏览器OnRepain事件。另一方面,它允许我们进行优化,并且只对能够改变元素可见性的DOM修改执行重新检查
永远不要只在jQuery中使用它,因为此时此刻。您的代码可以在本地硬盘上使用CSS,但一旦放到远程服务器上,它就会失败
在触发DOMContentLoaded之后,但是。因此,我们应该添加window.onload事件侦听器
我们还不能捕捉缩放/收缩事件
最后的办法可能是使用以下代码:
/* TODO: this looks like a very bad code */
setInterval(handler, 600);
如果您关心网页的选项卡是否处于活动状态且可见,则可以使用HTML5API的强大功能
TODO:此方法不处理两种情况:
使用z索引进行重叠。
在元素的容器中使用溢出滚动。
尝试新事物-。
请参阅的源代码,它使用。就像:
function inViewport (el) {
var r, html;
if ( !el || 1 !== el.nodeType ) { return false; }
html = document.documentElement;
r = el.getBoundingClientRect();
return ( !!r
&& r.bottom >= 0
&& r.right >= 0
&& r.top <= html.clientHeight
&& r.left <= html.clientWidth
);
}
如果元素的任何部分在视口中,则返回true。更好的解决方案:
function getViewportSize(w) {
var w = w || window;
if(w.innerWidth != null)
return {w:w.innerWidth, h:w.innerHeight};
var d = w.document;
if (document.compatMode == "CSS1Compat") {
return {
w: d.documentElement.clientWidth,
h: d.documentElement.clientHeight
};
}
return { w: d.body.clientWidth, h: d.body.clientWidth };
}
function isViewportVisible(e) {
var box = e.getBoundingClientRect();
var height = box.height || (box.bottom - box.top);
var width = box.width || (box.right - box.left);
var viewport = getViewportSize();
if(!height || !width)
return false;
if(box.top > viewport.h || box.bottom < 0)
return false;
if(box.right < 0 || box.left > viewport.w)
return false;
return true;
}
使现代化
在现代浏览器中,您可能希望查看提供以下好处的:
性能优于侦听滚动事件
在跨域iframe中工作
可以判断一个图元是否阻碍/相交于另一个图元
Intersection Observer正在成为一个成熟的标准,已经在Chrome 51+、Edge 15+和Firefox 55+中得到支持,并且正在为Safari开发。还有一个可用的
先前的答复
在某些情况下,该方法存在一些问题,可能使其成为不合适的方法。在他接近底部的回答中指出了其中一些问题,他的代码将为以下元素提供误报:
被测试元素前面的另一个元素隐藏
在父元素或父元素的可见区域之外
通过使用CSS clip属性隐藏的元素或其子元素
这些局限性在以下的测试结果中得到了证明:
解决方案:isElementVisible
下面是这些问题的解决方案,以及下面的测试结果和对代码某些部分的解释
function isElementVisible(el) {
var rect = el.getBoundingClientRect(),
vWidth = window.innerWidth || document.documentElement.clientWidth,
vHeight = window.innerHeight || document.documentElement.clientHeight,
efp = function (x, y) { return document.elementFromPoint(x, y) };
// Return false if it's not in the viewport
if (rect.right < 0 || rect.bottom < 0
|| rect.left > vWidth || rect.top > vHeight)
return false;
// Return true if any of its four corners are visible
return (
el.contains(efp(rect.left, rect.top))
|| el.contains(efp(rect.right, rect.top))
|| el.contains(efp(rect.right, rect.bottom))
|| el.contains(efp(rect.left, rect.bottom))
);
}
通过测试:
结果是:
附加说明
然而,这种方法也有其自身的局限性。例如,一个被测试的元素的z索引比同一位置的另一个元素低,即使前面的元素实际上没有隐藏它的任何部分,它也会被标识为隐藏。尽管如此,这种方法在Dan的解决方案未涵盖的某些情况下仍有其用途
element.getBoundingClientRect和document.elementFromPoint都是CSSOM工作草案规范的一部分,至少在IE 6和更高版本以及大多数桌面浏览器中都得到了长期支持,尽管并不完美。有关更多信息,请参阅
contains用于查看document.elementFromPoint返回的元素是否是我们正在测试可见性的元素的子节点。如果返回的元素是同一个元素,它也会返回true。这只会使检查更加健壮。所有主流浏览器都支持它,Firefox 9.0是最后一个添加它的浏览器。对于旧版Firefox支持,请查看此答案的历史记录
如果您想测试元素周围的更多点的可见性,即确保元素的覆盖率不超过(比如)50%,则不需要对答案的最后部分进行太多调整。但是,请注意,如果您检查每个像素以确保其100%可见,则速度可能会非常慢。我尝试过,但是,用于确定边界的代数意味着元素必须同时为≤ 视口大小和完全位于视口内部以获得tr
ue,容易导致误报。如果要确定某个图元是否在视口中,则该图元已关闭,但正在测试的图元应与视口重叠,因此请尝试以下操作:
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() */;
}
这是我的解决办法。如果一个元素被隐藏在一个可滚动的容器中,它就会工作 尝试重新调整窗口的大小以
var visibleY = function(el){
var top = el.getBoundingClientRect().top, rect, el = el.parentNode;
do {
rect = el.getBoundingClientRect();
if (top <= rect.bottom === false)
return false;
el = el.parentNode;
} while (el != document.body);
// Check it's within the document viewport
return top <= document.documentElement.clientHeight;
};
我只需要检查滚动Ajax加载更多记录功能在Y轴上是否可见。我的更短更快版本:
function isElementOutViewport(el){
var rect = el.getBoundingClientRect();
return rect.bottom < 0 || rect.right < 0 || rect.left > window.innerWidth || rect.top > window.innerHeight;
}
以及所需的JSFIDLE:作为公共服务:
Dan使用正确计算元素的答案可以是>窗口,特别是在手机屏幕上,正确的jQuery测试,以及添加isElementPartiallyInViewport:
顺便说一下,在window.innerWidth和document.documentElement.clientWidth之间,clientWidth/clientHeight不包含滚动条,而window.innerWidth/Height包含滚动条
function isElementPartiallyInViewport(el)
{
// Special bonus for those using jQuery
if (typeof jQuery !== 'undefined' && el instanceof jQuery)
el = el[0];
var rect = el.getBoundingClientRect();
// DOMRect { x: 8, y: 8, width: 100, height: 100, top: 8, right: 108, bottom: 108, left: 8 }
var windowHeight = (window.innerHeight || document.documentElement.clientHeight);
var windowWidth = (window.innerWidth || document.documentElement.clientWidth);
// http://stackoverflow.com/questions/325933/determine-whether-two-date-ranges-overlap
var vertInView = (rect.top <= windowHeight) && ((rect.top + rect.height) >= 0);
var horInView = (rect.left <= windowWidth) && ((rect.left + rect.width) >= 0);
return (vertInView && horInView);
}
// http://stackoverflow.com/questions/123999/how-to-tell-if-a-dom-element-is-visible-in-the-current-viewport
function isElementInViewport (el)
{
// Special bonus for those using jQuery
if (typeof jQuery !== 'undefined' && el instanceof jQuery)
el = el[0];
var rect = el.getBoundingClientRect();
var windowHeight = (window.innerHeight || document.documentElement.clientHeight);
var windowWidth = (window.innerWidth || document.documentElement.clientWidth);
return (
(rect.left >= 0)
&& (rect.top >= 0)
&& ((rect.left + rect.width) <= windowWidth)
&& ((rect.top + rect.height) <= windowHeight)
);
}
function fnIsVis(ele)
{
var inVpFull = isElementInViewport(ele);
var inVpPartial = isElementPartiallyInViewport(ele);
console.clear();
console.log("Fully in viewport: " + inVpFull);
console.log("Partially in viewport: " + inVpPartial);
}
测试用例
基于,我尝试清理实现,以便在同一页面上多次使用它更容易:
$(function() {
$(window).on('load resize scroll', function() {
addClassToElementInViewport($('.bug-icon'), 'animate-bug-icon');
addClassToElementInViewport($('.another-thing'), 'animate-thing');
// This checks if an element is at least partially in view (vertical dimension):
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}
}
$function{
$window.在“加载大小滚动”功能上{
AddClassToElementViewPort$'.bug图标','设置bug图标动画';
AddClassToElementViewPort$'。另一个东西是“动画化的东西”;
//这将检查图元是否至少部分位于视图垂直尺寸中:
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");
}
});
我发现这里的公认答案对于大多数用例来说过于复杂。这段代码使用jQuery很好地完成了这项工作,并区分了完全可见和部分可见的元素:
/**
* fullVisible=true only returns true if the all object rect is visible
*/
function isReallyVisible(el, fullVisible) {
if ( el.tagName == "HTML" )
return true;
var parentRect=el.parentNode.getBoundingClientRect();
var rect = arguments[2] || el.getBoundingClientRect();
return (
( fullVisible ? rect.top >= parentRect.top : rect.bottom > parentRect.top ) &&
( fullVisible ? rect.left >= parentRect.left : rect.right > parentRect.left ) &&
( fullVisible ? rect.bottom <= parentRect.bottom : rect.top < parentRect.bottom ) &&
( fullVisible ? rect.right <= parentRect.right : rect.left < parentRect.right ) &&
isReallyVisible(el.parentNode, fullVisible, rect)
);
};
我认为这是一种更实用的方法。
不要在递归上下文中工作
该函数通过递归测试HTML标记之前的任何级别,并在第一个false处停止,从而解决了当您的元素位于其他可滚动div中时的问题
$.fn.inView = function(){
if(!this.length)
return false;
var rect = this.get(0).getBoundingClientRect();
return (
rect.top >= 0 &&
rect.left >= 0 &&
rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
rect.right <= (window.innerWidth || document.documentElement.clientWidth)
);
};
// Additional examples for other use cases
// Is true false whether an array of elements are all in view
$.fn.allInView = function(){
var all = [];
this.forEach(function(){
all.push( $(this).inView() );
});
return all.indexOf(false) === -1;
};
// Only the class elements in view
$('.some-class').filter(function(){
return $(this).inView();
});
// Only the class elements not in view
$('.some-class').filter(function(){
return !$(this).inView();
});
我发现没有一个以jQuery为中心的功能版本让我感到不安。当我遇到这个机会时,我发现有机会为喜欢用jQuery OO风格编程的人提供一些东西。它很好,很快,对我来说很有魅力
八达炳八达邦
我有同样的问题,并通过使用getBoundingClientRect解决了这个问题
此代码是完全“通用”的,只需编写一次就可以工作,而不必为视口中的每个元素编写代码
此代码仅检查它在视口中是否垂直,而不是水平。在这种情况下,变量数组“elements”包含您要检查的所有元素,使其在视口中垂直,因此可以在任意位置抓取您想要的任何元素并将其存储在那里
“for loop”循环遍历每个元素,并检查它是否在视口中垂直。每次用户滚动时都会执行此代码!如果getBoudingClientRect.top小于视口的3/4,则元素在视口中占四分之一,它将注册为“在视口中”
由于代码是泛型的,您需要知道视口中的“which”元素。要了解这一点,您可以通过自定义属性、节点名称、id、类名等来确定它
这是我的代码,告诉我它是否不起作用;它已经在InternetExplorer11、Firefox 40.0.3、Chrome 45.0.2454.85 m、Opera 31.0.1889.174和Windows 10的Edge中进行了测试,[还没有Safari]
var parent = this.parentNode,
parentComputedStyle = window.getComputedStyle(parent, null),
parentBorderTopWidth = parseInt(parentComputedStyle.getPropertyValue('border-top-width')),
parentBorderLeftWidth = parseInt(parentComputedStyle.getPropertyValue('border-left-width')),
overTop = this.offsetTop - parent.offsetTop < parent.scrollTop,
overBottom = (this.offsetTop - parent.offsetTop + this.clientHeight - parentBorderTopWidth) > (parent.scrollTop + parent.clientHeight),
overLeft = this.offsetLeft - parent.offsetLeft < parent.scrollLeft,
overRight = (this.offsetLeft - parent.offsetLeft + this.clientWidth - parentBorderLeftWidth) > (parent.scrollLeft + parent.clientWidth),
alignWithTop = overTop && !overBottom;
对于一个类似的挑战,我真的很喜欢它为我们展示一个polyfill
回答问题所需的所有功夫都在这一块:
Element.prototype.isVisible = function(percentX, percentY){
var tolerance = 0.01; //needed because the rects returned by getBoundingClientRect provide the position up to 10 decimals
if(percentX == null){
percentX = 100;
}
if(percentY == null){
percentY = 100;
}
var elementRect = this.getBoundingClientRect();
var parentRects = [];
var element = this;
while(element.parentElement != null){
parentRects.push(element.parentElement.getBoundingClientRect());
element = element.parentElement;
}
var visibleInAllParents = parentRects.every(function(parentRect){
var visiblePixelX = Math.min(elementRect.right, parentRect.right) - Math.max(elementRect.left, parentRect.left);
var visiblePixelY = Math.min(elementRect.bottom, parentRect.bottom) - Math.max(elementRect.top, parentRect.top);
var visiblePercentageX = visiblePixelX / elementRect.width * 100;
var visiblePercentageY = visiblePixelY / elementRect.height * 100;
return visiblePercentageX + tolerance > percentX && visiblePercentageY + tolerance > percentY;
});
return visibleInAllParents;
};
这指的是您想知道的元素,例如,它是超顶还是超顶-您应该得到漂移…我在这里遇到的所有答案都只检查元素是否位于当前视口内。但这并不意味着它是可见的。
如果给定的元素在一个包含溢出内容的div中,并且被滚动到视图之外,该怎么办
要解决这个问题,您必须检查元素是否包含在所有父元素中。
我的解决方案正是这样做的:
它还允许您指定元素的可视程度
function elementInViewport(el) {
var elinfo = {
"top":el.offsetTop,
"height":el.offsetHeight,
};
if (elinfo.top + elinfo.height < window.pageYOffset || elinfo.top > window.pageYOffset + window.innerHeight) {
return false;
} else {
return true;
}
}
此解决方案忽略了一个事实,即元素可能由于其他因素而不可见,例如不透明度:0
我已经在Chrome和Internet Explorer 11中测试了此解决方案。我使用此功能,它只检查y是否在屏幕上,因为大多数情况下不需要x
$(window).on('scroll', function () {
var container = $('#sidebar');
var containerHeight = container.height();
var scrollPosition = $('#row1').offset().top - container.offset().top;
if (containerHeight < scrollPosition) {
console.log('not visible');
} else {
console.log('visible');
}
})
这是一个简单而小的解决方案,对我来说很有效
示例:您希望查看该元素在具有溢出滚动的父元素中是否可见
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
);
}
下面是一个函数,用于告知某个元素在父元素的当前视口中是否可见:
新的政策非常直接地解决了这个问题
此解决方案将需要一个polyfill,因为Safari、Opera和InternetExplorer不支持此功能,但polyfill已包含在解决方案中
在这个解决方案中,有一个观察到的目标框在视图外。当它进入视图时,标题顶部的按钮被隐藏。一旦框离开视图,它就会显示出来<
/p>
const buttonhide=document.querySelector'button';
const hidewhenboxiview=新的IntersectionObserverentries=>{
如果条目[0].intersectionRatio尽可能简单,IMO:
函数为VisibleElem{
var coords=elem.getBoundingClientRect;
return Math.abscoords.top支持的最简单的解决方案有:
以前的答案中的大多数用法在以下几点上都失败了:
-当元素的任何像素可见,但不是角点时
-当元素大于视口且居中时
-它们中的大多数只检查文档或窗口中的单个元素
嗯,对于所有这些问题,我有一个解决方案,其优点是:
-当只显示任意边上的像素而不是角点时,可以返回可见
-当元素大于视口时,仍然可以返回可见
-您可以选择父元素,也可以自动让它选择
-也适用于动态添加的元素
如果您查看下面的代码片段,您将看到在元素容器中使用溢出滚动不会造成任何问题的区别,并看到与其他答案不同的是,即使像素从任何一侧出现,或者当元素大于视口时,我们看到元素的内部像素,它仍然工作
用法很简单:
不带交叉搜索算法的演示,适用于大于视口的元素检查元素3内部像素以查看:
函数isVisibleelement、父函数、交叉搜索算法{
var rect=element.getBoundingClientRect,
prect=parent!=未定义?parent.getBoundingClientRect:element.parentNode.getBoundingClientRect,
csa=交叉搜索算法!=未定义?交叉搜索算法:false,
efp=函数x,y{return document.elementFromPointx,y};
//如果不在视口中,则返回false
如果rect.rightprect.right | rect.top>prect.bottom{
返回false;
}
var标志=假;
//如果从左到右到达任何边界像素,则返回true
对于变量x=rect.left;xrect.left | | yrect.left{x-;}
ify forvar i=4;i在Android上放大Google Chrome时,大多数被接受的答案不起作用。必须结合使用,才能在Android上计算Chrome。以下示例仅考虑垂直检查,并使用jQuery计算窗口高度:
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));
这里的所有答案都是确定元素是否完全包含在视口中,而不仅仅是以某种方式可见。例如,如果在视图底部只有一半图像可见,那么考虑到外部因素,这里的解决方案将失败
我有一个通过IntersectionObserver进行延迟加载的用例,但由于在弹出过程中出现动画,我不想观察页面加载时已经相交的任何图像。为此,我使用了以下代码:
/* TODO: this looks like a very bad code */
setInterval(handler, 600);
这基本上是检查顶部或底部边界在视口中是否独立。另一端可能在外部,
但只要一端在,它就至少部分可见。下面是一个片段,用于检查给定元素在其父元素中是否完全可见:
导出常量visibleInParentViewport=el=>{
const elementRect=el.getBoundingClientRect;
const parentRect=el.parentNode.getBoundingClientRect;
回来
elementRect.top>=parentRect.top&&
elementRect.right>=parentRect.left&&
elementRect.top+elementRect.height原来发布的函数有一个错误。需要在重新分配el之前保存宽度/高度…如果元素位于可滚动的div中并从视图中滚动出去会怎么样?请查看下面的脚本的更新版本,对@amartynov的问题很好奇。有人知道如何简单地判断元素是否隐藏了吗由于祖先元素溢出而导致den?如果无论子元素嵌套的深度如何,都能检测到这种情况,那就有好处了。@deadManN在DOM中递归的速度非常慢。这就是原因,但浏览器供应商也创建了getBoundingClientRect,专门用于查找元素坐标……我们为什么不使用它呢?我正在使用这个解决方案,但是要注意botom的输入错误。当我们正在考虑的元素中包含图像时,还有一些需要注意的事情。Chrome至少必须等待图像加载到boundingRectangle的精确值。Firefox似乎没有这个问题。当您启用滚动时,它是否工作d位于主体内的容器中。例如,它在此处不起作用-IsElementViewPortDocument.GetElementByIdinerEle.innerele位于启用滚动的容器中。计算假定元素比屏幕小。如果您有高或宽元素,则使用return rect.bottom>=0&&rect可能更准确.right>=0&&rect.top提示:对于那些试图用jQuery实现这一点的人来说,只是一个友好的提醒,让他们传入HTML DOM对象,例如IsElementViewPortDocument.getElementById'elem',而不是jQuery对象,例如IsElementViewPort$elem。jQuery等价物是这样添加[0]:IsElementViewPort$elem[0].el未定义您应该尝试解释为什么您的版本更好。就目前情况而言,它看起来与其他解决方案大致相同。伟大的解决方案它有一个框/滚动容器,只有在未指定的情况下才使用窗口。查看代码而不是评价它是一个更通用的解决方案正在搜索它。您是不是打算这么做使用doc.documentElement.clientWidth?应该改为“document.documentElement”吗?另一方面,这是唯一一种同样适用于使用CSS“clip”属性隐藏元素内容以便于访问的用例的方法:@klamping:很好,谢谢。我从我使用doc的代码中复制了它是的,我认为这是边缘情况的一个不错的解决方案。对我来说,它不起作用。但上一个答案中的inViewport在FF中起作用。如果应用圆角或变换,检查元素的中心是否可见也可能是有益的,因为边界角可能不会返回预期的元素ent:element.containsefprect.right-rect.width/2,rect.bottom-rect.height/2Did对我的输入不起作用chrome canary 50。不确定为什么,可能是本地圆角?我必须稍微减少坐标以使其工作el.containsefprect.left+1,rect.top+1 | el.containsefprect.right-1,rect.top+1 | el.containsefprect。right-1,rect.bottom-1 | | el.containsefprect.left+1,rect.bottom-1我的解决方案更贪婪更快,当元素在视口中有任何像素时,它将返回false。我喜欢它。简明。你可以删除函数名和括号之间的空格,以及括号和大括号之间的空格,在第一行。从来都不喜欢这些空格。也许吧只是我的文本编辑器对所有内容进行了颜色编码,这仍然使其易于阅读。函数aaaarg{statements}我知道这并不会使它执行得更快,而是在缩小范围内。IsElementPartialInViewport也非常有用。很好的一个。对于IsElementViewPorte:您的代码甚至没有加载图像,这一个是正确的:函数IsElementViewPorte{var t=e.getBoundingClientRect;return t.top>=0&&t.left>=0&&t.bottom@Arun chauhan:我的代码都没有加载图像,所以为什么要加载,而且公式是正确的。@targumon:原因是支持旧浏览器。@StefanSteiger根据MDN,它从IE9开始就受到支持,所以至少在我的情况下使用window.in实际上是安全的nerHeight。谢谢!大括号是否足以关闭if语句?我无法使它与同一类的多个元素一起工作。@TheWhizofOz我已更新了我的答案,以给出您提出的其他可能用例的示例。祝您好运。您应该将$window=$window缓存在滚动处理程序之外。您应该将$window=$window缓存在滚动手柄外
ood实施,根据其中的链接,IntersectionObserver是一种实验性功能,将来可能会发生变化。@KarthikChintala-除IE外,其他浏览器都支持该功能,并且还有一个polyfill可用。这并没有解决OP的问题,因为它只检测变化:IntersectionObserver仅在目标相对于根移动后激发回调。调用时,将立即激发观察事件,告诉您被跟踪元素的当前相交状态。所以,在某种程度上,它解决了问题。这取决于你所说的可见是什么意思。如果您的意思是它当前是否显示在页面上,给定滚动位置,您可以根据元素y偏移量和当前滚动位置计算它。说明:可见,如当前显示的矩形中所示。可见,如不隐藏或显示:无?可见,如不在Z顺序中的其他内容后面?如在当前显示的矩形中。谢谢重新措辞。请注意,这里的所有答案都会为位于其父元素e.h.可见区域之外、溢出隐藏但位于视口区域内的项目提供假阳性。答案有一百万个,大多数答案都长得离谱。这在移动浏览器上表现如何?他们中的大多数人在viewport方面都有缺陷,标题在滚动时会上下移动,键盘显示时的行为也会有所不同,这取决于是安卓还是ios等等。@Kev应该可以正常工作,这取决于您何时调用此方法。如果调用它,然后调整窗口大小,结果显然可能不再正确。根据需要的功能类型,您可以在每次调整大小事件中调用它。请随意问一个关于您的特定用例的单独问题,并在这里ping我。在99%的情况下,这就足够了,特别是当您只需要启动或停止音量控制器或其他东西并节省一些CPU时。让设备走向死亡的是开发人员,而不是普通用户$window.on'scroll',函数{ifisInView$'.fader'.get0{}else{};
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
);
}
function isInView(el) {
const box = el.getBoundingClientRect();
return box.top < window.innerHeight && box.bottom >= 0;
}
// For checking element visibility from any sides
isVisible(element)
// For checking elements visibility in a parent you would like to check
var parent = document; // Assuming you check if 'element' inside 'document'
isVisible(element, parent)
// For checking elements visibility even if it's bigger than viewport
isVisible(element, null, true) // Without parent choice
isVisible(element, parent, true) // With parent choice
var Rect = YOUR_ELEMENT.getBoundingClientRect();
var ElTop = Rect.top, ElBottom = Rect.bottom;
var WindowHeight = $(window).height();
if(window.visualViewport) {
ElTop -= window.visualViewport.offsetTop;
ElBottom -= window.visualViewport.offsetTop;
WindowHeight = window.visualViewport.height;
}
var WithinScreen = (ElTop >= 0 && ElBottom <= WindowHeight);
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));