useScroll
스크롤 애니메이션을 만들때 사용 👉🏻 progress indicators, parallax effects
Element scroll progress
import "./styles.css";
import { useRef } from "react";
import { motion, useScroll } from "framer-motion";
export default function App() {
const ref = useRef(null); // 스크롤을 감지할 요소에 적용
const { scrollXProgress } = useScroll({ container: ref });
return (
<>
<svg id="progress" width="100" height="100" viewBox="0 0 100 100">
<circle cx="50" cy="50" r="30" pathLength="1" className="bg" />
<motion.circle
cx="50"
cy="50"
r="30"
pathLength="1"
className="indicator"
style={{ pathLength: scrollXProgress }} // X스크롤의 진행률을 svg 요소에 적용
/>
</svg>
<ul ref={ref}> // ➡️ 스크롤바가 생기는 요소, X축으로 스크롤바 생김
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
</>
);
}
Parallax
export default function App() {
const { scrollYProgress } = useScroll();
const scaleX = useSpring(scrollYProgress, {
stiffness: 100,
damping: 30,
restDelta: 0.001
});
return (
<>
{[1, 2, 3, 4, 5].map((image) => (
<Image id={image} />
)}
<motion.div sytle={{ scaleX }}>
</>
)
}
Image Component
function Image ({ id }:{ id: number }) {
const ref = useRef(null);
const { scrollYProgress } = useScroll({ targe: ref });
const y = useParallax(scrollYProgress, 300)
return (
<section>
<div ref={ref}>
<img src={`/${id}.jpg`} alt='image' />
</div>
<motion.h2 style={{ y }}>{`#00${id}`}</motion.h2>
</section>
)
}
useParallax
function useParallax(value: MotionValue<number>, distance: number){
return useTransform(value, [0, 1], [-distance, distance]);
}
Scroll velocity
interface ParallaxProps {
children: string;
baseVelocity: number;
}
function ParallaxText({ children, baseVelocity = 100 } : ParallaxProps) {
const baseX = useMotionValue(0);
const { scrollY } = useScroll();
const scrollVelocity = useVelocity(scrollY); // 스크롤의 빠르기를 계산하여 저장
const smoothVelocity = useSpring(scrollVelocity, {
damping: 50,
stiffness: 400
});
const velocityFactor = useTransform(smoothVelocity, [0, 1000], [0, 5], {
clamp: false
});
const x = useTransform(baseX, (v) => `${wrap(-20, -45, v)}%`);
const directionFactor = useRef<number>();
useAnimationFrame((t, delta) => {
let moveBy = directionFactor.current * baseVelocity * (delta / 1000);
if(velocityFactor.get() < 0) {
directionFactor.current = -1;
} else if(velocityFactor.get() > 0) {
directionFactor.current = 1;
}
moveBy += directionFactor.current * moveBy * velocityfactor.get();
baseX.set(baseX.get()+ moveBy);
}
return (
<div className="parallax">
<motion.div className="scroller" style={{ x }}>
<span>{children} </span>
<span>{children} </span>
<span>{children} </span>
<span>{children} </span>
</motion.div>
</div>
);
}
scrollY
값의 변화 속도를 계산하여scrollVelocity
에 저장합니다. 이 값은 스크롤의 빠르기를 나타내며, 스크롤이 더 빨리 움직일수록 속도 값이 증가
Last updated