Table of contents
1. 글의 목적
롯데백화점 메인 페이지를 클론하며 커스텀 마우스 포인터를 구현하게 되었다. 처음에는 단순히 포인터를 커스터마이징하는 작업이라고 생각했지만, 특정 UI에 따라 반응하는 커스텀 포인터를 구현하면서 고려해야 할 세부 사항이 많다는 것을 깨달았다. 이러한 경험을 바탕으로 커스텀 마우스 포인터 구현 과정을 정리하여 공유하고자 한다.
2. CSS에서 해야할 작업들
마우스 포인터를 커스텀하기 위해서는 먼저, 문서 전체의 cursor
를 none
으로 지정해 주어야 한다. 이후 cursor를 대체할 요소에 position: fixed, pointer-events: none, transform: translate(-50%, -50%)
속성들을 필수로 지정해주면 된다.
html {
cursor: none;
}
.cursor {
width: 2rem;
height: 2rem;
position: fixed;
border-radius: 50%;
background-color: $cursor;
pointer-events: none;
transform: translate(-50%, -50%);
translate(-50%, -50%)
를 지정하지 않으면 cursor
요소가 0, 0
을 기준으로 위치하기 때문에 동작을 하게 되면 다소 어색하게 보일 수 있다. cursor
요소가 기존 마우스 포인터의 끝 지점을 중심으로 위치할 수 있도록 50%, 50%
으로 지정해 주었다.
pointer-events: none
을 사용하는 이유는 해당 요소가 마우스 이벤트를 무시하고 다른 요소 아래에 있는 요소로 이벤트를 통과시킬 수 있기 때문이다. 특히 이 경우에는 마우스 포인터와 커스텀 커서가 항상 겹쳐 있어서 링크 요소 등을 선택하는 데 제한이 생긴다. pointer-events: none
을 설정함으로써 부모 요소인 마우스 포인터에서도 이벤트를 받을 수 있도록 했다.
3. JS에서 해야할 작업들
마우스를 움직일 때마다 발생하는 mousemove
이벤트를 활용하여 현재 마우스 포인터 위치에 커스텀한 커서 요소가 따라다닐 수 있도록 구현했다. 각 이벤트가 발생할 때마다 커서의 위치를 clientX
와 clientY
값으로 설정해 주었다. 또한, 처음 mousemove
이벤트가 발생했을 때 커서가 갑자기 나타나는 느낌을 줄이기 위해 약간의 딜레이 후에 opacity
를 1
로 설정했다. 이렇게 함으로써 사용자는 부드럽게 커서를 조작할 수 있게 된다.
const cursor = document.querySelector(".cursor");
function setCursorPosition(left, top) {
gsap.to(cursor, 0.4, {
left: `${left}px`,
top: `${top}px`,
});
}
window.addEventListener("mousemove", (e) => {
gsap.to(cursor, 0.4, {
opacity: 1,
delay: 0.2,
});
setCursorPosition(e.clientX, e.clientY);
});
이어서 특정 요소에 접근할 때마다 커서 크기 변화, 텍스트 추가, 화살표 추가 등 해당 요소의 요구 사항에 맞는 다양한 디자인을 추가해 커스텀 커서를 완성했다.