`react-scroll-parallax`

스크롤 효과 라이브러리인 `react-scroll-parallax` 리뷰를 합니다.

2023-04-08

설정

jscottsmith/react-scroll-parallax: 🔮 React hooks and components to create parallax scroll effects for banners, images or any other DOM elements.

tsdx를 사용합니다. 마지막 커밋은 2022년 3월이지만 유명한 CLI툴 입니다. 리엑트 기반의 컴포넌트 라이브러리를 만들 때 boilerplate를 생성합니다. rollup을 사용하여 cjs, esm, umd를 지원하는 단일 js 파일을 만들어 줍니다.

리엑트 17 버전대의 class형 컴포넌트와 hook 기반 라이브러리로 구현하였습니다. ts-monorepo에 link를 할떄, ReactNode 정의가 달라 오류가 났습니다.

ts-monorepo는 pnpm으로 되어 있기 때문에 다음과 같이 link 명령을 사용합니다.

pnpm link /Users/swcho/projects/swcho/react-scroll-parallax

사용 예시는 다음과 같습니다.

https://react-scroll-parallax-examples.vercel.app/

기본적으로 특정 엘리먼트가 viewport에 진입할 때와 빠져나갈 떄를 기준으로 transform을 설정할 수 있습니다. 또한 스크롤 변화 시, 이벤트 콜백을 제공하기 때문에 다양하게 활용이 가능해 보입니다.

parallax-controller라는 모듈을 사용합니다. 분석을 위해선 추가로 설정을 해 줍니다.

전체적인 테스트 환경은 ts-monorepo 기반으로 구성했습니다.

동작 과정

<ParallaxProvider>를 react 코드에 설정해 주면 ParallaxController를 생성 합니다. 스크롤을 포함하는 엘리먼트를 넘겨주면, ParallaxController 객체가 스크롤 관련 처리를 수행합니다. ParallaxControllerscroll 이벤트와 함께, resize, blur, focus, load 이벤트를 처리합니다.

이렇게 스크롤을 포함하는 엘리먼트에 대한 초기 설정을 <ParallaxProvider>에서 하고 나면, <Parallax> 컴포넌트를 사용하여 viewport 영역의 enter, exit, progress 등의 이벤트를 받아 처리할 수 있습니다. 또한 transform, opacity와 같은 css 속성 값의 start, end 값과 progress에 따라 적용하는 easing 함수 등을 설정할 수 있습니다.

Scroll 이벤트 처리

생성 과정 중에서 전달 받은 target HTMLElement dom 객체의 scroll 이벤트를 등록합니다. target 엘리먼트를 전달하지 않을 경우, window 객체의 scroll 이벤트를 등록합니다.

addEventListener의 요상한 옵션들 중의 하나 Passive : 네이버 블로그

addEventListenerpassive 옵션은 scroll 이벤트 처리 과정 중 preventDefault를 할 것인지를 브라우저에게 알려주는 역할을 합니다.

parallax-controller 해당 옵션의 지원여부를 알아내는 코드는 다음과 같습니다.

export function testForPassiveScroll() {
  let supportsPassiveOption = false;
  try {
    const opts = Object.defineProperty({}, 'passive', {
      get() {
        supportsPassiveOption = true;
        return true;
      },
    });
    // @ts-expect-error
    window.addEventListener('test', null, opts);
    // @ts-expect-error
    window.removeEventListener('test', null, opts);
  } catch (e) {}
  return supportsPassiveOption;
}

opts라는 proxy 객체를 사용하여 passive라는 옵션을 브라우저가 읽으면 해당 기능을 지원하는 것으로 판단합니다.

이렇게 알아낸 값으로 scroll 이벤트 등록 옵션을 결정합니다. 물론 성능향상을 위해 passive 옵션을 true로 설정합니다.

...
  el.addEventListener(
    'scroll',
    this._handleScroll,
    this._supportsPassive ? { passive: true } : false
  );

영역 정보

기본적으로 영역에 대한 정보는 다음과 같은 dom 프로퍼티 값을 참조 합니다.

...
  const width = window.innerWidth || html.clientWidth;
  const height = window.innerHeight || html.clientHeight;
  const scrollHeight = html.scrollHeight;
  const scrollWidth = html.scrollWidth;

이벤트 동작

scroll 이벤트 뿐만아니라 resize, blur, focus, load 이벤트에 따라 Update를 진행합니다.

scroll 이벤트 처리에 추가로 viewport 크기 변경에 의한 값 조정을 모두 재조정하는 setCachedAttributes 작업을 수행합니다.

Loading script...