오버플로 된 Div 내의 요소로 어떻게 스크롤합니까?


159

한 번에 5 개만 표시 할 수있는 div 안에 20 개의 목록 항목이 있습니다. 항목 # 10으로 스크롤 한 다음 항목 # 20으로 스크롤하는 좋은 방법은 무엇입니까? 모든 항목의 높이를 알고 있습니다.

scrollTo플러그인은이 작업을 수행하지만, 소스 정말 그것으로 점점없이 이해하기 매우 쉬운 일이 아니다. 이 플러그인을 사용하고 싶지 않습니다.

이 전 2 개 요소를받는 함수가 있다고 가정 해 봅시다 $parentDiv, $innerListItem, 어느 쪽 $innerListItem.offset().top$innerListItem.positon().top나에게 $ parentDiv에 대한 올바른 scrollTop을 제공합니다.


업데이트로 인해 답변이 삭제되었습니다. 그러나 이전과 같은 태도를 보였지만 위치와 여백 등이 많은 브라우저 단점이 있습니다. 플러그인은 훨씬 간단한 경로와 적은 시간이 걸리며 GZip 전에는 3k에 불과 합니다.
Nick Craver

1
어쨌든 scrollTo 플러그인을 사용하십시오. 어렵지 않습니다. $("#container").scrollTo(target, duration, options). 대상은 단지입니다 #anchor. 끝난.
Ryan McGeary

플러그인 없이이 작업을 수행하는 데 필요한 지식이 있어야합니다. 내일 병 소스 읽기 시작
mkoryak

5
@ mkoryak-지식이 있지만 브라우저의 단점을 설명 할 때 기본적으로 .scrollTo 플러그인 으로 끝납니다. 왜 항상 바퀴를 다시 발명합니까?
Nick Craver

1
IMHO, 아마도 .scrollTo에서 필요한 것의 정확한 부분 집합으로 끝날 것 입니다 . .scrollTo는 IE9, FF4와 크롬 6으로 업데이트되었습니다 동안 그러나 몇 달의 시간에, 당신은 다시 시작해야합니다 ... 3K이를 방지하기 위해 매우 낮은 가격처럼 보인다.
Wim

답변:


236

$innerListItem.position().top받는 실제 상대적 .scrollTop()최초 위치 지정된 조상. 따라서 올바른 $parentDiv.scrollTop()값 을 계산하는 방법 $parentDiv은 위치가 올바른지 확인하는 것 입니다. 명시 적이 없으면를 position사용하십시오 position: relative. 요소 $innerListItem와 모든 조상 $parentDiv은 명시적인 위치를 가질 필요가 없습니다. 이제 $innerListItemwith (으)로 스크롤 할 수 있습니다 .

// Scroll to the top
$parentDiv.scrollTop($parentDiv.scrollTop() + $innerListItem.position().top);

// Scroll to the center
$parentDiv.scrollTop($parentDiv.scrollTop() + $innerListItem.position().top
    - $parentDiv.height()/2 + $innerListItem.height()/2);

152

이것은 내 자신의 플러그인입니다 (요소를 목록 맨 위에 배치합니다. 특히 overflow-y : auto.와 함께 작동하지 않을 수 있습니다 overflow-x!)

참고 : elem페이지를 스크롤 할 요소의 HTML 선택기입니다. : 추천 jQuery를, 지원 건 #myid, div.myclass, $(jquery object), [DOM 객체, 등등

jQuery.fn.scrollTo = function(elem, speed) { 
    $(this).animate({
        scrollTop:  $(this).scrollTop() - $(this).offset().top + $(elem).offset().top 
    }, speed == undefined ? 1000 : speed); 
    return this; 
};

애니메이션이 필요하지 않은 경우 다음을 사용하십시오.

jQuery.fn.scrollTo = function(elem) { 
    $(this).scrollTop($(this).scrollTop() - $(this).offset().top + $(elem).offset().top); 
    return this; 
};

사용하는 방법:

$("#overflow_div").scrollTo("#innerItem");
$("#overflow_div").scrollTo("#innerItem", 2000); //custom animation speed 

참고 : #innerItem내부 어디에나있을 수 있습니다 #overflow_div. 직접적인 아이 일 필요는 없습니다.

Firefox (23) 및 Chrome (28)에서 테스트되었습니다.

