Image zoom in 구현하기 - 1

jh_leitmotif·2021년 10월 1일
0

Frontend 개인 공부

목록 보기
2/24
post-thumbnail

🧐 개요

요즘 Node와 React를 이용해 웹 쇼핑몰 페이지를 클로닝 아닌(?) 클로닝을 하며 공부 중입니다.

그 중, 여러 쇼핑몰 사이트에서 지원하는 기능 중 하나인

이미지에 커서를 가져다 댔을 때, 자동으로 zoom in 되어 상세히 볼 수 있게 하는 것을

구현해보았습니다.

물론 관련 API는 다음 링크에 있는 것 처럼 많아서 가져다 쓰면 되는 일이긴 하지만

관련 링크 : https://www.cssscript.com/best-image-zoom-javascript-css/

그 전에 어떤 방식으로 동작하는지 알고자 직접 구현해보았습니다.

📋 설계하기

매우 조잡하지만..!

제품 게시판에서 상세 정보 페이지로 이동하면
위와 같은 방식의 레이아웃으로 짜여진 상세 페이지로 이동하게 됩니다.

만약 사용자가 상품 이미지에 커서를 올려서 이동하는 경우
커서를 기준으로 한 영역이 옆 상품 정보 칸 위에 줌인되어 보여지는 것으로 생각했습니다.


( 대충 위 사진 처럼 구현하고 싶었던 겁니다! )

아래는 코드를 작성하기 전 고민했던 부분입니다.

1. 사용자 커서의 x,y 좌표
2. 몇 배로 zoom을 넣을까?
3. 결과 창의 position 속성은?
4. 어떤 element에 어떤 event?

1. 사용자 커서의 x,y 좌표

event.clientX
-> 스크롤을 비포함한 현재 페이지 기준의 위치
event.pageX
-> 스크롤을 포함한 현재 문서 기준의 위치
event.screenX
-> 모니터 화면 기준의 커서 위치
event.offsetX
-> 이벤트 대상 객체의 상대적 커서 위치

  • 제품 상세 페이지는 대부분 스크롤을 포함한다. 그러므로 clientX 탈락!
  • 사용자마다 모니터 크기는 다 다르지 않을까? screenX 탈락!
  • 상대적 위치보다 절대 위치를 생각하는게 편하지 않을까? offsetX 탈락!

의식의 흐름이 맞는지는 모르겠지만, 여하튼 저는 위의 이유로 pageX, pageY 속성을 사용했습니다.

2. 몇 배로 Zoom을 넣을까?

이는 간단합니다.

위와 같이 이미지의 최대 너비를 250px로 정해두었습니다.

따라서... 그냥 주먹구구식으로 50px를 기준으로 잡아 5배 확대하기로 했습니다.

3. 결과 창의 position 속성은?

static
-> 기본 값
fixed
-> 사용자 View 기준, 고정된 위치
relative
-> 부모, 자식 등의 관계에 따라 위치가 지정됨
absolute
-> 부모요소가 relative 속성이면 부모가 기준점이나, 그렇지 않으면 브라우저를 기준.

결과 창은 상품 정보 위에 떠올라야 합니다.
즉, 다른 요소의 위치를 건드리지 않아야 하므로 static과 relative는 탈락!

fixed는 계속 사용자의 눈에 보여야하는 컴포넌트에 어울립니다.
확대된 이미지를 지속적으로 보는 것도 피곤할테니, fixed도 탈락!

그렇게 absolute를 쓰기로 결정했습니다.

4. 어떤 element에 어떤 event?

mouseenter / leave
-> 지정된 요소 및 자식요소의 영역에 대한 커서 진입/퇴장 이벤트
mouseover / out
-> 자식요소 영역을 제외한 지정 요소에 대한 커서 진입/퇴장 이벤트
mousemove
-> 커서의 움직임을 감지하는 이벤트

😡 잘못됐던 접근

위의 설명만 보고서 mousemove 이벤트로 zoom in을 그리고

mouseout 또는 mouseleave로 커서 주위에 그려진 영역을 지우면 되겠다! 싶었는데..

onMouseMove={imgMouseMoveFunc} onMouseLeave={imgMouseLeaveFunc}

보기 좋게 틀려버렸습니다.

Mousemove 이벤트는 아무래도 들어갔다가 나왔다하는 것이 반복되는 것으로 보입니다.

우회하기

상품의 이미지는 부모 div tag 안에서 선언됩니다.

따라서 div tag에 적절한 padding값을 주어 img 태그 사이 여백을 준 뒤

onMouseOver 이벤트를 통해 만약 커서가 닿는 부분의 태그 이름이 DIV라면

커서 주변에 생기는 네모 영역을 지우는 것으로 우회했습니다.

특이점은 ref로 지정해둔 커서 영역이 React의 지속적인 렌더링 특성 때문인지
순간 undefined가 되면서 오류를 뱉던 것이었습니다.

일단은 if로 조건을 걸어 정상작동하도록 했습니다.


이어질 포스트에서는 결과 창을 렌더링하는 부분으로 넘어갑니다.

profile
Define the undefined.

0개의 댓글