Получить видимую высоту div с помощью jQuery

Мне нужно получить видимую высоту div в прокручиваемой области. Я считаю себя довольно приличным с jQuery, но это полностью сбивает меня с толку.

предположим, у меня есть красный div в черной обертке:

на рисунке выше функция jQuery вернет 248, видимую часть div.

Как только пользователь прокручивает верхнюю часть div, как на приведенном выше рисунке, он отчет 296.

теперь, как только пользователь прокрутил мимо div, он снова сообщит 248.

очевидно, что мои цифры не будут такими последовательными и ясными, как в этой демонстрации, или я бы просто жесткий код для этих чисел.

У меня есть немного теории:

  • получить высоту окна
  • получить высоту div
  • получите начальное смещение div от верхней части окно
  • получить смещение при прокрутке пользователя.
    • если смещение положительное, это означает, что верхняя часть div все еще видна.
    • если он отрицательный, верхняя часть div была затенена окном. В этот момент div может либо занимать всю высоту окна, либо нижняя часть div может показывать
    • если дно div показывает, то вычислите вне зазор между им и дном окно.

это кажется довольно простым,но я просто не могу понять это. Завтра утром я сделаю еще одну попытку; я просто подумал, что некоторые из вас, гении, могли бы помочь.

спасибо!

UPDATE: я понял это самостоятельно, но похоже, что один из ответов ниже более элегантен, поэтому я буду использовать его вместо этого. Для любопытных, вот что я придумал:

$(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 ответов


вот быстрая и грязная концепция. Он в основном сравнивает 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);

пример скрипку

редактировать - небольшое обновление, чтобы также выполнить логику при изменении размера окна.


вычислить количество 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

ваши селекторы будут динамически слушать window scroll и resize но также Верните начальное значение на DOM ready через первый аргумент функции обратного вызова px.


вот версия подхода Рори выше, за исключением написанного, чтобы функционировать как плагин 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