<ChipsView>
<ChipsContainer>
<Chip/>
<Chip/>
/*... many more...*/
</ChipsContainer>
</ChipsView>
이런 형태의 구조다.
많은 캐러셀이 그러듯이 ChipsView
는 ChipsContainer
의 일부분만 보여주게 하고,
Container가 좌우로 움직이는 형태로 구현했다.
그런데... Container의 width가 View의 Width와 똑같이 잡혀있었다.
(Chips들이 많아 범위가 넘어가야함에도 불구하고... Overflow)
방식을 고민하다가 youtube에서 구현한 것을 봤더니
display: inline-block;
을 보고 혹시나...? 하는 마음에 적용했더니 chips를 모두 포함하는 width를 가지게 되었다.
참고한 블로그를 읽어보니 inline-block
은 고유의 size/spacing을 가질 수 있다는 것을 확인했다.
해결.
(문제를 조금 분리했다.)
IntersectionObserver를 이용하였다.
useEffect(() => {
const callback: IntersectionObserverCallback = (entries) => {
entries.forEach((entry) => {
switch (entry.target.id) {
case 'lastChip':
setIsLastExposed(entry.isIntersecting);
break;
case 'firstChip':
setIsFirstExposed(entry.isIntersecting);
break;
default:
break;
}
});
};
const options = {
root: view.current,
threshold: 1.0,
};
const observer = new IntersectionObserver(callback, options);
if (target.current) {
const { children } = target.current;
observer.observe(children[0]);
observer.observe(children[children.length - 1]);
}
}, []);
로직은 다음과 같다.
ChipsView
를 Observer에 root Option 대상으로 지정#firstChip
과#lastChip
을 observer에 등록- entries를 관찰하고 있다가 각 Chip이 안으로 들어오면 state에 따라 화살표를 제거
<ChipsView> /* <--- Observer :root */ <ChipsContainer> <Chip id="firstChip"/> /* observe 대상 */ <Chip/> <Chip/> <Chip/> <Chip id="lastChipChip"/> /* observe 대상 */ </ChipsContainer> </ChipsView>
해결.
오른쪽 chip이 노출된 이후에도 고정값으로 정해놓은 320px의 transform이
끝까지 시행되는 것을 알 수 있다. chip이 노출되는 순간 transform은 멈춰야한다.
const onLeftClick = () => {
const leftDiff =
(view.current as HTMLDivElement).getBoundingClientRect().left -
(container.current as HTMLDivElement).getBoundingClientRect().left;
setTransform((prev) => prev + (leftDiff < 320 ? leftDiff + 20 : 320));
};
const onRightClick = () => {
const rightDiff =
(container.current as HTMLDivElement).getBoundingClientRect().right -
(view.current as HTMLDivElement).getBoundingClientRect().right;
setTransform((prev) => prev - (rightDiff < 320 ? rightDiff + 20 : 320));
};
<ChipsView ref={view}>
<ChipsContainer ref={container}>
<Chip/>
<Chip/>
<Chip/>
<Chip/>
</ChipsContainer>
</ChipsView>
완료.
이후는 3으로 분리