요즘 이런 모션이 많아서 찾아봤다. 라이브러리도 있어서 그것으로 시도해봤으나 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를 조정해 준 것이다.