스크롤 후 요소가 보이는지 확인하는 방법은 무엇입니까?


1169

AJAX를 통해 요소를로드하고 있습니다. 일부는 페이지를 아래로 스크롤 한 경우에만 표시됩니다.
요소가 페이지의 보이는 부분에 있는지 알 수있는 방법이 있습니까?


42
그는 주어진 요소가 브라우저 창에 표시되는지 또는 사용자가 스크롤하여 요소를 볼 수 있는지 확인하는 방법을 원한다는 것을 의미합니다.
Romain Linsolas

1
컨테이너에 요소가 완전히 표시되는지 확인하려면 추가 선택기 매개 변수를 추가하고 elem 코드를 재사용하십시오. Library.IsElementVisibleInContainer = function (elementSelector, containerSelector) { var containerViewTop = $(containerSelector).offset().top; var containerViewBottom = containerViewTop + $(containerSelector).height();
Lifes



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
문서가 스크롤되는 요소 인 경우에만 작동합니다. 즉, 스크롤하는 내부 창에서 일부 요소의 가시성을 확인하지 않습니다.
앤드류 B.

8
약간의 오프셋을 추가하는 방법?
Jürgen Paul

5
내가 window.innerHeight대신 사용할 때만 작동
Christian Schnorr

2
들어 elemTop내가 사용 $(elem).position().top하고 위해 elemBottom내가 사용 elemTop + $(elem).outerHeight(true).
Sarah Vessels

13
들면 "뷰 요소의 일부"I 사용 : (((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
승인 된 답변과 비교하여 이것은 수백 가지 요소로 훨씬 더 잘 수행됩니다.
ncla

5
- 작은 바이올린 여기 시연 참조 jsfiddle.net/shaaraddalvi/4rp09jL0
upInCloud

122

업데이트 : IntersectionObserver 사용


지금까지 찾은 가장 좋은 방법은 jQuery appear plugin 입니다. 매력처럼 작동합니다.

요소가 스크롤되거나 사용자에게 표시 될 때 발생하는 사용자 정의 "appear"이벤트를 모방합니다.

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

이 플러그인은 숨겨 지거나 볼 수있는 영역 밖에있는 콘텐츠에 대한 불필요한 요청을 방지하는 데 사용할 수 있습니다.


30
이것은 멋진 플러그인이지만 의심의 여지가 없습니다.
Jon Adams

5
jQuery 모양 플러그인은 메인 페이지 영역의 컨텐츠에 적합하지만 불행히도 고정 크기 스크롤 div에 오버플로가 발생하는 문제가 있습니다. 바운드 요소가 페이지의 볼 수있는 영역 내에 있지만 div의 볼 수있는 영역 밖에 있으면 이벤트가 조기에 시작된 다음 요소가 div에 표시 될 때 예상대로 실행되지 않을 수 있습니다.
피터

17
사라지는 플러그인이 있습니까?
Shamoon

3
@Shamoon에서 소스를 확인하면 플러그인 을 얻기 위해 어딘가에 appear plugin추가해야 할 것입니다 . !disappear
Lucky Soni

5
참고로, 이것은 jQuery 1.11.X github.com/morr/jquery.appear/issues/37에서
Jason Parham

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

편집 2016-03-26 : 스크롤 가능한 컨테이너의 맨 위에 숨겨져 요소를 지나가는 스크롤을 설명하기 위해 솔루션을 업데이트했습니다. 2018-10-08 편집 : 화면 위에서 스크롤하지 않으면 처리하도록 업데이트되었습니다.


감사합니다, 아마 더 낫습니다 return top <= document.documentElement.clientHeight && top >= 0;
Yousef Salimpour 2018 년

16
+1 이것은 요소의 재귀 적 특성을 고려한 유일한 코딩 된 (즉, 타사가 아닌) 답변입니다. 가로, 세로 및 페이지 스크롤을 처리하도록 확장했습니다 : jsfiddle.net/9nuqpgqa
Pebbl

3
이 솔루션은 요소의 상단 만 확인합니다. 첫 번째 맨 위 픽셀이 표시되면 나머지 항목이 보이지 않더라도 true를 반환합니다. 전체 요소가 표시되는지 확인하려면 bottom 속성도 확인해야합니다.
Wojciech Jakubas

2
알겠습니다! 이 답변을 작성하는 데 도움 됩니다 (js 의견으로 신용으로).
Roamer-1888

잃어버린 ; 루프에서 두 번째 "거짓 반환"후
Mikhail

45

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에서는 지원되지 않음)


4
감사! 이것은 저에게 효과적이며 github.com/w3c/IntersectionObserver를
Matt Wilson

지금까지 최고의 솔루션. polyfill없이 IE11에서 일했습니다!
Fabian von Ellerts

안타깝게도 iOS / macOS Safari에서는 아직이 기능이 지원되지 않습니다. 폴리 필을 선택하면 성능 문제를 확인하십시오. 이는 많은 사용자 그룹입니다.
Leland

@Leland-프로젝트에 따라 다릅니다. 모든 프로젝트에서 이것은 절대 사용자 그룹입니다. 나는 웹 사이트를 구축하지 않고 웹 시스템을;)
vsync

여러 요소에서 루프로 이것을 실행하려고하지만 작동하지 않습니다. 어떤 아이디어? 해당 루프에서 대상으로 요소를 추가하고 있습니다.
Sascha Grindau

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
이것은 나를 위해 작동하지만 stackoverflow.com/questions/487073/… 에서 isScrolledIntoView 함수를 사용했습니다. :)
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

내 요구 사항에 대한 Tweeked Scott Dowding의 멋진 기능-요소가 화면으로 스크롤되었는지 확인하는 데 사용됩니다 (예 : 상단 가장자리).

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

12

el스크롤 가능한 div ( 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
단일 페이지 응용 프로그램 시대에 요소가 이외의 다른 요소에 표시되는지 확인하는 것이 일반적이되었습니다 . 그렇기 때문에 이것이 나의 투표를 얻는 이유입니다.
H 개

8

isScrolledIntoView 는 매우 필요한 기능이므로 시도해 보았습니다. 뷰포트보다 가볍지 않은 요소에서는 작동하지만 요소가 뷰포트보다 크면 작동하지 않습니다. 이 문제를 쉽게 해결하려면 조건을 변경하십시오.

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

이에:

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

데모보기 : http://jsfiddle.net/RRSmQ/


8

여기에있는 대부분의 답변은 요소가 전체 페이지뿐만 아니라 div보기에서 스크롤되기 때문에 숨길 수도 있다는 것을 고려하지 않습니다.

이러한 가능성을 다루기 위해서는 기본적으로 요소가 각 부모의 경계 안에 있는지 확인해야합니다.

이 솔루션은 정확히 다음을 수행합니다.

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 창에 처리기를 추가 한 다음 스크롤 된 컨테이너를 식별하기 위해 대상을 확인해야합니다.
Domysee

맞습니다. @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

새로운 "inview"이벤트를 추가하는 inview 라는 jQuery 용 플러그인 이 있습니다 .


다음은 이벤트를 사용하지 않는 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 inview는 더 이상 유지 관리되지 않으며 현재 버전의 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);
    }

