Як перевірити, чи елемент видно після прокрутки?


1169

Я завантажую елементи через AJAX. Деякі з них видно, лише якщо прокрутити сторінку вниз.
Чи я можу дізнатись, чи знаходиться елемент у видимій частині сторінки?


42
він означає, що він хоче, щоб метод дізнався, чи відображається певний елемент у вікні браузера, чи користувачеві потрібно прокрутити його, щоб побачити його.
Ромен Лінсолас

1
Щоб перевірити, чи елемент повністю видно в контейнері, просто додайте додатковий параметр вибору та повторно використовуйте для цього елем-код. Library.IsElementVisibleInContainer = function (elementSelector, containerSelector) { var containerViewTop = $(containerSelector).offset().top; var containerViewBottom = containerViewTop + $(containerSelector).height();
Життя



1
Усі відповіді викликають поповнення, так що це може бути шийка пляшки, ви кричите використовувати IntersectionObserver, якщо підтримується. Він матиме кращі показники роботи в сучасних браузерах,
jcubic

Відповіді:


1258

Для цього слід зробити фокус:

function isScrolledIntoView(elem)
{
    var docViewTop = $(window).scrollTop();
    var docViewBottom = docViewTop + $(window).height();

    var elemTop = $(elem).offset().top;
    var elemBottom = elemTop + $(elem).height();

    return ((elemBottom <= docViewBottom) && (elemTop >= docViewTop));
}

Проста функція утиліти Це дозволить викликати функцію утиліти, яка приймає шуканий елемент і якщо ви хочете, щоб елемент повністю переглянувся або частково.

function Utils() {

}

Utils.prototype = {
    constructor: Utils,
    isElementInView: function (element, fullyInView) {
        var pageTop = $(window).scrollTop();
        var pageBottom = pageTop + $(window).height();
        var elementTop = $(element).offset().top;
        var elementBottom = elementTop + $(element).height();

        if (fullyInView === true) {
            return ((pageTop < elementTop) && (pageBottom > elementBottom));
        } else {
            return ((elementTop <= pageBottom) && (elementBottom >= pageTop));
        }
    }
};

var Utils = new Utils();

Використання

var isElementInView = Utils.isElementInView($('#flyout-left-container'), false);

if (isElementInView) {
    console.log('in view');
} else {
    console.log('out of view');
}

52
Зауважте, що це працює лише в тому випадку, якщо документ є елементом прокрутки, тобто ви не перевіряєте видимість якогось елемента всередині внутрішньої панелі прокрутки.
Андрій Б.

8
як додати трохи зміщення?
Юрген Пол

5
Працював лише тоді, коли я використовував window.innerHeightзамість цього
Крістіан Шнорр

2
Бо elemTopя звик $(elem).position().topі для того, що elemBottomя використовував elemTop + $(elem).outerHeight(true).
Сара Везелс

13
Для: "Будь-яка частина елемента у перегляді" я використовувала: (((elemTop> = docViewTop) && (elemTop <= docViewBottom)) || ((elemBottom> = docViewTop) && (elemBottom <= docViewBottom)))
Grizly

415

Ця відповідь у ванілі:

function isScrolledIntoView(el) {
    var rect = el.getBoundingClientRect();
    var elemTop = rect.top;
    var elemBottom = rect.bottom;

    // Only completely visible elements return true:
    var isVisible = (elemTop >= 0) && (elemBottom <= window.innerHeight);
    // Partially visible elements return true:
    //isVisible = elemTop < window.innerHeight && elemBottom >= 0;
    return isVisible;
}

27
не повинно бути цього isVisible = elementTop < window.innerHeight && elementBottom >= 0? Інакше половина елемента на екрані повертає значення false.
gman

7
ні. я перевіряю, чи якийсь елемент повністю видно на сторінці. якщо ви хочете перевірити видимість якоїсь частини - ви можете налаштувати цей фрагмент.
bravedick

15
Я вважаю цю відповідь кращою, ніж обрана відповідь. Простіше теж.
Адам Венеція

12
У порівнянні із схваленою відповіддю, це робить waaaay набагато краще із сотнями елементів.
ncla

5
дивіться невелику скрипку, яка демонструє тут - jsfiddle.net/shaaraddalvi/4rp09jL0
upInCloud

122

Оновлення: використовуйте IntersectionObserver


Найкращий метод, який я знайшов поки що, - це плагін jQuery з'являються . Працює як шарм.

Імітує спеціальну подію "з'являтися", яка запускається, коли елемент прокручується до перегляду чи іншим чином стає видимим для користувача.

$('#foo').appear(function() {
  $(this).text('Hello world');
});

Цей плагін можна використовувати для запобігання непотрібних запитів на вміст, прихований або поза зоною видимості.


30
Це класний плагін, без сумніву, але не відповідає на питання.
Джон Адамс

5
Хоча плагін jQuery з’являється добре для вмісту на головній сторінці сторінки, він, на жаль, має проблеми із прокручуванням дивів фіксованого розміру із переповненням. Подія може запуститися передчасно, коли зв'язаний елемент знаходиться у зоні видимості сторінки, але поза зоною видимості div, а потім не запускається, як очікувалося, коли елемент потрапляє у поле перегляду.
Пітер

17
Чи є плагін зникнення?
Шамун

3
@Shamoon перевірити джерело на, appear pluginі вам, ймовірно, просто потрібно буде !десь додати, щоб отримати disappearплагін.
Lucky Soni

5
Як зауважимо, це не працює з jQuery 1.11.X github.com/morr/jquery.appear/isissue/37
Джейсон Пархам

86

Ось моє чисте рішення JavaScript, яке працює, якщо воно також приховане всередині контейнера, який прокручується.

Демонструйте тут (спробуйте також змінити розмір вікна)

var visibleY = function(el){
  var rect = el.getBoundingClientRect(), top = rect.top, height = rect.height, 
    el = el.parentNode
  // Check if bottom of the element is off the page
  if (rect.bottom < 0) return false
  // Check its within the document viewport
  if (top > document.documentElement.clientHeight) return false
  do {
    rect = el.getBoundingClientRect()
    if (top <= rect.bottom === false) return false
    // Check if the element is out of view due to a container scrolling
    if ((top + height) <= rect.top) return false
    el = el.parentNode
  } while (el != document.body)
  return true
};

EDIT 2016-03-26: Я оновив рішення для обліку прокрутки повз елемент, щоб він був прихованим над вершиною контейнера, який може прокручуватися. EDIT 2018-10-08: Оновлено для обробки, коли прокручується з виду над екраном.


дякую, можливо, краще бути return top <= document.documentElement.clientHeight && top >= 0;
Юсеф Салімпур

16
+1 Це була єдина кодована (тобто не третя сторона) відповідь, яка враховує рекурсивний характер елементів. Я розширив обробку горизонтальної, вертикальної та прокрутки сторінок: jsfiddle.net/9nuqpgqa
Pebbl

3
Це рішення перевіряє лише верхню частину елемента. Якщо перший верхній піксель видно, він повернеться істинним, навіть якщо решта елемента не буде видно. Щоб перевірити, чи видно весь елемент, вам також потрібно перевірити властивість нижнього.
Войцех Якубас

2
Ага, акуратно! Використовується, щоб допомогти написати цю відповідь (з кредитом як js коментар).
Roamer-1888

Відсутній; після другого "повернення помилкового" в циклі
Михайло Рамендик

45

Використання API IntersectionObserver (рідний у сучасних браузерах)

За допомогою спостерігача легко визначити, чи видно елемент у вікні перегляду або в будь-якому контейнері, що прокручується, легко та ефективно .

Необхідність приєднувати scrollподію та вручну перевіряти зворотний виклик події усувається, таким чином ефективність:

// this is the target which is observed
var target = document.querySelector('div');

// configure the intersection observer instance
var intersectionObserverOptions = {
  root: null,
  rootMargin: '150px',
  threshold: 1.0
}
    
var observer = new IntersectionObserver(onIntersection, intersectionObserverOptions);

// provide the observer with a target
observer.observe(target);

function onIntersection(entries){
  entries.forEach(entry => {
    console.clear();
    console.log(entry.intersectionRatio)
    target.classList.toggle('visible', entry.intersectionRatio > 0);
    
    // Are we in viewport?
    if (entry.intersectionRatio > 0) {
      // Stop watching 
      // observer.unobserve(entry.target);
    }
  });
}
.box{ width:100px; height:100px; background:red; margin:1000px; }
.box.visible{ background:green; }
Scroll both Vertically & Horizontally...
<div class='box'></div>


Перегляд таблиці підтримки браузерів (не підтримується в IE / Safari)


4
Дякую! Це працює для мене, і він також отримав це, працюючи в IE11 з github.com/w3c/IntersectionObserver
Метт Вілсон

На сьогодні найкраще рішення. Працювали в IE11 без поліфазу!
Фабіан фон Еллертс

Зауважте, що цей ПОСЛІД не підтримується в iOS / macOS Safari, на жаль. Не забудьте перевірити проблеми з парфумерією, якщо ви вирішили поліфінікувати, це велика група користувачів
Leland

@Leland - це залежить від проекту. для всіх моїх проектів це абсолютно 0 користувачів. Я не будую веб-сайти, а веб-систему;)
vsync

