자바스크립트에서 현재의 스크롤 위치를 원하는 엘리먼트 및 위치로 이동하는 방법을
순수 자바스크립트를 사용하여 라이브러리 없이 구현해보고자 합니다. 아래에서 자세히 알아보세요.
# 자바스크립트 스크롤 애니메이션 구현하기먼저 스크롤을 이동하는 경우는 언제 필요할까요? 가장 많이 사용되는 경우는 내부 링크로 이동하는 경우가 되겠습니다. 즉 버튼을 클릭시 원하는 내부 엘리먼트로 이동할 경우죠.
<a href="#target">바로가기</a>
<div id="target">Hi Webisfree.com</div>
일반적으로 #id를 사용하여 이동하는 방법이 많이 쓰입니다. 일단 별도의 자바스크립트가 필요없죠. 다만
애니메이션 효과가 없이 즉시 스크롤이 해당 위치로 움직인다는 단점이 존재합니다.
그래서 애니메이션이 있는 스크롤을 아래에서 구현해보려고 합니다.
@ css를 사용한 애니메이션 스크롤 방법
IE 등을 제외한 브라우저에서 동작하는 css를 사용하는 방법이 존재합니다. 바로 scroll-behavior 스타일 속성입니다.
자세한 내용이 궁금하시면 아래 링크를 클릭하세요.
https://webisfree.com/2019-12-19/[css]-스크롤-이동-애니메이션-속성-scroll-behavior! 순수 자바스크립트를 사용한 스크롤 애니메이션 구현하기
먼저 만들고자 하는 함수는 다음의 기능과 프로세스를 가져야합니다.
- 클릭시 원하는 엘리먼트를 찾음
- 현재 스크롤 위치와 타겟(해당 엘리먼트)의 스크롤 위치를 구함
- 해당 위치로 스크롤을 이동하되 이동시간(duration)에 맞춰 서서히 이동
- 완료 후 종료
위 코드의 순서대로 하나씩 코드를 구현해보도록 하겠습니다. 먼저 함수 animteScrollTo()를 만들고 사용할 파라미터를 설정합니다.
@param {string}
_selector Target selector
@param {number}
_duration (Option) Duration time(ms) (Default. 800ms)
@param {number}
_adjust (Option) Adjustment value of position (pixel)
_selector : 선택자를 문자열로 넘겨주면 해당 엘리먼트를 이동할 위치 엘리먼트로 설정함
_duration : 이동까지의 지연 시간 설정하며 기본값은 800ms
_adjust : 이동할 위치를 + 또는 - 값의 픽셀 단위로 조정할 수 있음
여기서 _selector값은 필수이고 나머지는 옵션사항입니다. _adjust는 header등이 fixed 속성을 가져 안 보이는 경우 이 값만큼 추가할 때 사용하면 편리합니다.
! 코드 작성시 생각이 필요한 부분
코드를 작성하면서 가장 중요한 부분을 생각하며 적어보았습니다.
하나. 애니메이션 구현시 requestAnimationFrame()을 사용하여 최적화 할 것
관련 링크 바로가기 >https://webisfree.com/2020-03-19/[자바스크립트]-requestanimationframe()을-사용하는-방법-및-예제둘. 처음 시작할 시간에서 현재 시간을 빼기 위해 타임스탬프 값을 사용할 것 (쉽게 ms 값을 얻음)셋. 타이밍 함수(Timing Function)에 관한 고민 세 번째 고민은 타이밍 함수를 반영하는 부분입니다. 완성된 함수는 선형(Linear) 방식의 함수를 사용했지만 나중에는 ease-in-out, benzier 등 다양한 방식의 타이밍 함수를 선택 가능하도록 하는 것이 필요해 보입니다.
# 완성된 스크롤링 이동 함수 보기아래는 순수 자바스크립트로 완성된 함수 animteScrollTo()입니다.
/**
* Animate scrolling to a target position
* @param {string} _selector Target selector
* @param {number} _duration (Option) Duration time(ms) (Default. 800ms)
* @param {number} _adjust (Option) Adjustment value of position
*/
animteScrollTo = function(_selector, _duration, _adjust) {
const targetEle = document.querySelector(_selector);
if (!targetEle) return;
// - Get current & target positions
const scrollEle = document.documentElement || window.scrollingElement,
currentY = scrollEle.scrollTop,
targetY = targetEle.offsetTop - (_adjust || 0);
animateScrollTo(currentY, targetY, _duration);
// - Animate and scroll to target position
function animateScrollTo(_startY, _endY, _duration) {
_duration = _duration ? _duration : 600;
const unitY = (targetY - currentY) / _duration;
const startTime = new Date().getTime();
const endTime = new Date().getTime() + _duration;
const scrollTo = function() {
let now = new Date().getTime();
let passed = now - startTime;
if (now <= endTime) {
scrollEle.scrollTop = currentY + (unitY * passed);
requestAnimationFrame(scrollTo);
}
else {
console.log('End off.')
}
};
requestAnimationFrame(scrollTo);
};
};
사용 방법은 간단합니다. 만약 #test 이름의 id를 가진 엘리먼트로 이동한다면 아래와 같죠.
animteScrollTo('#test');
옵션으로 duration과 adjustY 값을 적용할 수 있으니 함께 사용하면 좋겠습니다. 테스트를 목적으로 아래 버튼 두 개를 추가하였습니다. 각각 클릭 후 잘 동작하는지 확인해보세요.