Image Zoom on Hover 기능의 이미지 뷰어 바닐라 자바스크립트로 구현하기

2021년 8월 27일에 작성된 포스트를 옮겨왔습니다. 원본 글 확인하기
Image Zoom on Hover 이미지 뷰어
Image Zoom on Hover 기능은 쇼핑몰 상세 페이지에서 흔히 볼 수 있는 기능입니다. 마우스 커서를 이미지 영역 위에 올리면 확대된 이미지를 보여주는 뷰포트가 생겨 별도의 모달이나 윈도우 없이도 이미지를 자세히 볼 수 있는 인터랙션입니다.
라이브러리 없이 자바스크립트를 활용하여 사용자 인터랙션을 직접 만들어보고 싶었고, 객체의 좌표를 활용한 효과는 어떻게 만들 수 있는지 학습할 목적으로 만들었습니다.
문제의 정의
문제 해결은 문제를 정의하고, 내가 원하는 것을 명확히 하고, 차근차근 해결해 나가는 과정이라고 생각합니다.

아래 다섯 개의 명제가 이미지 줌 기능이 정상적으로 작동되기 위한 조건입니다. 아래 명제들을 가정하고, 하나씩 풀어가는 과정을 설명해드립니다.
- 이미지 영역 위에 마우스 커서를 올리면 이너 프레임과 확대창이 나타난다.
- 마우스 커서가 영역 밖으로 나가면 이너 프레임과 확대창은 사라진다.
- 이너 프레임은 마우스 커서를 따라 움직인다.
- 이너 프레임은 이미지 영역 경계 안에서만 움직인다.
- 확대 이미지는 정확히 이너 프레임 영역의 이미지가 보여야 하며, 크기가 달라도 움직임은 동기화되어야 한다.
const zoomFrame = document.querySelector(".zoomFrame");
const zoomLens = document.querySelector(".zoomLens");
const zoomWindow = document.querySelector(".zoomWindow");
문제 해결 과정
명제 1 - 이미지 영역 위에 마우스 커서를 올리면 이너 프레임과 확대창이 나타난다.
유저의 어떤 동작을 이벤트로서 인식할 것인지 정의하면 문제 해결이 쉬워집니다.
줌 프레임 영역에 커서가 진입했다 + 마우스가 움직인다 =
mousemove
zoomFrame.addEventListener("mousemove", callbackFn);
mouseenter
영역 안으로 진입했는지 여부만 따지고, mouseover
는 이벤트 입력 주기가 너무 띄엄띄엄이라 사용하지 않았습니다.
더 높은 FPS로 부드러운 동작이 가능한 mousemove
를 사용했습니다. 아래 비교를 보면 차이가 확연하게 보입니다.

영역 내의 움직임을 제어하는 함수는 별도의 함수로 선언합니다.
function handleMouseMove(event) {
zoomLens.style.display = "block";
zoomWindow.style.display = "block";
}
명제 2 - 마우스 커서가 영역 밖으로 나가면 이너 프레임과 확대창은 사라진다.
줌 프레임 영역 밖으로 커서가 나간다 =
mouseleave
zoomFrame.addEventListener("mouseleave", () => {
zoomLens.style.display = "none";
zoomWindow.style.display = "none";
});
마우스가 대상 밖으로 나가면 이벤트로 인식되는 mouseleave
를 사용했습니다.
마우스가 창을 떠날땐 요소를 숨기는 역할밖에 안하기 때문에 이벤트 리스너 인자 속에 그대로 선언했습니다.
명제 3 - 이너 프레임은 마우스 커서를 따라 움직인다.
요소가 마우스 커서를 따라다니게 하려면 마우스의 좌표를 알아야 합니다.
뷰포트상의 좌표를 찾는 것은 쉽지만 제가 원하는 것은 프레임의 위치와 관계된 상대적 마우스 좌표입니다.
이 값을 얻기 위해서 내가 찾아야 할 것은 아래와 같습니다.
- 뷰포트 속 마우스 커서의 상대 좌표
- 뷰포트 속 프레임 영역의 상대적 위치