기본적으로 FF의 빈 문자열이기 때문에 e.style.opacity > 0to를 변경하면 이것이 효과적입니다 (!e.style.opacity || e.style.opacity > 0).
Brett Zamir 2016 년

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"을 사용하여 요소가 현재 뷰포트에 있는지 확인할 수 있습니다. 플러그인은 화면에 선택기가 나타날 때 선택기의 ": 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

그 죄송합니다. 나는 FF에서이 테스트를하지 않도록 내 응용 프로그램 ... 만 IE 6 (예, 나는 :( 운이 아니다)에서 실행해야합니다
로맹 Linsolas에게

이것이 맞다면 이것이 가장 좋은 대답이 될 것입니다. 이 당신의 라인 올바른 하나 : var visibleBottom = visibleTop + window.innerHeight;나는 jQuery를 사용하지 않는 당신은 나에게 정답을 찾을 수있었습니다.
Bitterblue

3

다른 div 내에서 항목을 스크롤하기 위해 이것을 조정하려면,

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를로드 할 필요가 없다고 생각합니다!


아주 좋은 설명! 그러나 같은 당신이해야합니까 정확히 답변, 이미있는 앨리의 대답
Domysee

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

참고 : 요소가 스크롤 가능한 div보다 큰 경우에는 작동하지 않습니다.


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

나는 많은 요소를 매우 빠르게 처리하도록 설계된 작업을위한 구성 요소 를 작성 했습니다 ( 느린 모바일에서 1000 요소의 경우 10ms 미만으로 조정 ).

창, HTML 요소, 내장은 iframe, 양산 자식 창 - - 그것은 모든 사용자가 액세스 할 수있는 스크롤 컨테이너의 종류와 함께 작동하고 (감지 것에 매우 유연 전체 또는 부분 가시성 , 경계 상자 또는 컨텐츠 상자 , 사용자 정의 공차 영역 , ).

대부분 자동 생성 된 대규모 테스트 스위트를 통해 광고 된 크로스 브라우저 로 작동 합니다 .

원한다면 jQuery.isInView 샷을 제공하십시오 . 그렇지 않으면 소스 코드에서 영감을 얻을 수 있습니다 (예 : here) .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.