

<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으로 분리