jQuery로 div의 가시 높이 가져 오기


87

스크롤 가능한 영역 내에서 div의 보이는 높이를 검색해야합니다. 나는 jQuery에 대해 꽤 괜찮다고 생각하지만 이것은 나를 완전히 버리고 있습니다.

검은 색 래퍼 안에 빨간색 div가 있다고 가정 해 보겠습니다.

위의 그래픽에서 jQuery 함수는 div의 보이는 부분 인 248을 반환합니다.

위의 그래픽에서와 같이 사용자가 div의 맨 위로 스크롤하면 296이보고됩니다.

이제 사용자가 div를지나 스크롤하면 다시 248을보고합니다.

분명히 내 수치는이 데모 에서처럼 일관되고 명확하지 않을 것입니다. 아니면 그 수치에 대해 하드 코딩 할 것입니다.

나는 약간의 이론이 있습니다.

  • 창 높이 가져 오기
  • div의 높이 가져 오기
  • 창 상단에서 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

답변:


58

여기에 빠르고 더러운 개념이 있습니다. 기본적으로 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- 창의 크기를 조정할 때 로직을 수행하기위한 작은 업데이트입니다.


div코드를 반복하지 않고 여러 s에 대해 이것을 설정하는 데 문제 가 있습니다. 이를 수행하는 방법이 있습니까?
JacobTheDev

2
@Rev 여기 있습니다 : jsfiddle.net/b5DGj/1 . 각 요소를 자체 함수 호출로 분리했습니다. 더 나아가서이를 위해 플러그인을 정의 할 수도 있습니다.
Rory McCrossan 2014

jQuery 플러그인으로 작동하는 @RoryMcCrossan의 접근 방식을 약간 다시 작성하고 아래에 답변으로 게시했습니다. 해당 형식에서 더 일반적인 적용 가능성이있을 수 있습니다.
Michael.Lumley

때때로 요소는 부분적으로 상관없이 "윈도우"의 오버 플로우로 인해 또는 부모 요소 숨길 수
Nadav B

56

요소 (높이)가 뷰포트에있는 픽셀의 양을 계산합니다.

바이올린 데모

이 작은 함수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

당신의 선택기는 동적으로 창을들을 것입니다 scrollresize뿐만 아니라 DOM 준비 트로프의 첫 번째 콜백 함수 인수를 초기 값을 반환합니다 px.


Android Chrome에서 작업하려면 <meta name="viewport" content="width=your_size">head html 섹션에 추가해야 할 수 있습니다 .
userlond apr

@userlond 귀하의 기여에 감사 드리지만 content="width=1259"대다수에게 적합 하지 않을 수 있습니다. content="width=device-width, initial-scale=1"대신 시도해 보셨습니까 ?
Roko C. Buljan

사이트에 너비가 고정 된 레거시 템플릿이 있고 응답이 없습니다 ... 귀하의 제안이 대부분 괜찮을 것이라고 생각합니다. 따라서 명확히하기 위해 : Roko C. Buljan의 솔루션이 작동하지 않으면 <meta name="viewport" content="your_content">선언 을 추가해보십시오. :)
userlond

이것은 너무 굉장하고 내가 찾고 있던 것에 너무 가깝습니다. 요소 하단에서 창 하단까지의 거리를 어떻게 계산할 수 있습니까? 따라서 콘텐츠의 끝을보기 전에 더 많은 콘텐츠를로드 할 수 있습니다. 예를 들어, windowBot에서 elBottom <200이면 AJAX를 실행합니다.
Thom

1
@Thom 잘, 위의 메소드는 다른 특정 값을 반환하지 않습니다 ( visible height px객체와 같은 단순한 것보다 더 많은 것을 반환하도록 확장 할 수 있습니다 . 이러한 아이디어에 대해서는이 바이올린을 참조하십시오. jsfiddle.net/RokoCB/6xjq5gyy (개방형 개발자 콘솔) ) 로그를 볼 수
로코 C. Buljan에게

11

다음은 jQuery 플러그인으로 작동하도록 작성된 것을 제외하고 위의 Rory 접근 방식의 버전입니다. 해당 형식에서보다 일반적인 적용 가능성이있을 수 있습니다. 좋은 대답, Rory-감사합니다!

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