使用 jQuery 获取 div 的可见高度

IT技术 javascript jquery height visible
2021-01-18 06:08:32

我需要在可滚动区域内检索 div 的可见高度。我认为自己使用 jQuery 还算不错,但这完全让我失望。

假设我有一个黑色包装内的红色 div:

在上图中,jQuery 函数将返回 248,即 div 的可见部分。

一旦用户滚动超过 div 的顶部,如上图所示,它将报告 296。

现在,一旦用户滚动过 div,它会再次报告 248。

显然,我的数字不会像本演示中那样一致和清晰,或者我只是对这些数字进行硬编码。

我有一个理论:

  • 获取窗口的高度
  • 获取div的高度
  • 获取 div 距窗口顶部的初始偏移量
  • 获取用户滚动时的偏移量。
    • 如果偏移量为正,则表示 div 的顶部仍然可见。
    • 如果它是负数,则 div 的顶部已经被窗口遮住了。此时,div 可以占据窗口的整个高度,也可以显示 div 的底部
    • 如果显示 div 的底部,请找出它与窗口底部之间的间隙。

这看起来很简单,但我就是无法理解它。明天早上我再吃一次;我只是想你们中的一些天才可能会提供帮助。

谢谢!

更新:我自己发现了这一点,但看起来下面的答案之一更优雅,所以我将改用它。对于好奇,这是我想出的:

$(document).ready(function() {
    var windowHeight = $(window).height();
    var overviewHeight = $("#overview").height();
    var overviewStaticTop = $("#overview").offset().top;
    var overviewScrollTop = overviewStaticTop - $(window).scrollTop();
    var overviewStaticBottom = overviewStaticTop + $("#overview").height();
    var overviewScrollBottom = windowHeight - (overviewStaticBottom - $(window).scrollTop());
    var visibleArea;
    if ((overviewHeight + overviewScrollTop) < windowHeight) {
        // alert("bottom is showing!");
        visibleArea = windowHeight - overviewScrollBottom;
        // alert(visibleArea);
    } else {
        if (overviewScrollTop < 0) {
            // alert("is full height");
            visibleArea = windowHeight;
            // alert(visibleArea);
        } else {
            // alert("top is showing");
            visibleArea = windowHeight - overviewScrollTop;
            // alert(visibleArea);
        }
    }
});
3个回答

计算元素(高度)在视口中的像素数量

小提琴演示

这个小函数将返回px在(垂直)视口中可见的元素数量

function inViewport($el) {
    var elH = $el.outerHeight(),
        H   = $(window).height(),
        r   = $el[0].getBoundingClientRect(), t=r.top, b=r.bottom;
    return Math.max(0, t>0? Math.min(elH, H-t) : Math.min(b, H));
}

像这样使用:

$(window).on("scroll resize", function(){
  console.log( inViewport($('#elementID')) ); // n px in viewport
});

而已。


jQuery.inViewport()插件

jsFiddle 演示

从上面你可以提取逻辑并创建一个像这样的插件:

/**
 * inViewport jQuery plugin by Roko C.B.
 * http://stackoverflow.com/a/26831113/383904
 * Returns a callback function with an argument holding
 * the current amount of px an element is visible in viewport
 * (The min returned value is 0 (element outside of viewport)
 */
;(function($, win) {
  $.fn.inViewport = function(cb) {
     return this.each(function(i,el) {
       function visPx(){
         var elH = $(el).outerHeight(),
             H = $(win).height(),
             r = el.getBoundingClientRect(), t=r.top, b=r.bottom;
         return cb.call(el, Math.max(0, t>0? Math.min(elH, H-t) : Math.min(b, H)));  
       }
       visPx();
       $(win).on("resize scroll", visPx);
     });
  };
}(jQuery, window));

像这样使用:

$("selector").inViewport(function(px) {
  console.log( px ); // `px` represents the amount of visible height
  if(px > 0) {
    // do this if element enters the viewport // px > 0
  }else{
    // do that if element exits  the viewport // px = 0
  }
}); // Here you can chain other jQuery methods to your selector

