Получить видимую высоту 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 70

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);

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

edit - небольшое обновление для выполнения логики при изменении размера окна.

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

ваши селекторы будут динамически прослушивать окно 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