Я намагаюся запустити це в циклі на декількох елементах, але це не працює. Будь-які ідеї? Я додаю елемент для націлювання в цьому циклі.
Саша Гріндау

42

Плагін jQuery Waypoints тут дуже приємний.

$('.entry').waypoint(function() {
   alert('You have scrolled to an entry.');
});

На сайті плагіна є кілька прикладів .


3
Для мене це працювало лише зі зміщенням $('#my-div').waypoint(function() { console.log('Hello there!'); }, { offset: '100%' });
leymannx

21

Як щодо

function isInView(elem){
   return $(elem).offset().top - $(window).scrollTop() < $(elem).height() ;
}

Після цього ви можете запускати все, що завгодно, як тільки елемент виглядає таким чином

$(window).scroll(function(){
   if (isInView($('.classOfDivToCheck')))
      //fire whatever you what 
      dothis();
})

Це працює для мене просто чудово


1
Це працює для мене, але я використав, здавалося б , більш повна, функція isScrolledIntoView в stackoverflow.com/questions/487073 / ... :)
Meetai.com

3
Я думаю, що це має бути $ (window) .scrollTop () <$ (elem) .offset (). Top + $ (elem) .height ();
Молодий

Моя модифікація буде такою: `return $ (window) .scrollTop () + $ (window) .height ()> $ (elem) .offset (). Top + $ (elem) .height (); `
bubencode

