Chips 캐러셀 만들기 3부

김민석·2022년 1월 30일
0

한 달에, 한 주제

목록 보기
19/19


네번째 문제

: 오른쪽 끝 chip이 노출되면 화면 resize크기에 따라 transform 변경하기

Youtube

내꺼

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이 밀린다. (원인 파악이 잘 안된다.)

이제부터 이 두 가지 문제를 해결해야한다.

네번째 문제 - 1

: 화면을 작게 했을 때, 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]);

네번째 문제 - 2

: 화면을 빠르게 resize시키면 transform이 밀림

밀리는 이유는 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]);

완료

0개의 댓글