클릭시 특정 div로 부드럽게 스크롤


94

내가하려는 것은 버튼을 클릭하면 페이지의 특정 div로 (부드럽게) 스크롤되도록 만드는 것입니다.

내가 필요한 것은 버튼을 클릭하면 div '초'로 부드럽게 스크롤됩니다.

.first {
    width: 100%;
    height: 1000px;
    background: #ccc;
}

.second {
    width: 100%;
    height: 1000px;
    background: #999;
}
<div class="first"><button type="button">Click Me!</button></div>
<div class="second">Hi</div>


당신은 시도 할 수 이 플러그인을 ,하지만 이 일이 훨씬 더 사용자 친화적이다. 헤더에서 JS 파일을 링크하고 마크 업이 작동하도록 적절하게 변경하면됩니다.
joshrathke 2013-08-06

답변:


178

하다:

$("button").click(function() {
    $('html,body').animate({
        scrollTop: $(".second").offset().top},
        'slow');
});

Jsfiddle 업데이트


여기에서 자바 스크립트를 사용하고 있습니까? 아니면 jQuery를 사용하고 있습니까?

1
@FahadUddin의 jQuery.
Sudhir Bastakoti 2017 년

@SudhirBastakoti : JsFiddle이 해당 페이지에 jquery 라이브러리를 포함하지 않은 이유는 무엇입니까?

@Sudhir Bastakoti 그러나 많은 사용자가 부드러운 스크롤이 아니라고 불평합니다.
Maulik

40

jQuery, Mootools, Prototype 등과 같은 JS 라이브러리를 사용한 부드러운 스크롤링의 예가 많이 있습니다.

다음 예제는 순수 JavaScript에 있습니다. 페이지에 jQuery / Mootools / Prototype이 없거나 무거운 JS 라이브러리로 페이지를 오버로드하지 않으려면 예제가 도움이 될 것입니다.

http://jsfiddle.net/rjSfP/

HTML 부분 :

<div class="first"><button type="button" onclick="smoothScroll(document.getElementById('second'))">Click Me!</button></div>
<div class="second" id="second">Hi</div>

CSS 부분 :

.first {
    width: 100%;
    height: 1000px;
    background: #ccc;
}

.second {
    width: 100%;
    height: 1000px;
    background: #999;
}

JS 부분 :

window.smoothScroll = function(target) {
    var scrollContainer = target;
    do { //find scroll container
        scrollContainer = scrollContainer.parentNode;
        if (!scrollContainer) return;
        scrollContainer.scrollTop += 1;
    } while (scrollContainer.scrollTop == 0);

    var targetY = 0;
    do { //find the top of target relatively to the container
        if (target == scrollContainer) break;
        targetY += target.offsetTop;
    } while (target = target.offsetParent);

    scroll = function(c, a, b, i) {
        i++; if (i > 30) return;
        c.scrollTop = a + (b - a) / 30 * i;
        setTimeout(function(){ scroll(c, a, b, i); }, 20);
    }
    // start scrolling
    scroll(scrollContainer, scrollContainer.scrollTop, targetY, 0);
}

나는 이것을 사용하고 있으며 훌륭하게 작동합니다. 그래도 스크롤을 느리게 만들려면 어떻게해야합니까?
jamescampbell

이 코드에서 고정 navbar에 대한 오프셋을 추가하는 방법을 알고 계십니까? 여기에 내가 만든 예입니다 바이올린
Plavookac

3
아직 오년 후 helpfull
Owaiz Yusufi에게

9

나는 니코의 대답을 조금 가지고 놀았고 불안해했다. 약간의 조사를 수행하고 window.requestAnimationFrame각 다시 그리기주기에서 호출되는 함수를 찾았습니다 . 이를 통해보다 깔끔한 애니메이션을 만들 수 있습니다. 단계 크기에 대한 좋은 기본값을 계속 연마하려고하지만 내 예제에서는이 구현을 사용하여 매우 좋아 보입니다.

var smoothScroll = function(elementId) {
    var MIN_PIXELS_PER_STEP = 16;
    var MAX_SCROLL_STEPS = 30;
    var target = document.getElementById(elementId);
    var scrollContainer = target;
    do {
        scrollContainer = scrollContainer.parentNode;
        if (!scrollContainer) return;
        scrollContainer.scrollTop += 1;
    } while (scrollContainer.scrollTop == 0);

    var targetY = 0;
    do {
        if (target == scrollContainer) break;
        targetY += target.offsetTop;
    } while (target = target.offsetParent);

    var pixelsPerStep = Math.max(MIN_PIXELS_PER_STEP,
                                 (targetY - scrollContainer.scrollTop) / MAX_SCROLL_STEPS);

    var stepFunc = function() {
        scrollContainer.scrollTop =
            Math.min(targetY, pixelsPerStep + scrollContainer.scrollTop);

        if (scrollContainer.scrollTop >= targetY) {
            return;
        }

        window.requestAnimationFrame(stepFunc);
    };

    window.requestAnimationFrame(stepFunc);
}

