React项目中onMouseLeave事件调用gsap.reverse()不生效问题咨询
React中GSAP hover动画reverse无效问题解决
问题根因
你当前的代码每次调用hoverScaleAnimation函数都会创建一个全新的GSAP动画实例,onLeave事件中调用reverse()的是新生成的实例,并非onEnter时已经开始播放的那个动画,因此反向播放没有效果。同时多次调用gsap.to会给同一元素叠加多段动画,也可能导致状态冲突。
解决方案
你需要复用同一个动画实例,不要每次事件触发都重新创建动画,用useRef存储初始化好的动画实例即可,实现步骤如下:
- 声明两个ref,分别存储目标DOM元素、GSAP动画实例
- 组件挂载时仅初始化一次动画,设置
paused: true默认暂停 - 鼠标进出事件直接操作已有的动画实例,调用
play()/reverse()
代码示例
import { useRef, useLayoutEffect } from 'react' import gsap from 'gsap' const YourComponent = () => { // 存储目标DOM元素 const itemRef = useRef<HTMLDivElement>(null) // 存储唯一的GSAP动画实例 const hoverAnimRef = useRef<gsap.core.Tween | null>(null) // 组件挂载时初始化动画,仅执行一次 useLayoutEffect(() => { if (!itemRef.current) return hoverAnimRef.current = gsap.to(itemRef.current, { scale: 1.05, paused: true // 初始化后默认暂停,等待事件触发播放 }) }, []) const onEnter = () => { hoverAnimRef.current?.play() } const onLeave = () => { hoverAnimRef.current?.reverse() } return <div ref={itemRef} onMouseEnter={onEnter} onMouseLeave={onLeave}>hover 测试元素</div> }
可选:封装为公共Hook
如果需要多个组件复用这个hover缩放逻辑,可以封装为自定义Hook:
const useHoverScaleAnim = <T extends HTMLElement>() => { const targetRef = useRef<T>(null) const animRef = useRef<gsap.core.Tween | null>(null) useLayoutEffect(() => { if (!targetRef.current) return animRef.current = gsap.to(targetRef.current, { scale: 1.05, paused: true }) }, []) const handlers = { onMouseEnter: () => animRef.current?.play(), onMouseLeave: () => animRef.current?.reverse() } return [targetRef, handlers] as const } // 组件内使用 const Item = () => { const [itemRef, hoverHandlers] = useHoverScaleAnim<HTMLDivElement>() return <div ref={itemRef} {...hoverHandlers}>item内容</div> }
注意事项
如果是循环渲染的多个需要hover动画的元素,需要给每个元素单独声明对应的DOM ref和动画实例ref,不要共用同一个ref,避免多个元素动画互相干扰。
内容的提问来源于stack exchange,提问作者crevulus
相关产品推荐
相关产品推荐

