使用jQuery获取div的可见高度


86

我需要检索可滚动区域内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。您可能会找到一个解决方案。找到视口的高度,元素的高度,元素的位置和滚动位置,然后进行相应的计算。
davidcondrey

假设内部DIV上有余量,则四周都说“ 10px”。我将检测滚动高度以查看是否已通过“ 10”,然后我将获取父元素的高度,并根据其滚动高度减去它。

如果其他所有方法都失败了,那么我只是遇到了这个脚本,它似乎可以满足
davidcondrey 2014年

Answers:


57

这是一个快速而肮脏的概念。基本上,它将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(visibleBottom - visibleTop);
}

$(window).on('scroll resize', getVisible);

小提琴的例子

编辑-小更新,在调整窗口大小时也执行逻辑。


我在div不重复代码的情况下很难将其设置为多个。有没有办法做到这一点?
JacobTheDev 2014年

2
@Rev,您可以前往:jsfiddle.net/b5DGj/1。我将每个元素都分离为其自己的函数调用。您甚至可以进一步定义一个插件来为您执行此操作。
罗里·麦克罗森

我略微重写了@RoryMcCrossan用作jQuery插件的方法,并将其作为答案发布在下面-该格式可能具有更一般的适用性。
Michael.Lumley 2015年

有时元素可能由于溢出或父元素而被部分隐藏,而不管“窗口”是什么
Nadav B

55

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

小提琴演示

这个微小的函数将返回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

您的选择器将动态监听窗口scrollresize并且还会通过第一个回调函数参数返回DOM ready上的初始值px


要在Android Chrome上运行,您可能需要添加<meta name="viewport" content="width=your_size">到head html部分。
userlond '16

@userlond感谢您的贡献,但我不确定content="width=1259"是否适合大多数人。您尝试过content="width=device-width, initial-scale=1"吗?
Roko C. Buljan '16

网站具有固定宽度的旧版模板,并且没有响应...我认为您的建议对大多数人来说是可以的。因此,需要澄清一下:如果Roko C. Buljan的解决方案不起作用,请尝试添加<meta name="viewport" content="your_content">声明:)
userlond

这太棒了,非常接近我一直在寻找的东西。如何计算从元素底部到窗口底部的距离?因此,在您看到内容结尾之前,我可以加载更多内容。例如,如果windowBot的elBottom <200,则启动AJAX。
Thom

1
@Thom好,上述方法不会返回任何其他特定值(可以扩展为返回除visible height px诸如对象之类的东西之外的更多东西。请参见此小提琴以获得这样的想法:jsfiddle.net/RokoCB/6xjq5gyy(开放的开发者控制台)查看日志)
Roko C. Buljan '17

11

这是上面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();

jsFiddle


2
如果窗口变大并且块可以容纳,请勿使用。这就是为什么我们需要重置块的高度:$(this).css('height',''); jsfiddle.net/b5DGj/144
Max Koshel
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.