1
@Alfonso 위를 참조하십시오. 이것은 이전 답변에서 nico 코드의 최적화 된 버전입니다.
Ned Rockson

@NedRockson은 콘솔 메시지 "Uncaught TypeError : Cannot read property 'parentNode'of null"을 제공하지만 nico의 코드가 작동합니다. 어떻게해야 깨끗한 애니메이션을 적용 할 수 있습니까?
Kartik Watwani

@KartikWatwani 이는 읽는 줄 scrollContainer = scrollContainer.parentNode에서 scrollContainer가 null 임을 의미합니다 . 이것은 elementId이 함수를 호출 할 때 올바른 값을 전달하지 않았 음을 의미합니다 . 해당 elementId가 존재하지 않는 페이지에서이 스크립트를 실행하는 것도 가능합니다.
네드 Rockson

@NedRockson 만약 틀렸다면 @nico의 경우 elementId와 같은 오류를 받았을 것입니다. 그러나이 경우 스크롤은 작동하지만 부드럽게되지는 않습니다.
Kartik Watwani

requestAnimationFrame대신 사용 하는 setTimeout것이 방법입니다. setTimeout애니메이션에 사용해서는 안됩니다.
tsnkff


2

나는 Ned Rockson 의 버전을 가져 와서 위쪽 스크롤도 허용하도록 조정했습니다.

var smoothScroll = function(elementId) {
  var MIN_PIXELS_PER_STEP = 16;
  var MAX_SCROLL_STEPS = 30;
  var target = document.getElementById(elementId);
  var scrollContainer = target;
  do {
    scrollContainer = scrollContainer.parentNode;
    if (!scrollContainer) return;
    scrollContainer.scrollTop += 1;
  } while (scrollContainer.scrollTop === 0);

  var targetY = 0;
  do {
    if (target === scrollContainer) break;
    targetY += target.offsetTop;
  } while (target = target.offsetParent);

  var pixelsPerStep = Math.max(MIN_PIXELS_PER_STEP,
    Math.abs(targetY - scrollContainer.scrollTop) / MAX_SCROLL_STEPS);

  var isUp = targetY < scrollContainer.scrollTop;

  var stepFunc = function() {
    if (isUp) {
      scrollContainer.scrollTop = Math.max(targetY, scrollContainer.scrollTop - pixelsPerStep);
      if (scrollContainer.scrollTop <= targetY) {
        return;
      }
    } else {
        scrollContainer.scrollTop = Math.min(targetY, scrollContainer.scrollTop + pixelsPerStep);

      if (scrollContainer.scrollTop >= targetY) {
        return;
      }
    }

    window.requestAnimationFrame(stepFunc);
  };

  window.requestAnimationFrame(stepFunc);
};


0

Ned Rockson은 기본적으로이 질문에 답합니다. 그러나 그의 솔루션에는 치명적인 결함이 있습니다. 대상 요소가 viewport-height보다 페이지 하단에 더 가까우면 함수가 exit 문에 도달하지 않고 페이지 하단에있는 사용자를가 둡니다. 이것은 반복 횟수를 제한하여 간단히 해결됩니다.

var smoothScroll = function(elementId) {
    var MIN_PIXELS_PER_STEP = 16;
    var MAX_SCROLL_STEPS = 30;
    var target = document.getElementById(elementId);
    var scrollContainer = target;
    do {
        scrollContainer = scrollContainer.parentNode;
        if (!scrollContainer) return;
        scrollContainer.scrollTop += 1;
    } while (scrollContainer.scrollTop == 0);

    var targetY = 0;
    do {
        if (target == scrollContainer) break;
        targetY += target.offsetTop;
    } while (target = target.offsetParent);

    var pixelsPerStep = Math.max(MIN_PIXELS_PER_STEP,
                                 (targetY - scrollContainer.scrollTop) / MAX_SCROLL_STEPS);

    var iterations = 0;
    var stepFunc = function() {
        if(iterations > MAX_SCROLL_STEPS){
            return;
        }
        scrollContainer.scrollTop =
            Math.min(targetY, pixelsPerStep + scrollContainer.scrollTop);

        if (scrollContainer.scrollTop >= targetY) {
            return;
        }

        window.requestAnimationFrame(stepFunc);
    };

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