您的选择器将动态侦听 windowscroll并且resize还会通过第一个回调函数参数返回 DOM ready 的初始值px

@Thom 好吧,上面的方法不返回任何其他特定的值(它可以扩展以返回更多的东西,而不仅仅是visible height px一个对象,例如一个对象。有关这样的想法,请参阅此小提琴:jsfiddle.net/RokoCB/6xjq5gyy(打开开发人员控制台)查看日志)
2021-03-23 06:08:32
站点具有固定宽度的旧模板并且没有响应......我认为您的建议对大多数人来说都可以。所以澄清一下:如果 Roko C. Buljan 的解决方案不起作用,请尝试添加<meta name="viewport" content="your_content">声明:)
2021-03-25 06:08:32
这太棒了,太接近我一直在寻找的东西了。如何计算元素底部到窗口底部的距离?所以我可以在你看到内容的结尾之前加载更多的内容。例如,如果 windowBot 的 elBottom < 200,则触发 AJAX。
2021-04-03 06:08:32
要在 Android Chrome 上工作,您可能需要添加<meta name="viewport" content="width=your_size">到 head html 部分。
2021-04-06 06:08:32
@userlond 感谢您的贡献,但我不确定content="width=1259"是否适合大多数人。你试过content="width=device-width, initial-scale=1"吗?
2021-04-06 06:08:32

这是一个快速而肮脏的概念。它基本上将offset().top元素的 与窗口顶部和窗口offset().top + height()底部进行比较:

function getVisible() {
  var $el = $('#foo'),
    scrollTop = $(this).scrollTop(),
    scrollBot = scrollTop + $(this).height(),
    elTop = $el.offset().top,
    elBottom = elTop + $el.outerHeight(),
    visibleTop = elTop < scrollTop ? scrollTop : elTop,
    visibleBottom = elBottom > scrollBot ? scrollBot : elBottom;
  $('#notification').text(`Visible height of div: ${visibleBottom - visibleTop}px`);
}

$(window).on('scroll resize', getVisible).trigger('scroll');
html,
body {
  margin: 100px 0;
}

#foo {
  height: 1000px;
  background-color: #C00;
  width: 200px;
  margin: 0 auto;
}

#notification {
  position: fixed;
  top: 0;
  left: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<div id="foo"></div>
<div id="notification"></div>

如有必要,逻辑可以更简洁,我刚刚为这个例子声明了单独的变量,以使计算尽可能清晰。

我稍微重写了@RoryMcCrossan 的作为 jQuery 插件运行的方法,并将其作为答案发布在下面 - 它在该格式中可能具有更广泛的适用性。
2021-03-25 06:08:32
有时一个元素会因为溢出或父元素而被部分隐藏,不管“窗口”如何
2021-03-30 06:08:32
我无法div在不重复代码的情况下为多个s设置它有没有办法做到这一点?
2021-04-08 06:08:32
@Rev 给你:jsfiddle.net/b5DGj/1我将每个元素分开到它自己的函数调用中。你甚至可以更进一步,定义一个插件来为你做这件事。
2021-04-08 06:08:32

这是上面 Rory 方法的一个版本,除了编写为用作 jQuery 插件之外。它在该格式中可能具有更广泛的适用性。很好的答案,罗里 - 谢谢!

$.fn.visibleHeight = function() {
    var elBottom, elTop, scrollBot, scrollTop, visibleBottom, visibleTop;
    scrollTop = $(window).scrollTop();
    scrollBot = scrollTop + $(window).height();
    elTop = this.offset().top;
    elBottom = elTop + this.outerHeight();
    visibleTop = elTop < scrollTop ? scrollTop : elTop;
    visibleBottom = elBottom > scrollBot ? scrollBot : elBottom;
    return visibleBottom - visibleTop
}

可以通过以下方式调用:

$("#myDiv").visibleHeight();

js小提琴

当窗口变大并且块可以容纳时不要工作。这就是为什么我们需要重置块高度: $(this).css('height', ''); jsfiddle.net/b5DGj/144
2021-03-30 06:08:32