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

IT技术 javascript jquery zk
2021-03-05 04:59:30

如果 DIV 元素没有脱离屏幕,我需要检查 jQuery。这些元素是可见的,并根据 CSS 属性显示,但可以通过以下方式有意地将它们放置在屏幕外:

position: absolute; 
left: -1000px; 
top: -1000px;

我无法使用 jQuery:visible选择器,因为该元素的高度和宽度不为零。

我没有做任何花哨的事情。这种绝对位置放置是我的Ajax框架实现某些小部件隐藏/显示的方式。

6个回答

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

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

jQuery.expr.filters.offscreen = function(el) {
  var rect = el.getBoundingClientRect();
  return (
           (rect.x + rect.width) < 0 
             || (rect.y + rect.height) < 0
             || (rect.x > window.innerWidth || rect.y > window.innerHeight)
         );
};

然后,您可以通过多种方式使用它:

// returns all elements that are offscreen
$(':offscreen');

// boolean returned if element is offscreen
$('div').is(':offscreen');
@fekirimalek 你是对的,我已经更新了这个例子来说明这一点
2021-04-18 04:59:30
请注意,目前(2017 年 1 月)这至少在 Chrome 上不起作用,因为 Element.getBoundingClientRect() 具有属性 top、right、bottom 和 left 而不是 x 和 y。
2021-04-30 04:59:30
我在这里认为如果 el 将父级(绝对或相对)定位在身体之前就不会这样,我错了吗?
2021-05-05 04:59:30
我喜欢这个,但是如果您的元素在可滚动容器内,它就会中断——2 屏幕高 DIV 底部的元素将始终处于“屏幕外”,因为窗口高度小于元素的 offsetTop。
2021-05-13 04:59:30
@scurker 我无法让它工作。这是我关于这个问题的 SO 问题(使用 jsFiddle):stackoverflow.com/questions/26004098/...
2021-05-15 04:59:30

这里有一个jQuery 插件,它允许用户测试元素是否落在浏览器的可见视口内,同时考虑浏览器的滚动位置。

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

您还可以检查部分可见性:

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

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

这个插件很轻,很容易实现。解决了我在子菜单中遇到的问题。
2021-04-17 04:59:30
这是一个非常轻量级的插件。我能够在向上滚动时获得一个固定的导航栏,并在添加后的几分钟内做出响应。很棒的建议。
2021-05-06 04:59:30

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

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))
    }
});
如果您使用$(this).offset而不是$this.position. 现在它只是计算与它的父级的距离,这可能是一个完美包裹它的 div。
2021-04-22 04:59:30

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

  • 您应该能够选择是希望整个元素显示在屏幕上还是仅显示其中的任何部分
  • 如果元素高于/宽于窗口并且有点覆盖浏览器窗口,建议的解决方案失败

这是我的解决方案,其中包括jQuery .fn实例函数和expression. 我在我的函数中创建了比我所能创建的更多的变量,但是对于复杂的逻辑问题,我喜欢将它分成更小的、明确命名的部分。

我正在使用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);
};
嗨Lurr ...我试过 $("#divId").isOnScreen(true); 其中“divId”在屏幕外,它返回“false”;所以,我觉得它的工作
2021-04-27 04:59:30
我在那里尝试使用你的函数时得到 make_footer_down.js:8 Uncaught TypeError: Cannot read property 'getBoundingClientRect' of undefined。
2021-05-14 04:59:30

我知道这有点晚了,但这个插件应该可以工作。http://remysharp.com/2009/01/26/element-in-view-event-plugin/

$('p.inview').bind('inview', function (event, visible) {
if (visible) {
  $(this).text('You can see me!');
} else {
  $(this).text('Hidden again');
}