Отримати видиму висоту div за допомогою jQuery


86

Мені потрібно отримати видиму висоту div у прокручуваній області. Я вважаю себе досить пристойним з jQuery, але це мене повністю відкидає.

Скажімо, у мене є червоний div у чорній обгортці:

На графіку вище функція jQuery повертає 248, видиму частину div.

Як тільки користувач прокрутить верхню частину div, як на графіку вище, він повідомить 296.

Тепер, як тільки користувач прокрутив повз div, він знову повідомить про 248.

Очевидно, що мої номери не будуть такими ж послідовними та чіткими, як у цій демонстрації, або я б просто вказав ці цифри.

У мене є трохи теорії:

  • Отримати висоту вікна
  • Отримати висоту 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", тоді я просто отримав би висоту батьківського елемента, відніс би її на основі висоти прокрутки.

Якщо все інше не вдається, я щойно натрапив на цей сценарій, який, схоже, може слугувати потрібній вам цілі: larsjung.de/fracs
davidcondrey

Відповіді:


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

2
@Rev ось ви йдете: jsfiddle.net/b5DGj/1 . Я розділив кожен елемент на власний виклик функції. Ви навіть можете піти далі і визначити плагін, який зробить це за вас.
Rory McCrossan

Я трохи переписав підхід @ RoryMcCrossan до роботи як плагін jQuery і опублікував його як відповідь нижче - він може мати більш загальну застосовність у цьому форматі.
Майкл Ламлі,

Іноді елемент може бути частково прихований через переповнення або батьківські елементи, незалежно від "вікна"
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
});

Це воно.


.inViewport()плагін jQuery

демонстрація 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 готового кориті першої функції зворотного виклику аргумент px.


Для роботи з Android Chrome вам може знадобитися додати <meta name="viewport" content="width=your_size">в головний html розділ.
userlond

@userlond дякую за ваш внесок, але я не впевнений, що content="width=1259"може підійти для більшості. Ви намагалися content="width=device-width, initial-scale=1"замість цього?
Roko C. Buljan

Сайт має застарілий шаблон із фіксованою шириною і не реагує ... Я думаю, що ваші пропозиції будуть нормальними для більшості. Тож для уточнення: якщо рішення Роко К. Буляна не працює, спробуйте додати <meta name="viewport" content="your_content">декларацію :)
userlond

Це так чудово і так близько до того, що я шукав. Як я можу розрахувати відстань від елементів до низу вікна? Тож я можу завантажити більше вмісту, перш ніж ви побачите кінець вмісту. Наприклад, якщо elBottom <200 з windowBot, запустіть AJAX.
Том

1
@ Тож, вищезазначений метод не повертає жодних інших конкретних значень (його можна розширити, щоб повернути більше речей, ніж просто visible height px, наприклад, об'єкт. Дивіться цю скрипту для такої ідеї: jsfiddle.net/RokoCB/6xjq5gyy (відкрита консоль розробника) бачити журнали)
Roko C. Buljan

11

Ось версія підходу Рорі вище, за винятком написаної для функціонування як плагін 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
Макс
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.