requestAnimationFrame导致自定义光标CSS过渡卡顿问题求助
解决React中requestAnimationFrame导致自定义光标过渡卡顿的问题
核心解决方案
- 用
useRef替代useState存储光标坐标:避免鼠标移动时频繁触发组件重渲染,减少主线程负载 - 将光标位置更新纳入
requestAnimationFrame调度:让光标动画与滚动动画同帧执行,避免帧冲突 - 优化光标CSS的合成层策略:确保光标在独立合成层渲染,减少重绘重排
修改后的代码
React组件代码
function App() { // 用useRef存光标位置,避免触发重渲染 const cursorRef = useRef({ x: 0, y: 0 }); const cursorElRef = useRef(null); const [mouseIn, setMouseIn] = useState(true); const scrollWrapRef = useRef(null); const contentRef = useRef(null); let offset = 0; let currentPos = 0; useEffect(() => { const mouse = (e) => { // 直接更新ref值,不触发重渲染 cursorRef.current.x = e.clientX; cursorRef.current.y = e.clientY; }; window.addEventListener("mousemove", mouse); const scrollWrap = scrollWrapRef.current; const content = contentRef.current; const cursorEl = cursorElRef.current; const updateAnimations = () => { // 滚动平滑动画 offset += (window.pageYOffset - offset) * 0.04; scrollWrap.style.transform = `translateY(-${offset}px) translateZ(0)`; // 内容扭曲动画 const newPos = window.pageYOffset; const diff = newPos - currentPos; const speed = diff * 0.6; content.style.transform = `skewY(${speed}deg)`; currentPos = newPos; // 光标位置更新,和其他动画同帧执行 cursorEl.style.left = `${cursorRef.current.x}px`; cursorEl.style.top = `${cursorRef.current.y}px`; requestAnimationFrame(updateAnimations); }; updateAnimations(); return () => { window.removeEventListener("mousemove", mouse); }; }, []); return ( <div className="App "> {/* custom cursor */} <div ref={cursorElRef} className="cursor" ></div> <div ref={scrollWrapRef}> <div ref={contentRef} className="section"> <Intro /> <About /> <Projects /> <Work /> <Contact /> </div> </div> </div> ); }
优化后的CSS代码
/* custom cursor */ .cursor { width: 20px; height: 20px; background: rgb(255, 255, 255); position: fixed; border-radius: 50%; mix-blend-mode: difference; pointer-events: none; z-index: 100; transform: translate(-50%, -50%); transition: 0.15s linear, transform 0.8s ease-in-out; /* 强制光标进入合成层,避免重绘 */ will-change: left, top; backface-visibility: hidden; } /* Scroll animation */ .section { position: relative; transform-style: preserve-3d; transform-origin: 0% 0%; transition: transform 0.25s; will-change: transform; }
问题根源分析
- 原代码中
useState触发频繁重渲染:每次鼠标移动调用setCursorX/setCursorY都会触发App组件重渲染,加上两个独立的requestAnimationFrame循环不断修改DOM样式,导致主线程过载,CSS过渡动画被打断。 - 动画调度不同步:光标过渡是CSS自动调度,而滚动动画是JS的RAF调度,两者帧时序不一致,导致视觉上的卡顿。
- 合成层未优化:光标默认可能不在独立合成层,每次位置更新都会触发页面重绘,加重性能负担。
内容的提问来源于stack exchange,提问作者ram
相关产品推荐
相关产品推荐