15

WebResourcesDepot написав сценарій для завантаження під час прокрутки, який використовував jQuery деякий час тому. Ви можете переглянути їх демонстрацію наживо тут . Яловичина їх функціональності полягала в наступному:

$(window).scroll(function(){
  if  ($(window).scrollTop() == $(document).height() - $(window).height()){
    lastAddedLiveFunc();
  }
});

function lastAddedLiveFunc() { 
  $('div#lastPostsLoader').html('<img src="images/bigLoader.gif">');
  $.post("default.asp?action=getLastPosts&lastPostID="+$(".wrdLatest:last").attr("id"),
    function(data){
        if (data != "") {
          $(".wrdLatest:last").after(data);         
        }
      $('div#lastPostsLoader').empty();
    });
};

15

Класна функція Твітка Скотта Доудінга на мою вимогу - це використовується для визначення того, чи елемент просто прокрутився на екран, тобто це верхній край.

function isScrolledIntoView(elem)
{
    var docViewTop = $(window).scrollTop();
    var docViewBottom = docViewTop + $(window).height();
    var elemTop = $(elem).offset().top;
    return ((elemTop <= docViewBottom) && (elemTop >= docViewTop));
}

12

Звичайна ваніль, щоб перевірити, чи elвидно елемент ( ) у ділі, що прокручується ( holder)

function isElementVisible (el, holder) {
  holder = holder || document.body
  const { top, bottom, height } = el.getBoundingClientRect()
  const holderRect = holder.getBoundingClientRect()

  return top <= holderRect.top
    ? holderRect.top - top <= height
    : bottom - holderRect.bottom <= height
},