전체 페이지를 스크롤하려면 이 질문을 확인 하십시오 .


무엇 elem입니까 ?? 당신은 전혀 설명하지 않습니다.
vsync

fn.scrollTo에서 $를 대신 jQuery로 바꾸면 마일리지 / 비 충돌 문제가 개선됩니다.
Barry Carlyon

이것에 대한 큰 결함, 당신의 범위를 포함하지 않는 : $(this).scrollTop($(this).scrollTop() - $(this).offset().top + $(elem, $(this)).offset().top);-안부
Luke Snowden

1
페이지와 요소 사이에 약간의 여백을 남기고 싶은 경우 (어떤 경우에는 더 좋아 보일 수 있음), 예를 들어 10px를 빼십시오 $(this).scrollTop() - $(this).offset().top + $(elem).offset().top - 10.
lepe

Firefox와 Chrome (또는 다른 브라우저)간에 위치 차이가있는 경우 HTML 코드를 확인하십시오 ( 이 버그 보고서 참조 )
Lepe

34

overflow div가 페이지 상단에 없을 수도 있다는 사실을 설명하기 위해 Glenn Moss의 답변을 조정했습니다.

parentDiv.scrollTop(parentDiv.scrollTop() + (innerListItem.position().top - parentDiv.position().top) - (parentDiv.height()/2) + (innerListItem.height()/2)  )

반응 형 템플릿이있는 Google지도 응용 프로그램에서 이것을 사용하고있었습니다. 800px 이상의 해상도에서 목록은지도의 왼쪽에있었습니다. 해상도 <800에서 목록은지도 아래에있었습니다.


6

위의 답변은 내부 요소가 오버플로 요소 내부에 있어도 오버플로 요소의 맨 위에 배치합니다. 요소가 보이지 않는 경우 스크롤 위치를 변경하지 않도록 수정하지 않았습니다.

jQuery.fn.scrollTo = function(elem, speed) {
    var $this = jQuery(this);
    var $this_top = $this.offset().top;
    var $this_bottom = $this_top + $this.height();
    var $elem = jQuery(elem);
    var $elem_top = $elem.offset().top;
    var $elem_bottom = $elem_top + $elem.height();

    if ($elem_top > $this_top && $elem_bottom < $this_bottom) {
        // in view so don't do anything
        return;
    }
    var new_scroll_top;
    if ($elem_top < $this_top) {
        new_scroll_top = {scrollTop: $this.scrollTop() - $this_top + $elem_top};
    } else {
        new_scroll_top = {scrollTop: $elem_bottom - $this_bottom + $this.scrollTop()};
    }
    $this.animate(new_scroll_top, speed === undefined ? 100 : speed);
    return this;
};


1

나는 내 인생을 더 쉽게하기 위해이 두 가지 기능을 작성합니다.

function scrollToTop(elem, parent, speed) {
    var scrollOffset = parent.scrollTop() + elem.offset().top;
    parent.animate({scrollTop:scrollOffset}, speed);
    // parent.scrollTop(scrollOffset, speed);
}

function scrollToCenter(elem, parent, speed) {
    var elOffset = elem.offset().top;
    var elHeight = elem.height();
    var parentViewTop = parent.offset().top;
    var parentHeight = parent.innerHeight();
    var offset;

    if (elHeight >= parentHeight) {
        offset = elOffset;
    } else {
        margin = (parentHeight - elHeight)/2;
        offset = elOffset - margin;
    }

    var scrollOffset = parent.scrollTop() + offset - parentViewTop;

    parent.animate({scrollTop:scrollOffset}, speed);
    // parent.scrollTop(scrollOffset, speed);
}

그리고 그것들을 사용하십시오 :

scrollToTop($innerListItem, $parentDiv, 200);
// or
scrollToCenter($innerListItem, $parentDiv, 200);

elem.offset().top화면 상단에서 계산 중입니다. 부모 요소에서 계산하고 싶습니다. 어떻게합니까?
Santosh

0

오랫동안 가지고 놀았을 때, 이것이 내가 생각해 낸 것입니다.

    jQuery.fn.scrollTo = function (elem) {
        var b = $(elem);
        this.scrollTop(b.position().top + b.height() - this.height());
    };

나는 이것을 이렇게 부른다

$("#basketListGridHolder").scrollTo('tr[data-uid="' + basketID + '"]');
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.