React中用GSAP实现翻书滚动动画遇.getContext错误求助
解决React中Canvas关联GSAP时的
.getContext is not a function错误 核心问题分析
- React的
useRef返回的是Ref对象,你直接操作canvasRef而非其current属性,而current才指向实际的Canvas DOM元素 - 在组件渲染阶段直接初始化Canvas,此时Canvas还未挂载到DOM树,
canvasRef.current为null,自然无法调用getContext - 代码中
currentFrame箭头函数存在语法错误,把=>写成了=
修复步骤
- 使用
useEffect钩子,在组件挂载后再操作Canvas DOM元素 - 所有操作Canvas的逻辑都要通过
canvasRef.current访问真实DOM节点 - 修正
currentFrame的语法错误 - 集成GSAP ScrollTrigger实现滚动控制帧动画的逻辑
修复后的完整代码
import { useRef, useEffect } from "react"; import gsap from "gsap"; import ScrollTrigger from "gsap/ScrollTrigger"; // 注册ScrollTrigger插件 gsap.registerPlugin(ScrollTrigger); function Landing() { const canvasRef = useRef(null); const frameCount = 230; const currentFrame = (index) => `../../assets/landing-animations/${(index + 1).toString()}.jpg`; useEffect(() => { // 确保Canvas DOM元素存在 const canvas = canvasRef.current; if (!canvas) return; // 初始化Canvas尺寸 canvas.width = window.innerWidth; canvas.height = window.innerHeight; const context = canvas.getContext("2d"); const images = []; let animationState = { frame: 0 }; // 预加载所有帧图片 for (let i = 0; i < frameCount; i++) { const img = new Image(); img.src = currentFrame(i); images.push(img); } // 渲染函数 function render() { context.clearRect(0, 0, canvas.width, canvas.height); context.drawImage(images[animationState.frame], 0, 0); } // 第一帧加载完成后初始化渲染 images[0].onload = () => { render(); // 用GSAP ScrollTrigger实现滚动控制动画 gsap.to(animationState, { frame: frameCount - 1, snap: "frame", ease: "none", scrollTrigger: { trigger: canvas, scrub: 0.5, // 滚动与动画的同步系数 start: "top top", end: "bottom bottom", // 可选:添加标记方便调试 // markers: true }, onUpdate: render // 每帧更新时调用渲染 }); }; // 窗口 resize 时重新设置Canvas尺寸 const handleResize = () => { canvas.width = window.innerWidth; canvas.height = window.innerHeight; render(); }; window.addEventListener("resize", handleResize); // 清理函数:移除监听和销毁ScrollTrigger return () => { window.removeEventListener("resize", handleResize); ScrollTrigger.getAll().forEach(trigger => trigger.kill()); }; }, []); return ( <div className="landing"> <h1 className="landing__header">Welcome to my portfolio</h1> <canvas className="landing__canvas" ref={canvasRef}></canvas> </div> ); } export default Landing;
额外说明
- 必须注册
ScrollTrigger插件才能使用其功能 - 添加了窗口resize监听,保证Canvas尺寸适配窗口变化
- 通过
onUpdate钩子绑定渲染函数,实现帧动画随滚动更新 - 清理函数中销毁ScrollTrigger和移除监听,避免内存泄漏
内容的提问来源于stack exchange,提问作者Omar
相关产品推荐
相关产品推荐