Використання jQuery:

var el = $('tr:last').get(0);
var holder = $('table').get(0);
isVisible =  isScrolledIntoView(el, holder);

2
У цю епоху програм для одноразових програм стало частіше перевіряти, чи елемент видно в іншому елементі, крім вікна . Ось чому цей отримує мою репутацію.
Н Собака

8

isScrollIntoView - дуже потрібна функція, тому я спробував це, він працює для елементів, які не є більшими, ніж вікно перегляду, але якщо елемент більший, оскільки огляд перегляду, він не працює. Щоб виправити це, легко змініть умову

return ((elemBottom <= docViewBottom) && (elemTop >= docViewTop));

до цього:

return (docViewBottom >= elemTop && docViewTop <= elemBottom);

Дивіться демонстрацію тут: http://jsfiddle.net/RRSmQ/


8

Більшість відповідей тут не враховує, що елемент також може бути прихований, оскільки він прокручується з-за погляду не лише всієї сторінки.

Щоб покрити таку можливість, вам в основному потрібно перевірити, чи розташований елемент у межах кожного з його батьків.

Це рішення робить саме це:

function(element, percentX, percentY){
    var tolerance = 0.01;   //needed because the rects returned by getBoundingClientRect provide the position up to 10 decimals
    if(percentX == null){
        percentX = 100;
    }
    if(percentY == null){
        percentY = 100;
    }

    var elementRect = element.getBoundingClientRect();
    var parentRects = [];

    while(element.parentElement != null){
        parentRects.push(element.parentElement.getBoundingClientRect());
        element = element.parentElement;
    }

    var visibleInAllParents = parentRects.every(function(parentRect){
        var visiblePixelX = Math.min(elementRect.right, parentRect.right) - Math.max(elementRect.left, parentRect.left);
        var visiblePixelY = Math.min(elementRect.bottom, parentRect.bottom) - Math.max(elementRect.top, parentRect.top);
        var visiblePercentageX = visiblePixelX / elementRect.width * 100;
        var visiblePercentageY = visiblePixelY / elementRect.height * 100;
        return visiblePercentageX + tolerance > percentX && visiblePercentageY + tolerance > percentY;
    });
    return visibleInAllParents;
};

Він також дозволяє вказати, який відсоток він повинен бути видно у кожному напрямку.
Це не охоплює можливості того, що воно може бути прихованим через інші фактори, наприклад display: hidden.

Це повинно працювати у всіх основних браузерах, оскільки вони використовуються лише getBoundingClientRect. Я особисто тестував це в Chrome і Internet Explorer 11.


Дякуємо за цей код. Цікаво, як у цьому випадку ви б додали слухача подій у прокрутці, що у вас є кілька вкладених прокручуваних елементів? Здається, що додавання слухача до вікна лише недостатньо, чи потрібно нам повернутися до верхнього батьківського пристрою, щоб додати слухача до кожного контейнера, який прокручується?
mr1031011

@ mr1031011 Має бути можливість додати обробник до вікна, а потім перевірити ціль, щоб виявити контейнер, який прокручувався.
Домієє

правильно, це не працює з прикладом, поданим @vanowm,
mr1031011

7
function isScrolledIntoView(elem) {
    var docViewTop = $(window).scrollTop(),
        docViewBottom = docViewTop + $(window).height(),
        elemTop = $(elem).offset().top,
     elemBottom = elemTop + $(elem).height();
   //Is more than half of the element visible
   return ((elemTop + ((elemBottom - elemTop)/2)) >= docViewTop && ((elemTop + ((elemBottom - elemTop)/2)) <= docViewBottom));
}

7

Ось ще одне рішення від http://web-profile.com.ua/

<script type="text/javascript">
$.fn.is_on_screen = function(){
    var win = $(window);
    var viewport = {
        top : win.scrollTop(),
        left : win.scrollLeft()
    };
    viewport.right = viewport.left + win.width();
    viewport.bottom = viewport.top + win.height();

    var bounds = this.offset();
    bounds.right = bounds.left + this.outerWidth();
    bounds.bottom = bounds.top + this.outerHeight();

    return (!(viewport.right < bounds.left || viewport.left > bounds.right ||    viewport.bottom < bounds.top || viewport.top > bounds.bottom));
 };

if( $('.target').length > 0 ) { // if target element exists in DOM
    if( $('.target').is_on_screen() ) { // if target element is visible on screen after DOM loaded
        $('.log').html('<div class="alert alert-success">target element is visible on screen</div>'); // log info       
    } else {
        $('.log').html('<div class="alert">target element is not visible on screen</div>'); // log info
    }
}
$(window).scroll(function(){ // bind window scroll event
if( $('.target').length > 0 ) { // if target element exists in DOM
    if( $('.target').is_on_screen() ) { // if target element is visible on screen after DOM loaded
        $('.log').html('<div class="alert alert-success">target element is visible on screen</div>'); // log info
    } else {
        $('.log').html('<div class="alert">target element is not visible on screen</div>'); // log info
    }
}
});
</script>

Дивіться це в JSFiddle


7

Це враховує будь-яке набивання, облямівку або поле, яке має елемент, а також елементи, що перевищують сам огляд.

function inViewport($ele) {
    var lBound = $(window).scrollTop(),
        uBound = lBound + $(window).height(),
        top = $ele.offset().top,
        bottom = top + $ele.outerHeight(true);

    return (top > lBound && top < uBound)
        || (bottom > lBound && bottom < uBound)
        || (lBound >= top && lBound <= bottom)
        || (uBound >= top && uBound <= bottom);
}

Щоб зателефонувати, використовуйте щось подібне:

var $myElement = $('#my-element'),
    canUserSeeIt = inViewport($myElement);

console.log(canUserSeeIt); // true, if element is visible; false otherwise

7

Існує плагін для jQuery під назвою inview, який додає нову подію "inview".


Ось код для плагіна jQuery, який не використовує події:

$.extend($.expr[':'],{
    inView: function(a) {
        var st = (document.documentElement.scrollTop || document.body.scrollTop),
            ot = $(a).offset().top,
            wh = (window.innerHeight && window.innerHeight < $(window).height()) ? window.innerHeight : $(window).height();
        return ot > st && ($(a).height() + ot) < (st + wh);
    }
});

(function( $ ) {
    $.fn.inView = function() {
        var st = (document.documentElement.scrollTop || document.body.scrollTop),
        ot = $(this).offset().top,
        wh = (window.innerHeight && window.innerHeight < $(window).height()) ? window.innerHeight : $(window).height();

        return ot > st && ($(this).height() + ot) < (st + wh);
    };
})( jQuery );

Я знайшов це у коментарі тут ( http://remysharp.com/2009/01/26/element-in-view-event-plugin/ ) блокером під назвою Джеймс


На жаль, перегляд jQuery більше не підтримується і не працює з поточними версіями jQuery.
mikemaccana

1
JQuery 1 призначений для підтримки застарілого браузера, нові функції є в jQuery 2.
mikemaccana

Посилання не відображає приклад, коли сторінку оновлювали.
професор програмування

6

Мені потрібно було перевірити видимість у елементах всередині прокручуваного контейнера DIV

    //p = DIV container scrollable
    //e = element
    function visible_in_container(p, e) {
        var z = p.getBoundingClientRect();
        var r = e.getBoundingClientRect();

        // Check style visiblilty and off-limits
        return e.style.opacity > 0 && e.style.display !== 'none' &&
               e.style.visibility !== 'hidden' &&
               !(r.top > z.bottom || r.bottom < z.top ||
                 r.left > z.right || r.right < z.left);
    }

це працює для мене, якщо я змінити e.style.opacity > 0на, (!e.style.opacity || e.style.opacity > 0)тому що за замовчуванням для мене це порожній рядок у FF.
Бретт Замір

6

Створюючи цю чудову відповідь , ви можете трохи спростити її за допомогою ES2015 +:

function isScrolledIntoView(el) {
  const { top, bottom } = el.getBoundingClientRect()
  return top >= 0 && bottom <= window.innerHeight
}

Якщо вам не байдуже, що вершина виходить через вікно, і просто дбаєте про те, щоб дно було переглянуте, це можна спростити

function isSeen(el) {
  return el.getBoundingClientRect().bottom <= window.innerHeight
}

або навіть однолінійний

const isSeen = el => el.getBoundingClientRect().bottom <= window.innerHeight

4

Ви можете скористатися плагіном jquery "на екрані", щоб перевірити, чи є елемент у поточному вікні перегляду під час прокрутки. Плагін встановлює значення ": onScreen" селектора на значення true, коли на екрані з'являється селектор. Це посилання на плагін, який ви можете включити у свій проект. " http://benpickles.github.io/onScreen/jquery.onscreen.min.js "

Ви можете спробувати наведений нижче приклад, який працює для мене.

$(document).scroll(function() {
    if($("#div2").is(':onScreen')) {
        console.log("Element appeared on Screen");
        //do all your stuffs here when element is visible.
    }
    else {
        console.log("Element not on Screen");
        //do all your stuffs here when element is not visible.
    }
});

HTML-код:

<div id="div1" style="width: 400px; height: 1000px; padding-top: 20px; position: relative; top: 45px"></div> <br>
<hr /> <br>
<div id="div2" style="width: 400px; height: 200px"></div>

CSS:

#div1 {
    background-color: red;
}
#div2 {
    background-color: green;
}

3

У мене є такий метод у моєму додатку, але він не використовує jQuery:

/* Get the TOP position of a given element. */
function getPositionTop(element){
    var offset = 0;
    while(element) {
        offset += element["offsetTop"];
        element = element.offsetParent;
    }
    return offset;
}

/* Is a given element is visible or not? */
function isElementVisible(eltId) {
    var elt = document.getElementById(eltId);
    if (!elt) {
        // Element not found.
        return false;
    }
    // Get the top and bottom position of the given element.
    var posTop = getPositionTop(elt);
    var posBottom = posTop + elt.offsetHeight;
    // Get the top and bottom position of the *visible* part of the window.
    var visibleTop = document.body.scrollTop;
    var visibleBottom = visibleTop + document.documentElement.offsetHeight;
    return ((posBottom >= visibleTop) && (posTop <= visibleBottom));
}

Редагувати: Цей метод добре працює для IE (принаймні версія 6). Прочитайте коментарі щодо сумісності з FF.


2
Чомусь document.body.scrollTop завжди повертає 0 (на ff3). Змініть його на var visibleTop = (document.documentElement.scrollTop? Document.documentElement.scrollTop: document.body.scrollTop);
yoavf

Вибачте за це. Моя заявка повинна працювати лише в IE 6 (так, мені не пощастило :(), тому я ніколи не тестував цього на FF ...
Ромен Лінсолас

Це була б найкраща відповідь тут, якби вона була правильною. Виправте один із своїх рядків до цього: var visibleBottom = visibleTop + window.innerHeight;я не використовую jQuery, і ви допомогли мені знайти правильну відповідь.
Bitterblue

3

Якщо ви хочете змінити цей елемент для прокрутки в іншому розділі,

function isScrolledIntoView (elem, divID) 

{

    var docViewTop = $('#' + divID).scrollTop();


    var docViewBottom = docViewTop + $('#' + divID).height();

    var elemTop = $(elem).offset().top;
    var elemBottom = elemTop + $(elem).height();

    return ((elemBottom <= docViewBottom) && (elemTop >= docViewTop)); 
}

3

Змінив прийняту відповідь так, що елемент повинен мати його властивість відображення встановити на щось інше, ніж "немає" на якість як видиме.

function isScrolledIntoView(elem) {
   var docViewTop = $(window).scrollTop();
  var docViewBottom = docViewTop + $(window).height();

  var elemTop = $(elem).offset().top;
  var elemBottom = elemTop + $(elem).height();
  var elemDisplayNotNone = $(elem).css("display") !== "none";

  return ((elemBottom <= docViewBottom) && (elemTop >= docViewTop) && elemDisplayNotNone);
}

3

Ось спосіб досягти того ж, використовуючи Mootools, в горизонтальній, вертикальній або обох.

Element.implement({
inVerticalView: function (full) {
    if (typeOf(full) === "null") {
        full = true;
    }

    if (this.getStyle('display') === 'none') {
        return false;
    }

    // Window Size and Scroll
    var windowScroll = window.getScroll();
    var windowSize = window.getSize();
    // Element Size and Scroll
    var elementPosition = this.getPosition();
    var elementSize = this.getSize();

    // Calculation Variables
    var docViewTop = windowScroll.y;
    var docViewBottom = docViewTop + windowSize.y;
    var elemTop = elementPosition.y;
    var elemBottom = elemTop + elementSize.y;

    if (full) {
        return ((elemBottom >= docViewTop) && (elemTop <= docViewBottom)
            && (elemBottom <= docViewBottom) && (elemTop >= docViewTop) );
    } else {
        return ((elemBottom <= docViewBottom) && (elemTop >= docViewTop));
    }
},
inHorizontalView: function(full) {
    if (typeOf(full) === "null") {
        full = true;
    }

    if (this.getStyle('display') === 'none') {
        return false;
    }

    // Window Size and Scroll
    var windowScroll = window.getScroll();
    var windowSize = window.getSize();
    // Element Size and Scroll
    var elementPosition = this.getPosition();
    var elementSize = this.getSize();

    // Calculation Variables
    var docViewLeft = windowScroll.x;
    var docViewRight = docViewLeft + windowSize.x;
    var elemLeft = elementPosition.x;
    var elemRight = elemLeft + elementSize.x;

    if (full) {
        return ((elemRight >= docViewLeft) && (elemLeft <= docViewRight)
            && (elemRight <= docViewRight) && (elemLeft >= docViewLeft) );
    } else {
        return ((elemRight <= docViewRight) && (elemLeft >= docViewLeft));
    }
},
inView: function(full) {
    return this.inHorizontalView(full) && this.inVerticalView(full);
}});

3

Приклад, що базується на цій відповіді, щоб перевірити, чи елемент видимий на 75% (тобто менше 25% його відключено від екрана).

function isScrolledIntoView(el) {
  // check for 75% visible
  var percentVisible = 0.75;
  var elemTop = el.getBoundingClientRect().top;
  var elemBottom = el.getBoundingClientRect().bottom;
  var elemHeight = el.getBoundingClientRect().height;
  var overhang = elemHeight * (1 - percentVisible);

  var isVisible = (elemTop >= -overhang) && (elemBottom <= window.innerHeight + overhang);
  return isVisible;
}

3

На це питання є понад 30 відповідей, і жоден з них не використовує дивовижно просте чисте рішення JS, яке я використовував. Немає необхідності завантажувати jQuery лише для вирішення цього питання, як наполягають багато інших.

Для того, щоб сказати, чи знаходиться елемент у вікні перегляду, спочатку слід визначити положення елементів у тілі. Нам це не потрібно робити рекурсивно, як я колись думав. Натомість ми можемо використовувати element.getBoundingClientRect().

pos = elem.getBoundingClientRect().top - document.body.getBoundingClientRect().top;

Це значення - різниця Y між вершиною об'єкта та вершиною тіла.

Тоді ми мусимо сказати, чи елемент знаходиться в межах перегляду. Більшість реалізацій запитують, чи повний елемент знаходиться у вікні перегляду, тому це ми будемо висвітлювати.

Перш за все, верхнє розташування вікна: window.scrollY.

Ми можемо отримати нижнє положення вікна, додавши висоту вікна до його верхнього положення:

var window_bottom_position = window.scrollY + window.innerHeight;

Дозволяє створити просту функцію для отримання верхнього положення елемента:

function getElementWindowTop(elem){
    return elem && typeof elem.getBoundingClientRect === 'function' ? elem.getBoundingClientRect().top - document.body.getBoundingClientRect().top : 0;
}

Ця функція поверне верхнє положення елемента у вікні або повернеться, 0якщо ви передасте йому щось інше, ніж елемент із .getBoundingClientRect()методом. Цей метод існує давно, тому вам не доведеться турбуватися про те, що ваш браузер не підтримує його.

Тепер вища позиція нашого елемента:

var element_top_position = getElementWindowTop(element);

А або нижнє положення елемента:

var element_bottom_position = element_top_position + element.clientHeight;

Тепер ми можемо визначити, чи знаходиться елемент у вікні перегляду, перевіривши, чи нижнє положення елемента нижче верхнього положення вікна перегляду, і перевіривши, чи верхнє положення елемента вище нижнього положення вікна перегляду:

if(element_bottom_position >= window.scrollY 
&& element_top_position <= window_bottom_position){
    //element is in view
else
    //element is not in view

Звідти ви можете виконати логіку, щоб додати або видалити in-viewклас на своєму елементі, який ви зможете пізніше обробити ефектами переходу у вашій CSS.

Я абсолютно вражений тим, що не знайшов цього рішення ніде більше, але я вважаю, що це найчистіше і найефективніше рішення, і це не вимагає від вас завантаження jQuery!


Дуже приємне пояснення! Але вже є відповіді, які роблять саме те, що ви робите, як відповідь Аллі
Домісі

1
@Domysee Хм, я якось пропустив це. Справедливо. Дякую, що все-таки вказали на це. Приємно бачити, що це робиться іншим способом.
WebWanderer

3

Більш ефективна версія цієї відповіді :

 /**
 * Is element within visible region of a scrollable container
 * @param {HTMLElement} el - element to test
 * @returns {boolean} true if within visible region, otherwise false
 */
 function isScrolledIntoView(el) {
      var rect = el.getBoundingClientRect();
      return (rect.top >= 0) && (rect.bottom <= window.innerHeight);
 }

2

Цей метод поверне значення true, якщо будь-яка частина елемента буде видимою на сторінці. У моєму випадку це спрацювало краще і, можливо, допоможе комусь іншому.

function isOnScreen(element) {
  var elementOffsetTop = element.offset().top;
  var elementHeight = element.height();

  var screenScrollTop = $(window).scrollTop();
  var screenHeight = $(window).height();

  var scrollIsAboveElement = elementOffsetTop + elementHeight - screenScrollTop >= 0;
  var elementIsVisibleOnScreen = screenScrollTop + screenHeight - elementOffsetTop >= 0;

  return scrollIsAboveElement && elementIsVisibleOnScreen;
}

2

Проста модифікація для прокручуваного div (контейнера)

var isScrolledIntoView = function(elem, container) {
    var containerHeight = $(container).height();
    var elemTop = $(elem).position().top;
    var elemBottom = elemTop + $(elem).height();
    return (elemBottom > 0 && elemTop < containerHeight);
}

ПРИМІТКА: це не працює, якщо елемент більший за розділовий розділовий елемент.


2

Я адаптував це коротке розширення функції jQuery, яке ви можете вільно користуватися (ліцензія MIT).

/**
 * returns true if an element is visible, with decent performance
 * @param [scope] scope of the render-window instance; default: window
 * @returns {boolean}
 */
jQuery.fn.isOnScreen = function(scope){
    var element = this;
    if(!element){
        return;
    }
    var target = $(element);
    if(target.is(':visible') == false){
        return false;
    }
    scope = $(scope || window);
    var top = scope.scrollTop();
    var bot = top + scope.height();
    var elTop = target.offset().top;
    var elBot = elTop + target.height();

    return ((elBot <= bot) && (elTop >= top));
};

2

Я написав компонент для завдання, призначений для обробки великої кількості елементів надзвичайно швидко (на межі <10 мс на 1000 елементів на повільному мобільному пристрої ).

Він працює з кожним типом контейнера прокрутки у вас є доступ до - вікна, HTML елементів, вбудований кадру, котрий породив дочірньому вікном - і дуже гнучкий в тому, що він виявляє ( повну або часткову видимість , межі вікна або вікно контенту , призначені для користувача зони допуску , і т.д. ).

Величезний, здебільшого автоматично створений тестовий набір гарантує, що він працює як рекламований, крос-браузер .

Спробуйте, якщо вам подобається: jQuery.isInView . В іншому випадку ви можете знайти натхнення у вихідному коді, наприклад, тут .

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.