javascript와 html을 이용하여 진행을 하였습니다.
빠르게 코드 먼저 살펴보도록 하겠습니다.
const animationMove = function(selector)
{
const targetEl = document.querySelector(selector);
if (!targetEl) return;
const browserScrollY = window.scrollY ? window.scrollY : window.pageYOffset;
const targetScrollY = targetEl.getBoundingClientRect().top + browserScrollY;
const rem = parseFloat(getComputedStyle(document.documentElement).fontSize) * 3;
const finalScrollY = targetScrollY - rem;
window.scrollTo({ top: finalScrollY, behavior: 'smooth' });
};
const scollMoveEl = document.querySelectorAll("[data-animation-scroll='true']");
for(let i = 0; i < scollMoveEl.length; i++)
{
scollMoveEl[i].addEventListener('click', function(e)
{
const target = this.dataset.target;
animationMove(target);
});
}
코드를 한 줄 한 줄 살펴보도록 하겠습니다.
document.querySelectorAll("[data-animation-scroll='true']");
[data-animation-scroll='true']의 모든 요소를 반환을 합니다. 없을 경우에는 null을 반환하게 됩니다.
scollMoveEl[i].addEventListener('click', function(e){...});
addEventListener은 특정 이벤트가 발생하면 function을 실행하게 됩니다.
여기서는 'click' 이벤트가 발생시에 function이 실행되게 됩니다.
const target = this.dataset.target;
html에서 요소에 사용자 정의 속성을 추가하려면 data-로 속성을 추가할 수 있습니다. 이는 개발자용으로 예약되어 있기 때문에 속성을 data-*을 사용할 수 있습니다.
data-* 전역 특성은 사용자 지정 데이터 특성(custom data attributes)이라는 특성 클래스를 형성함으로써 임의의 데이터를 문서화하여 교환할 수 있는 방법입니다.
위와 같이 dataset.target은 data-target에 대한 요소를 문서화하여 반환을 하게 됩니다.
this는 자기자신을 뜻합니다. 여기서는 "data-animation-scroll='true'"를 가진 요소들 중에 클릭 이벤트가 발생된 요소를 가리키게 됩니다.
이제 animationMove 함수 내부를 살펴보도록 하겠습니다.
const targetEl = document.querySelector(selector);
위에서 살펴본 querySelectorAll에서 All이 빠진 모습입니다. 이는 함수 이름에서도 알 수 있듯이 select 요소 하나만 리턴을 하게 됩니다. 리턴할 요소들이 많다면, 가장 첫 번째 요소를 리턴하게 됩니다. 마찬가지로 select가 존재하지 않는다면 null을 리턴합니다.
const browserScrollY = window.scrollY ? window.scrollY : window.pageYOffset;
window.scrollY는 원점으로부터 문서를 수직방향으로 스크롤한 픽셀의 수를 나타내는, 부동소수점 값입니다. 양의 값이 위쪽 스크롤을 의미합니다. 쉽게 설명하면, 현재 window의 y축 위치입니다.
window.pageYOffset도 마찬가지 기능을 한다.
여기서 의문은 그렇다면 왜 2개를 다 사용한 것일까?? 그 이유는 scrollY는 IE에서 동작하지 않기 때문이다. 그렇기 때문에 window.scrollY를 사용을 할 수 없는 환경이라면 window.pageYOffset을 사용하는 것입니다.
const targetScrollY = targetEl.getBoundingClientRect().top + browserScrollY;
targetEl.getBoundingClientRect()는 element의 크기와 뷰포트에 상대적인 위치 정보를 제공하는 객체를 반환을 해줍니다. 현재 위치에서 target의 위치를 측정하는 것이기 때문에 음수가 나오기도 합니다.
그러고 나서 browserScrollY를 더해서 어느 정도 멀리 떨어져 있는지를 알아냅니다.
const rem = parseFloat(getComputedStyle(document.documentElement).fontSize) * 3;
parseFloat 함수는 인자값을 부동 소수점으로 반환을 해주는 함수입니다.
getComputedStyle 함수는 인자로 전달받은 요소의 모든 CSS 속성값을 담은 객체를 반환합니다. document.documentElement는 루트 요소를 나타내는 element를 반환합니다. getComputedStyle(document.documentElement).fontSize는 루트 요소의 css 중 fontSize를 가져오는 것입니다.
(이것은 원래의 위치보다 조금더 아래에 가도록 설정을 하는 것이기 때문에 필요 없으시면 이 부분은 제외하셔도 무방합니다. )
window.scrollTo({ top: finalScrollY, behavior: 'smooth' });
이제 마지막으로 위치로 이동을 해보도록 하겠습니다.
window.scrollTo()는 문서의 특정 좌표 집합으로 스크롤하게 됩니다.
options가 여러개가 있는데 그중에 top과 behavior을 사용하였습니다.
- top은 창이나 요소를 스크롤하기 위해 Y축을 따라 픽셀 수를 지정하게 됩니다. 맨 위의 위치를 기준으로 움직일 y축으로 움직일 pixel을 정합니다.
- behavior은 스크롤이 즉시 이루어지는지 아니면 부드럽게 애니메이션화되는지 여부를 결정합니다. smooth값을 주어서 스크롤이 부드럽게 애니메이션 되도록 만들었습니다.
한줄한줄 자세히 살펴보았습니다. 위의 코드를 사용하기 위해서는 html에 설정해 놓은 값들을 넣어주어야 합니다. 클릭할 요소에 "data-animation-scroll='true'"를 넣어서 클릭 시 이동이 되게 만드는 요소 목록에 추가를 하고 "data-target='#main'"를 요소 클릭 시 어디를 목적지로 삼을 지도 정해 주어야 합니다. 목적지 요소에는 당연히 "id='main'"을 넣어야 하죠.
이렇게 자연스로운 스크롤 이동에 대해 알아보았습니다. 하시는 프로젝트에 도움이 되셨으면 좋겠습니다.
'Language > javascript' 카테고리의 다른 글
자동 검색 및 pagination! (9) | 2024.11.11 |
---|---|
html 요소 클릭시 문자열 복사하기 (0) | 2024.11.04 |
모바일 전용 페이지 만들기 (0) | 2024.10.28 |