繁体   English   中英

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

[英]How to check if an element is off-screen

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

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

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

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

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

使用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');

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

$('#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))
    }
});

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

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

这是我的解决方案,其中包括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);
};

我创建了一个小插件来执行此操作 ,它具有一些灵活的选项(在您调整浏览器窗口大小时也可以使用)。

我知道这有点晚了,但这个插件应该可以工作。 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');
}
  • 获取到给定元素顶部的距离
  • 添加相同给定元素的高度。 这将告诉您从屏幕顶部到给定元素末尾的总数。
  • 然后你所要做的就是从文档总高度中减去它

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

尽管最初的发帖人要求使用 JQuery 解决方案,但他们还在问题上添加了一个 JavaScript 标记,这也允许添加这个更现代的解决方案:

TLDR:使用IntersectionObserver API

以下是我在原生 JavaScript 和 React 中制作的两个沙箱,用于在工作示例中展示这一点:

  1. Vanilla JavaScript 示例沙箱
  2. React 示例沙箱(使用 react-intersection-observer NPM 模块)

更长一点的答案:这个问题被问到已经有 10 多年了,当时使用这些 JQuery 解决方案是有意义的,但是今天我们不再需要 JQuery 来满足这种需求了:

Intersection Observer API 提供了一种方法来观察目标元素与祖先元素或顶级文档视口的交集的变化。

它很容易使用,首先创建一个观察者并在它被触发时传递你想要做的事情(一个回调函数),并且还可以选择传递一个选项对象,例如,在这个问题的情况下,我们需要threshold 选项,值为 1 以确保元素完全在视口内,如果不是,那么我们将知道它是“屏幕外”:

const doable = () => {
  //do something
}
const observer = new IntersectionObserver(doable, { threshold: 1 });

现在调用它的observe()方法并将你想要观察的元素传递给它:

observer.observe(observee)

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

if($(div).position().left < 0 && $(div).position().top < 0){
    alert("off screen");
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM