Как проверить, виден ли элемент после прокрутки? - PullRequest
1061 голосов
/ 28 января 2009

Я загружаю элементы через AJAX. Некоторые из них видны только при прокрутке страницы вниз.
Могу ли я узнать, находится ли элемент в видимой части страницы?

Ответы [ 39 ]

1194 голосов
/ 28 января 2009

Это должно сработать:

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');
}
351 голосов
/ 18 марта 2014

Этот ответ в ванили:

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;
}
118 голосов
/ 21 августа 2010

Лучший метод, который я нашел на данный момент, - это jQuery Появляется плагин . Работает как шарм.

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

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

Этот плагин можно использовать для предотвращения ненужных запросов на контент, который скрыт или находится за пределами видимой области.

77 голосов
/ 07 февраля 2014

Вот мое чистое решение 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
};

РЕДАКТИРОВАТЬ 2016-03-26: я обновил решение для учета прокрутки мимо элемента, чтобы он скрывался над верхней частью контейнера с прокруткой. РЕДАКТИРОВАТЬ 2018-10-08: Обновлено для обработки при прокрутке вне экрана над экраном.

41 голосов
/ 04 декабря 2011

Плагин jQuery Waypoints идет очень хорошо здесь.

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

На сайте плагина есть несколько примеров .

19 голосов
/ 29 апреля 2014

Как насчет

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

После этого вы можете активировать все, что захотите, когда элемент будет виден, как этот

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

Это прекрасно работает для меня

17 голосов
/ 10 августа 2017

Использование ("новый") IntersectionObserver API

Очень просто и эффективно определить, виден ли элемент в окне просмотра. Использование наблюдателя устраняет необходимость в прикреплении события 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)

14 голосов
/ 28 января 2009

WebResourcesDepot написал скрипт для загрузки при прокрутке , который использует jQuery некоторое время назад. Вы можете посмотреть их Live Demo Здесь . Говорят, что их функциональность была такой:

$(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();
    });
};
13 голосов
/ 30 апреля 2013

крутая функция Скотта Даудинга для моего требования- это используется для нахождения прокрутки элемента на экране, т.е. его верхнего края.

function isScrolledIntoView(elem)
{
    var docViewTop = $(window).scrollTop();
    var docViewBottom = docViewTop + $(window).height();
    var elemTop = $(elem).offset().top;
    return ((elemTop <= docViewBottom) && (elemTop >= docViewTop));
}
8 голосов
/ 26 июня 2016

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

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

Это решение делает именно это:

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.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...