-
Notifications
You must be signed in to change notification settings - Fork 2
색상 영역 컴포넌트
eVe68 edited this page Aug 25, 2024
·
5 revisions
- 색상 영역 컴포넌트는 스크롤에 따라 변화하는 화면을 구현
- 사용자 화면 높이에 따라 오차가 발생하지 않도록 스크롤 계산 기준을 설정해야 함
- 색상 네비게이션을 구현하여 사용자가 원하는 색상 영역으로 이동 가능하도록 해야 함
- 섹상 영역을 지정해 내부 스크롤을 사용하면 스크롤이 끊김
- UX 적으로 좋은 경험이 전혀 아니었음
- 자연스럽게 아래로 내리는 과정에서 색상이 변경되었으면 좋겠음
- 섹션 내부 스크롤이 아닌 메인 화면 스크롤을 그대로 이용
- 메인 화면 스크롤을 이용할 때 위에서부터의 절대값을 이용하면 사용자에 따라 계산에 오차가 있을 수 있음을 고려해야 했음
- 처음에는 자동차 이미지와 배경을 따로 두었음
- 배경과 자동차 이미지가 동시에 동기화되어 변화해야 함
- 배경과 자동차가 하나인 하나의 이미지를 사용하여 구현
- 르노삼성 홈페이지를 디버깅해 보았을 때 CSS의 마스크를 사용하여 이미지를 자름
- CSS clip-path 속성을 사용
-
inset(0 0 ${변수}% 0)
을 통해 변수 값을 변경하면 아래부터 잘려 보이는 비율을 조절
- 스크롤 상태에 맞추어 요소가 변화해야 함
- 스크롤 상태에 따른 지속적인 리렌더링이 필수적이라고 생각함
- requestAnimationFrame을 사용하기로 결정
useEffect(() => {
requestAnimationRef.current = requestAnimationFrame(render);
return () => {
cancelAnimationFrame(requestAnimationRef.current);
};
}, []);
- 시스템이 프레임을 그릴 준비가 되면 애니메이션 프레임을 호출하여 애니메이션 웹페이지를 보다 원활하고 효율적으로 생성할 수 있도록 함
- 실제 화면이 갱신되어 표시되는 주기에 따라 함수를 호출해주기 때문에 자바스크립트가 프레임 시작 시 실행되도록 보장함
- 이를 통해 스크롤이나 애니메이션의 업데이트가 자연스럽고 성능이 최적화된 방식으로 이루어 질 수 있음
-
const scrollPosition = -divRef.current.getBoundingClientRect().y;
를 통해 절대적인 스크롤 상태 값을 가져옴 - divRef를 기준으로 현재 뷰포트의 위치를 가져올 수 있음
- 이 값에 음수를 취함으로써
scrollPosition
은 색상 영역으로부터 아래로 스크롤된 거리를 나타냄 - 이 값을 requestAnimationFrame 안에서 사용해 지속적으로 계산하도록 함
const render = () => {
if (divRef.current) {
const imageHeight = divRef.current.offsetHeight / colorInfoData.length;
const scrollPosition = -divRef.current.getBoundingClientRect().y;
const newClipPosition = colorInfoData.map((_, index) => {
const imageOffset = (index + 1) * imageHeight;
if (
imageOffset < scrollPosition &&
scrollPosition < imageOffset + imageHeight
) {
return ((scrollPosition - imageOffset) / imageHeight) * 100;
} else if (imageOffset < scrollPosition) {
return 100;
} else {
return 0;
}
});
setClipPosition(newClipPosition);
}
requestAnimationFrame(render);
};
- 결국 메인 페이지 전체에서 자연스럽게 스크롤이 되어야 하므로 레이아웃 영역 자체는 한 페이지가 아닌 겹친 페이지만큼의 길이
- 표시할 색상이 5가지이므로
5*(화면 높이)
만큼 스크롤이 되어야 함
- 표시할 색상이 5가지이므로
- 2장이 겹친 상태에서 스크롤이 될 때 위쪽에 위치한 이미지가 점점 가려지는 방식으로 구현해야 함
- 결국 메인 페이지에 종속되어있기 때문에 첫 화면에서부터 떠 있는 문제
- 이를 해결하기 위해 색상 영역에 종속시키면 스크롤에 따라 그냥 올라가 버리는 문제
- top-0을 줘서 해결하려 했지만 스크롤을 따라 올라가려다 top 요소에 의해 잡혀 내려오는 듯 덜덜거리는 현상 발생
- top을 0으로 설정하고 index에 따라 가려지는 비율을 결정하는 방식
- 하지만 요소가 겹치지 않아 top-0에 붙는 시점에 이미지가 모두 가려지는 문제
- 첫 번째 이미지 뒤에 두번째 이미지가 top-0위치까지 올라온 뒤 첫 번째 이미지를 가리기 시작함
- 0번 index 요소의 스크롤이 길어졌지만 이외의 해결책을 찾지 못하였음
-
const imageOffset = (index + 1) * imageHeight;
에서 index에 1을 더한 이유임
- 이미지 여러장이 겹친 상태에서의 조건부 논리를 통해 어떻게 보여질지 결정함
- 현재 스크롤 위치가 이미지의 시작과 끝 사이에 있는 경우:
(scrollPosition - imageOffset) / imageHeight * 100
계산을 통해 클립 비율을 계산 - 스크롤 위치가 이미지의 끝을 지나간 경우: 클립 비율을 100%로 설정하여 이미지가 완전히 보이지 않도록 함
- 스크롤 위치가 이미지의 시작 전에 있는 경우: 클립 비율을 0%로 설정하여 이미지가 전혀 보이도록 함
- 현재 스크롤 위치가 이미지의 시작과 끝 사이에 있는 경우:
- 🛠️ 테스트 코드 작성
- 워드 클라우드
- 컴포넌트 설계
- 스토리북 적용
- useAnimation Hook
- 룰렛 컴포넌트
- 토스트 컴포넌트
- useInView Hook
- 색상 영역 컴포넌트
- msw
- webpack
- 컴포넌트 동시에 띄우기