在JavaScript中,您如何检查元素是否实际可见?
我不仅指检查visibility
和display
属性。我指的是,要检查元素不是:
visibility: hidden
或display: none
- 位于另一个元素下面
- 已滚动到屏幕边缘之外
基于技术原因,我无法包含任何脚本。但是,由于Prototype已经在页面上,因此可以使用它。
在JavaScript中,您如何检查元素是否实际可见?
我不仅指检查visibility
和display
属性。我指的是,要检查元素不是:
visibility: hidden
或display: none
基于技术原因,我无法包含任何脚本。但是,由于Prototype已经在页面上,因此可以使用它。
对于第二点。
我看到没有人建议使用document.elementFromPoint(x,y)
,在我看来这是测试一个元素是否被嵌套或被另一个元素隐藏的最快方法。您可以将目标元素的偏移量传递给该函数。
这是PPK关于elementFromPoint
的测试页面:elementFromPoint。
来自MDN文档:
elementFromPoint()
方法 - 可在Document和ShadowRoot对象上使用 - 返回指定坐标(相对于视口)的最顶层元素。
elementFromPoint()
方法显示一个元素被其它元素完全覆盖住了(你把它视为不可见),但用户却能看到它。请问如何解决? - Konstantin Smolyanin<div>
。实际上,父<div>
是有效和可见的,但输出并未显示这一点。 - user172163我不知道这在老版本或不太现代的浏览器中有多少支持,但我正在使用类似于这样的东西(不需要任何库):
function visible(element) {
if (element.offsetWidth === 0 || element.offsetHeight === 0) return false;
var height = document.documentElement.clientHeight,
rects = element.getClientRects(),
on_top = function(r) {
var x = (r.left + r.right)/2, y = (r.top + r.bottom)/2;
return document.elementFromPoint(x, y) === element;
};
for (var i = 0, l = rects.length; i < l; i++) {
var r = rects[i],
in_viewport = r.top > 0 ? r.top <= height : (r.bottom > 0 && r.bottom <= height);
if (in_viewport && on_top(r)) return true;
}
return false;
}
它检查元素是否具有面积大于0,然后检查元素的任何部分是否在视口内,并且它没有被另一个元素“遮盖”(实际上我仅在元素中心的一个单点上进行检查,因此无法保证100%——但如果您确实需要,您可以修改脚本以迭代元素的所有点……)。
更新
修改后的 on_top 函数检查每个像素:
on_top = function(r) {
for (var x = Math.floor(r.left), x_max = Math.ceil(r.right); x <= x_max; x++)
for (var y = Math.floor(r.top), y_max = Math.ceil(r.bottom); y <= y_max; y++) {
if (document.elementFromPoint(x, y) === element) return true;
}
return false;
};
不清楚性能方面的情况 :)
height = window.innerHeight?window.innerHeight:document.documentElement.clientHeight;
- Seanonymous有趣的问题。
这是我的方法。
希望对你有所帮助。
目前为止,这就是我做到的。它涵盖了1和3。但是,由于我不太熟悉Prototype(我更喜欢jQuery),所以我仍然在努力解决2。
function isVisible( elem ) {
var $elem = $(elem);
// First check if elem is hidden through css as this is not very costly:
if ($elem.getStyle('display') == 'none' || $elem.getStyle('visibility') == 'hidden' ) {
//elem is set through CSS stylesheet or inline to invisible
return false;
}
//Now check for the elem being outside of the viewport
var $elemOffset = $elem.viewportOffset();
if ($elemOffset.left < 0 || $elemOffset.top < 0) {
//elem is left of or above viewport
return false;
}
var vp = document.viewport.getDimensions();
if ($elemOffset.left > vp.width || $elemOffset.top > vp.height) {
//elem is below or right of vp
return false;
}
//Now check for elements positioned on top:
//TODO: Build check for this using Prototype...
//Neither of these was true, so the elem was visible:
return true;
}
Checking visibility can be a pain, but you can use the Element.getStyle()
method and Element.visible()
methods combined into a custom function. With getStyle()
you can check the actual computed style.
I don't know exactly what you mean by "underneath" :) If you meant by it has a specific ancestor, for example, a wrapper div, you can use Element.up(cssRule)
:
var child = $("myparagraph");
if(!child.up("mywrapper")){
// I lost my mom!
}
else {
// I found my mom!
}
If you want to check the siblings of the child element you can do that too:
var child = $("myparagraph");
if(!child.previous("mywrapper")){
// I lost my bro!
}
else {
// I found my bro!
}
Again, Element lib can help you if I understand correctly what you mean :) You can check the actual dimensions of the viewport and the offset of your element so you can calculate if your element is "off screen".
getStyle()
。为了最大化isMyElementReallyVisible函数的可靠性,你应该结合以下几点:
function isViewable(element){
return (element.clientHeight > 0);
}
/**
* Checks display and visibility of elements and it's parents
* @param DomElement el
* @param boolean isDeep Watch parents? Default is true
* @return {Boolean}
*
* @author Oleksandr Knyga <oleksandrknyga@gmail.com>
*/
function isVisible(el, isDeep) {
var elIsVisible = true;
if("undefined" === typeof isDeep) {
isDeep = true;
}
elIsVisible = elIsVisible && el.offsetWidth > 0 && el.offsetHeight > 0;
if(isDeep && elIsVisible) {
while('BODY' != el.tagName && elIsVisible) {
elIsVisible = elIsVisible && 'hidden' != window.getComputedStyle(el).visibility;
el = el.parentElement;
}
}
return elIsVisible;
}
一个方法是:
isVisible(elm) {
while(elm.tagName != 'BODY') {
if(!$(elm).visible()) return false;
elm = elm.parentNode;
}
return true;
}
致谢:https://github.com/atetlaw/Really-Easy-Field-Validation/blob/master/validation.js#L178
element.getBoundingClientRect()
,它会返回一个带有以下属性的对象:
BoundingClientRect
的宽度和高度是否不为零,因为隐藏或非可见元素的值为零。如果这些值大于零,则该元素应该在页面中可见。然后检查 bottom
属性是否小于 screen.height
,这意味着元素在视口内。(从技术上讲,还需要考虑浏览器窗口的顶部,包括搜索栏、按钮等。)
overflow:hidden
情况的解决方案: https://dev59.com/AI3da4cB1Zd3GeqPyVML - Yuval A.