Notice
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
Tags
- PongWorld
- GIT
- react native 개발
- 리액트 네이티브
- React
- s3 upload
- Access Key 생성
- 리액트
- react native CLI
- react native 세팅
- 리액트 네이티브 에러
- fire base
- firebase 라이브러리
- 문자열 대소문자
- 문자열 대소문자 구별
- aws bucket 정책
- react native font
- react native picker
- react native
- error
- js
- AWS Access Key
- img upload
- 리엑트 네이티브 아이콘
- babel.config.js
- Next.js
- 백준
- AWS
- 에러
- Project
Archives
- Today
- Total
밝을희 클태
[ Next.JS ] 이미지 슬라이더(image-slider) UX 개선 본문
기존에 이미지 슬라이더가 이미지 드래그 도중에 아래 또는 위로 스크롤을 하면 스크롤이 됐다. 그래서 터치 이벤트가 시작될 때 기본 동작을 막아버렸는데 이렇게 되면 문제가 이미지 슬라이더 영역에서는 스크롤이 되지 않아 그 외의 영역을 스크롤해야 했다. 더 좋은 방법이 없을까 고민을 하다가 다른 대기업들의 이미지 슬라이더를 한참을 만져보다가 아이디어가 떠올랐다.
터치 이벤트가 시작이 되고 드래그가 일어날때 y, x의 이동거리를 계산해서 y가 더 크다면 페이지를 스크롤하고, x의 이동거리가 더 크다면 이미지 슬라이더가 드래그되게 하면서 동시에 'touchmove' 이벤트의 기본동작을 막아준다. 정말 별거 아니지만 여기 까지 오는데 시간이 엄청 오래 걸렸다...
touchstart event
const startTouch = useCallback(
e => {
// 아래의 hook으로 지금 동작이 스크롤중인지 이미지 슬라이더 드래그 중인지 판단
// 처음에는 undefined로 초기화
isScrolling.current = undefined;
setIsTransitioning(true);
travelRatio.current = 0;
// 터치 좌표를 초기화
initDragPos.current = { x: e.touches[0].clientX, y: e.touches[0].clientY };
originOffset.current = offset;
// passive 옵션을 false로 지정해줘야 touchmove의 기본 동작을 막을 수 있다.
document.addEventListener('touchmove', move, { passive: false });
document.addEventListener('touchend', end);
},
[offset, move, end],
);
touchmove event
const move = useCallback(
e => {
const travelX = e.touches[0].clientX - initDragPos.current.x;
const travelY = e.touches[0].clientY - initDragPos.current.y;
// hook의 값이 undefined 이면 y, x의 이동거리를 계산해서 hook의 값을 변경
// 페이지 스크롤중이라면 'true' 이미지 슬라이더 드래그중이면 'false'
if (isScrolling.current === undefined) isScrolling.current = Math.abs(travelY) > Math.abs(travelX);
if (isScrolling.current === false) {
if ((travelX > 0 && currentImageIndex === 0) || (travelX < 0 && currentImageIndex === images.length - 1))
return;
e.preventDefault();
if (Math.abs(travelRatio.current) < 0.8) {
travelRatio.current = travelX / clientWidth;
if (imageShowRef.current)
imageShowRef.current.style.transform = `translateX(${originOffset.current + travelX}px)`;
}
}
},
[clientWidth, currentImageIndex],
);