react framer-motion 스크롤 비디오

해적왕·2022년 8월 16일
1
post-custom-banner

요즘 이런 모션이 많아서 찾아봤다. 라이브러리도 있어서 그것으로 시도해봤으나 8년전 마지막 업데이트인 점과 부드럽게 이어지지 않아서 이것으로 올리게 됐다.
여태 이미지를 여러개 붙인 건 줄 알았는데 스크롤로 동영상을 컨트롤 하는 것이었다.

https://codesandbox.io/s/framer-scroll-video-71btc?file=/src/App.js

역시 코드샌드박스에 있었다.

const VideoCmp = () => {
  const url =
    "jellyfish.mp4";
  const { scrollYProgress, scrollY } = useScroll();
  const ref = useRef();

  const updateAtScroll = () => {
    let video = ref.current;
    video.pause();
    const p = scrollYProgress.get();
    const currentFrame = Math.round(p * video.duration * 1000) / 1000;
    video.currentTime = currentFrame;
  };

  useEffect(() => scrollY.onChange(throttle(updateAtScroll, 80)), []);

  return (
    <VideoS ref={ref}>
      <source src={url} type="video/mp4" />
    </VideoS>
  );
};

const p = scrollYProgress.get();
스크롤 지수를 가져온다.


const currentFrame = Math.round(p * video.duration * 1000) / 1000;
video.duration은 재생시간이다. 나는 9초의 동영상을 써서 9.366667이라고 뜨는 걸 확인했다.
이 부분이 스크롤을 감지해 동영상이 보이도록 하는 부분이다.

useEffect(() => scrollY.onChange(throttle(updateAtScroll, 80)), []);
Scroll X/Y: 절대 스크롤 위치(픽셀)
ScrollXProgress/YProgress: 정의된 간격띄우기 사이의 스크롤 위치이며, 0과 1 사이의 값으로 사용.

throttle 부분

const throttle = (callback, delay) => {
  let last;
  let timer;
  return function () {
    let context = this;
    let now = +new Date();
    let args = arguments;
    if (last && now < last + delay) {
      clearTimeout(timer);
      timer = setTimeout(function () {
        last = now;
        callback.apply(context, args);
      }, delay);
    } else {
      last = now;
      callback.apply(context, args);
    }
  };
}

arguments 객체는 모든 함수 내에서 이용 가능한 지역 변수이다. arguments 객체를 사용하여 함수 내에서 모든 인수를 참조할 수 있으며, 호출할 때 제공한 인수 각각에 대한 항목을 갖고 있습니다. 항목의 인덱스는 0부터 시작한다.

arguments 객체는 Array가 아니다. Array와 비슷하지만, length 빼고는 pop()과 같은 어떤 Array 속성도 없습니다. 그러나 실제 Array로 변환할 수 있다.

setTimeout 은 일정시간이 지난 후에 함수가 실행되도록 하고, clearTimeout 은 setTimeout을 취소하는 역활을 한다.

솔직히 throttle 부분을 잘 모르겠다.. ㅠ 어려워

메인 부분

const VideoExample = () => {
  return (
    <Wrap>
      <Video>
        <VideoCmp />
      </Video>
    </Wrap>
  )
}
export default AboutFlow;

const Wrapp = styled(motion.div)`
  position:relative;
  height:300vh;
  width:100%;
`

const Video = styled(motion.div)`
  height:700px;
  width:90%;
  margin:0 auto;
  top:250px;
  border-radius:50px;
  overflow: hidden;
  position:sticky;
  left:0;

  video{
    width:100%;
    height:100%;
    vertical-align:bottom;
    object-fit:cover;
  }
`


그럼 이렇게 된다.
처음 이미지는 scrollYProgress 로 width,height를 조정해 준 것이다.

profile
프론트엔드
post-custom-banner

0개의 댓글