here's what I got but it doesn't work (
@Rodrigo
import React from 'react';
import { gsap } from 'gsap';
import ScrollTrigger from 'gsap/dist/ScrollTrigger';
if (typeof window !== 'undefined') {
gsap.registerPlugin(ScrollTrigger);
}
function getCurrentFrame(index) {
return `assets/frames/process_0${index.toString().padStart(4, '0')}.jpg`;
}
export const CanvasScroll = ({ scrollHeight, numFrames, width, height, svgRef }) => {
const canvasRef = React.useRef(null);
const [images, setImages] = React.useState([]);
const [frameIndex, setFrameIndex] = React.useState(0);
function preloadImages() {
for (let i = 1; i <= numFrames; i++) {
const img = new Image(100, 100);
const imgSrc = getCurrentFrame(i);
img.src = imgSrc;
setImages((prevImages) => [...prevImages, img]);
}
}
const handleScroll = () => {
const scrollFraction = window.scrollY / (scrollHeight - window.innerHeight);
const index = Math.min(numFrames - 1, Math.ceil(scrollFraction * numFrames));
if (index <= 0 || index > numFrames) {
return;
}
setFrameIndex(index);
};
const renderCanvas = () => {
const context = canvasRef.current.getContext('2d');
context.canvas.width = width;
context.canvas.height = height;
};
React.useEffect(() => {
preloadImages();
renderCanvas();
window.addEventListener('scroll', handleScroll);
return () => window.removeEventListener('scroll', handleScroll);
}, []);
React.useEffect(() => {
if (!canvasRef.current || images.length < 1) {
return;
}
const context = canvasRef.current.getContext('2d');
let requestId;
const render = () => {
context.drawImage(images[frameIndex], 0, 0);
requestId = requestAnimationFrame(render);
};
render();
return () => cancelAnimationFrame(requestId);
}, [frameIndex, images]);
React.useEffect(() => {
const t = gsap.to('.canvas', {
scrollTrigger: {
trigger: svgRef.current,
start: 'top top',
end: '+=' + numFrames * scrollHeight,
},
});
return () => {
t.kill();
ScrollTrigger.getAll().forEach((e) => e.kill());
};
}, []);
return (
<div className="canvas">
<canvas ref={canvasRef} />
</div>
);
};