한 줄 요약 위아래로 굴리면 항목이 가운데에 딱 멈추고, 그 가운데 값이 선택되는 아이폰식 회전 휠이에요.
이럴 때 필요해요
시간수량옵션처럼 정해진 값 중 하나를 빠르게 고르는 상황에서, 긴 드롭다운이나 작은 +/- 버튼보다 휠이 훨씬 직관적이에요. 특히 모바일에서 엄지로 굴려 고르는 손맛이 좋죠. 알람 시간, 타이머, 생년월일, 인원수 선택 같은 곳에 잘 어울려요.
어떻게 동작하나
세로로 스크롤되는 목록에 CSS
scroll-snap을 걸어서, 손을 떼면 항목이 가운데 칸에 자석처럼 딱 멈춰요.지금 무엇이 선택됐는지는 따로 추적하지 않고, 스크롤한 거리(
scrollTop)를 칸 높이로 나눠 "가운데에 온 항목"을 그때그때 계산해요.가운데에서 멀어진 항목일수록
rotateX로 뒤로 눕히고 작게흐리게 만들어요. 그러면 평평한 목록이 둥근 원통(드럼)을 옆에서 보는 것처럼 보여요. 이 효과는 컨테이너의perspective가 만들어요.이 3D 변형은 상태를 바꾸지 않고 각 항목의 style을 직접 칠해서 줘요. 스크롤은 1초에도 수십 번 일어나니,
requestAnimationFrame으로 한 프레임에 한 번만 그려 부드럽게 유지해요.
핵심은 이거예요
선택값을 손으로 관리하지 마세요 스크롤 위치 하나가 곧 선택값이에요(가운데 인덱스 = scrollTop 칸높이). 스냅은 CSS가, 멈출 위치 계산은 이 한 줄이 해주니, 우리가 할 일은 그 결과로 화면을 칠하는 것뿐이에요.
놓치기 쉬운 것
첫 항목과 마지막 항목도 가운데에 오려면 위아래에 빈 여백(패딩)을 칸 높이만큼 줘야 해요. 안 그러면 끝값이 가운데까지 안 와요.
매 스크롤마다 모든 항목을 React로 다시 그리면 버벅여요 ref로 DOM을 직접 갱신하고 선택값만 상태로 둬요.
3D
rotateX가 보이려면 부모(스크롤 영역)에perspective가 있어야 해요.
이런 곳에 써요
알람타이머의 시분 선택, 인원/수량 고르기
생년월일날짜 일부를 빠르게 고르는 모바일 폼
옵션이 정해진 설정값(폰트 크기, 반복 횟수 등) 선택