Javascript 如何检查元素是否在屏幕外

Javascript 如何检查元素是否在屏幕外,javascript,jquery,zk,Javascript,Jquery,Zk,我需要使用jQuery检查DIV元素是否没有从屏幕上脱落。元素是可见的,并根据CSS属性显示,但可以通过以下方式有意将其置于屏幕外: position: absolute; left: -1000px; top: -1000px; 我无法使用jQuery:visible选择器,因为元素的高度和宽度非零 我没有做任何花哨的事。此绝对位置放置是my framework实现某些小部件的隐藏/显示的方式。您可以使用$(div.position()检查div的位置,并检查左上边距属性是否小于0: i

我需要使用jQuery检查DIV元素是否没有从屏幕上脱落。元素是可见的,并根据CSS属性显示,但可以通过以下方式有意将其置于屏幕外:

position: absolute; 
left: -1000px; 
top: -1000px;
我无法使用jQuery
:visible
选择器,因为元素的高度和宽度非零


我没有做任何花哨的事。此绝对位置放置是my framework实现某些小部件的隐藏/显示的方式。

您可以使用
$(div.position()
检查div的位置,并检查左上边距属性是否小于0:

if($(div).position().left < 0 && $(div).position().top < 0){
    alert("off screen");
}
if($(div.position().left<0&$(div.position().top<0){
警报(“屏幕外”);
}

取决于您对“屏幕外”的定义。这是在视口内,还是在页面定义的边界内

使用可以轻松检测元素是否在视口的边界内(即屏幕上或屏幕外):

有一个允许用户在考虑浏览器滚动位置的情况下,测试元素是否位于浏览器的可见视口中

$('#element').visible();
您还可以检查局部可见性:

$('#element').visible( true);

一个缺点是,它只适用于垂直定位/滚动,尽管在组合中添加水平定位应该很容易。

我知道这有点晚,但这个插件应该可以工作


不需要插件来检查是否在视图端口之外

var w = Math.max(document.documentElement.clientWidth, window.innerWidth || 0)
var h = Math.max(document.documentElement.clientHeight, window.innerHeight || 0)
var d = $(document).scrollTop();

$.each($("div"),function(){
    p = $(this).position();
    //vertical
    if (p.top > h + d || p.top > h - d){
        console.log($(this))
    }
    //horizontal
    if (p.left < 0 - $(this).width() || p.left > w){
        console.log($(this))
    }
});
var w=Math.max(document.documentElement.clientWidth,window.innerWidth|0)
var h=Math.max(document.documentElement.clientHeight,window.innerHeight | | 0)
var d=$(document.scrollTop();
$。每个($(“div”),函数(){
p=$(this.position();
//垂直的
如果(p.top>h+d | | p.top>h-d){
console.log($(this))
}
//水平的
如果(p.left<0-$(this).width()| | p.left>w){
console.log($(this))
}
});

嗯。。。我在这里提出的每个解决方案中都发现了一些问题

  • 您应该能够选择是希望整个元素出现在屏幕上,还是希望只是其中的任何部分
  • 如果元素比窗口高/宽,并且有点覆盖了浏览器窗口,则建议的解决方案将失败
下面是我的解决方案,其中包括
jQuery
.fn实例函数和
表达式。我在函数中创建了比我所能创建的更多的变量,但对于复杂的逻辑问题,我喜欢将其划分为更小的、名称明确的部分

我正在使用
getBoundingClientRect
方法返回元素相对于视口的位置,因此我不需要关心滚动位置

使用

$(".some-element").filter(":onscreen").doSomething();
$(".some-element").filter(":entireonscreen").doSomething();
$(".some-element").isOnScreen(); // true / false
$(".some-element").isOnScreen(true); // true / false (partially on screen)
$(".some-element").is(":onscreen"); // true / false (partially on screen)
$(".some-element").is(":entireonscreen"); // true / false 
$.fn.isOnScreen = function(partial){

    //let's be sure we're checking only one element (in case function is called on set)
    var t = $(this).first();

    //we're using getBoundingClientRect to get position of element relative to viewport
    //so we dont need to care about scroll position
    var box = t[0].getBoundingClientRect();

    //let's save window size
    var win = {
        h : $(window).height(),
        w : $(window).width()
    };

    //now we check against edges of element

    //firstly we check one axis
    //for example we check if left edge of element is between left and right edge of scree (still might be above/below)
    var topEdgeInRange = box.top >= 0 && box.top <= win.h;
    var bottomEdgeInRange = box.bottom >= 0 && box.bottom <= win.h;

    var leftEdgeInRange = box.left >= 0 && box.left <= win.w;
    var rightEdgeInRange = box.right >= 0 && box.right <= win.w;


    //here we check if element is bigger then window and 'covers' the screen in given axis
    var coverScreenHorizontally = box.left <= 0 && box.right >= win.w;
    var coverScreenVertically = box.top <= 0 && box.bottom >= win.h;

    //now we check 2nd axis
    var topEdgeInScreen = topEdgeInRange && ( leftEdgeInRange || rightEdgeInRange || coverScreenHorizontally );
    var bottomEdgeInScreen = bottomEdgeInRange && ( leftEdgeInRange || rightEdgeInRange || coverScreenHorizontally );

    var leftEdgeInScreen = leftEdgeInRange && ( topEdgeInRange || bottomEdgeInRange || coverScreenVertically );
    var rightEdgeInScreen = rightEdgeInRange && ( topEdgeInRange || bottomEdgeInRange || coverScreenVertically );

    //now knowing presence of each edge on screen, we check if element is partially or entirely present on screen
    var isPartiallyOnScreen = topEdgeInScreen || bottomEdgeInScreen || leftEdgeInScreen || rightEdgeInScreen;
    var isEntirelyOnScreen = topEdgeInScreen && bottomEdgeInScreen && leftEdgeInScreen && rightEdgeInScreen;

    return partial ? isPartiallyOnScreen : isEntirelyOnScreen;

};

$.expr.filters.onscreen = function(elem) {
  return $(elem).isOnScreen(true);
};

$.expr.filters.entireonscreen = function(elem) {
  return $(elem).isOnScreen(true);
};
来源

$(".some-element").filter(":onscreen").doSomething();
$(".some-element").filter(":entireonscreen").doSomething();
$(".some-element").isOnScreen(); // true / false
$(".some-element").isOnScreen(true); // true / false (partially on screen)
$(".some-element").is(":onscreen"); // true / false (partially on screen)
$(".some-element").is(":entireonscreen"); // true / false 
$.fn.isOnScreen = function(partial){

    //let's be sure we're checking only one element (in case function is called on set)
    var t = $(this).first();

    //we're using getBoundingClientRect to get position of element relative to viewport
    //so we dont need to care about scroll position
    var box = t[0].getBoundingClientRect();

    //let's save window size
    var win = {
        h : $(window).height(),
        w : $(window).width()
    };

    //now we check against edges of element

    //firstly we check one axis
    //for example we check if left edge of element is between left and right edge of scree (still might be above/below)
    var topEdgeInRange = box.top >= 0 && box.top <= win.h;
    var bottomEdgeInRange = box.bottom >= 0 && box.bottom <= win.h;

    var leftEdgeInRange = box.left >= 0 && box.left <= win.w;
    var rightEdgeInRange = box.right >= 0 && box.right <= win.w;


    //here we check if element is bigger then window and 'covers' the screen in given axis
    var coverScreenHorizontally = box.left <= 0 && box.right >= win.w;
    var coverScreenVertically = box.top <= 0 && box.bottom >= win.h;

    //now we check 2nd axis
    var topEdgeInScreen = topEdgeInRange && ( leftEdgeInRange || rightEdgeInRange || coverScreenHorizontally );
    var bottomEdgeInScreen = bottomEdgeInRange && ( leftEdgeInRange || rightEdgeInRange || coverScreenHorizontally );

    var leftEdgeInScreen = leftEdgeInRange && ( topEdgeInRange || bottomEdgeInRange || coverScreenVertically );
    var rightEdgeInScreen = rightEdgeInRange && ( topEdgeInRange || bottomEdgeInRange || coverScreenVertically );

    //now knowing presence of each edge on screen, we check if element is partially or entirely present on screen
    var isPartiallyOnScreen = topEdgeInScreen || bottomEdgeInScreen || leftEdgeInScreen || rightEdgeInScreen;
    var isEntirelyOnScreen = topEdgeInScreen && bottomEdgeInScreen && leftEdgeInScreen && rightEdgeInScreen;

    return partial ? isPartiallyOnScreen : isEntirelyOnScreen;

};

$.expr.filters.onscreen = function(elem) {
  return $(elem).isOnScreen(true);
};

$.expr.filters.entireonscreen = function(elem) {
  return $(elem).isOnScreen(true);
};
$.fn.isOnScreen=函数(部分){
//让我们确保只检查一个元素(以防在集合上调用函数)
var t=$(this.first();
//我们使用getBoundingClientRect获取元素相对于视口的位置
//所以我们不需要关心滚动位置
var-box=t[0]。getBoundingClientRect();
//让我们节省窗口大小
var win={
h:$(窗口).height(),
w:$(窗口).width()
};
//现在我们检查元素的边
//首先我们检查一个轴
//例如,我们检查元素的左边缘是否在scree的左边缘和右边缘之间(仍然可能在上方/下方)
var topEdgeInRange=box.top>=0&&box.top=0&&box.bottom=0&&box.left=0&&box.right
  • 获取距给定元素顶部的距离
  • 添加相同给定元素的高度。这将告诉您从屏幕顶部到给定元素末尾的总数
  • 然后你所要做的就是从总文档高度中减去它

    jQuery(function () {
        var documentHeight = jQuery(document).height();
        var element = jQuery('#you-element');
        var distanceFromBottom = documentHeight - (element.position().top + element.outerHeight(true));
        alert(distanceFromBottom)
    });
    

我喜欢这样,但是如果元素在可滚动的容器中,它就会崩溃——一个2屏高的DIV底部的元素将始终是“屏幕外”的,因为窗口高度小于元素的偏移。@scurker我无法实现这一点。这是我的SO问题(使用jsFiddle)关于这个问题:如果el将父元素(绝对或相对)放在身体之前,我认为这不会发生,这是错误的吗?@fekirimalek你是对的,我已经更新了这个例子来说明这一点,注意到目前(2017年1月)这至少在Chrome上不起作用,因为Element.getBoundingClientRect()属性是top、right、bottom和left,而不是x和y。如果div在视图中不是负数怎么办?我在这个“重复”的问题上也给出了答案:我得到make_footer_down.js:8 Uncaught TypeError:在尝试使用我们的函数时无法读取未定义的属性“getBoundingClientRect”。嗨,Lurr…我试过$(“#divId”).isOnScreen(真);其中'divId'在屏幕外,它返回我'false';因此,我觉得它的工作是一个非常轻的插件。我能够得到一个固定的导航栏,并在添加它后几分钟内响应工作。很好的建议。这个插件非常轻,很容易实现。解决了我与子菜单的问题。如果您使用了
$(this.offset
而不是
$this.position
。现在它只是在计算距离其父对象的距离,这可能是一个完美包裹它的div。
jQuery(function () {
    var documentHeight = jQuery(document).height();
    var element = jQuery('#you-element');
    var distanceFromBottom = documentHeight - (element.position().top + element.outerHeight(true));
    alert(distanceFromBottom)
});