使用 jQuery 获取 div 的可见高度

Posted

技术标签:

【中文标题】使用 jQuery 获取 div 的可见高度【英文标题】:Get the visible height of a div with jQuery 【发布时间】:2014-09-06 06:34:22 【问题描述】:

我需要检索可滚动区域内 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);
        
    
);

【问题讨论】:

我会研究 vh 单位。 1vh = 视口高度的 1/100。您可能会找到解决方案。找到视口的高度、元素的高度、元素的位置和滚动位置,并据此计算。 假设内部 DIV 上有边距,周围都说“10px”。我会检测滚动高度以查看它是否已通过“10”,然后我将获取父元素的高度,然后根据它的滚动高度减去它。 如果一切都失败了,我刚刚遇到了这个脚本,它看起来可以满足您的需要:larsjung.de/fracs 【参考方案1】:

这是一个快速而肮脏的概念。它基本上将元素的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 - visibleToppx`);


$(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>

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

【讨论】:

我在为多个divs 设置此设置时遇到问题,而无需重复代码。有没有办法做到这一点? @Rev 给你:jsfiddle.net/b5DGj/1。我将每个元素与其自己的函数调用分开。你甚至可以更进一步,定义一个插件来为你做这件事。 我稍微重写了@RoryMcCrossan 的 jQuery 插件功能方法,并将其作为答案发布在下面 - 它可能在该格式中具有更普遍的适用性。 有时一个元素会因为溢出或父元素而被部分隐藏,不管“窗口”是什么【参考方案2】:

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

Fiddle demo

这个小函数将返回一个元素在(垂直)视口中可见的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 demo

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

/**
 * inViewport jQuery plugin by Roko C.B.
 * http://***.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

您的选择器将动态侦听窗口 scrollresize,但也会通过第一个回调函数参数 px 返回 DOM 就绪时的初始值。

【讨论】:

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

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

$.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();

jsFiddle

【讨论】:

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

以上是关于使用 jQuery 获取 div 的可见高度的主要内容,如果未能解决你的问题,请参考以下文章

jQuery 如何获取到隐藏元素的高度?或者在dom元素可见性改变时能触发个事件也行。

js或者jquery如何获取自适应宽度的具体值

JQuery元素滚动定位及获取元素的scrollTop,clientHeight,scrollHeight

JQuery元素滚动定位及获取元素的scrollTop,clientHeight,scrollHeight

Js/Jquery获取网页屏幕可见区域高度

Js/Jquery获取网页屏幕可见区域高度