youtube는 오른쪽 끝 chip ('새로운 맞춤 동영상')이 노출된 이후부터는 화면 resize크기에 맞춰 transform값이 커지고 있는 것을 알 수 있다.
const resizeListener = () => {
if (isLastExposed) {
const rightDiff =
(view.current as HTMLDivElement).getBoundingClientRect().right -
(container.current as HTMLDivElement).getBoundingClientRect().right;
setTransform((prev) => prev + (rightDiff - transformMargin));
}
};
window.addEventListener('resize', resizeListener);
return () => {
window.removeEventListener('resize', resizeListener);
};
}, [isLastExposed]);
따라서 resize event에 리슨하고, 마지막 chip이 노출되어 있을 때만 resize 크기에 맞게 transform크기를 늘려주는 방식을 생각했다.
잘되는 것처럼 보이나 문제가 있다.
문제 1 : 화면을 작게 했을 때, transform이 같이 줄어듬 (👇 유튭은 그렇지 않다.)
문제 2 : 화면을 빠르게 resize시키면 transform이 밀린다. (원인 파악이 잘 안된다.)
이제부터 이 두 가지 문제를 해결해야한다.
첫번째 chip이 노출되어 있을 때는 resize에 따른 transform이 작동하지 않게 하였다.
useEffect(() => {
const resizeListener = () => {
if (isLastExposed && !isFirstExposed) {
const nextTransform =
(view.current as HTMLDivElement).getBoundingClientRect().right -
(container.current as HTMLDivElement).getBoundingClientRect().right -
transformMargin;
setTransform((prev) => prev + nextTransform);
}
};
window.addEventListener('resize', resizeListener);
return () => {
window.removeEventListener('resize', resizeListener);
};
}, [isLastExposed, isFirstExposed]);
밀리는 이유는 previous transform이 466밖에 되지 않지만 776을 옆으로 밀기 때문에다.
resize 될 때마다 getBoundingClientRect로 차이를 계산하는 부분이 정확하지 않다.
이 부분에 대해서 매 resize event가 trigger될 때마다 transform이 완료된 element들의 width 차이를 계산하고 싶었다.
eventloop에서의 순서를 정확하게 다루거나, repaint-reflow에 대한 이해가 깊었다면 좀 더 우아한 방식으로 해결할 수 있었을 것 같다.
useEffect(() => {
const resizeListener = () => {
if (isLastExposed) {
const nextTransform =
(view.current as HTMLDivElement).getBoundingClientRect().right -
(container.current as HTMLDivElement).getBoundingClientRect().right -
transformMargin;
setTransform((prev) => {
// prev + nextTransform에 대한 기준 추가
if (prev + nextTransform < 0) {
return prev + nextTransform;
}
return 0;
});
}
};
window.addEventListener('resize', resizeListener);
return () => {
window.removeEventListener('resize', resizeListener);
};
}, [isLastExposed, isFirstExposed]);