클릭시 특정 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.