I'm trying to make the following code play my rive animation in sync with the scroll, but it doesn't work. Can anyone help?
It just keeps playing automatically and the scroll isn't having any impact on the position of the animation.
import Rive from "@rive-app/react-canvas";
import { useRef, useEffect, useState } from "react";
const App = () => {
const riveRef = useRef(null);
const animationDuration = useRef(0);
const [isLoaded, setIsLoaded] = useState(false);
useEffect(() => {
const handleScroll = () => {
if (!riveRef.current || !riveRef.current.rive || !isLoaded) return;
const riveInstance = riveRef.current.rive;
const scrollProgress = window.scrollY / (document.body.scrollHeight - window.innerHeight);
if (animationDuration.current > 0) {
riveInstance.setTime(scrollProgress * animationDuration.current);
riveInstance.drawFrame(); // Ensures frame update
}
};
window.addEventListener("scroll", handleScroll);
return () => window.removeEventListener("scroll", handleScroll);
}, [isLoaded]);
return (
<div style={{ height: "300vh", overflow: "hidden" }}>
<div style={{ width: "100vw", height: "100vh", overflow: "hidden", position: "fixed" }}>
<Rive
ref={riveRef}
src="images/web-animationv3.riv"
stateMachines="State Machine 1"
onLoad={(riveInstance) => {
const animation = riveInstance.animations[0];
if (animation) {
animationDuration.current = animation.duration;
riveInstance.pause(); // Stop auto-play
setIsLoaded(true); // Ensure state is updated to enable scroll sync
}
}}
style={{ width: "100%", height: "100%" }}
/>
</div>
</div>
);
};
export default App;