You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为Framer Motion的useAnimate钩子设置初始值

问题:useAnimate结合useInView时如何设置初始值避免元素跳变?

当使用motion组件的initial属性时,我们可以直接定义元素的初始动画状态:

<motion.div
  initial={{ x: "100%" }}
  animate={{ x: "calc(100vw - 50%)" }}
/>

但在结合useAnimate与useInView钩子实现滚动触发动画时,如下代码会导致元素在动画开始前从0跳至100的初始位置:

const [scope, animate] = useAnimate();
const isInView = useInView(scope, { once: true, amount: 0.8 });

useEffect(() => {
  if (isInView) {
    animate('.anim-up', { y: [100, 0] }, { duration: 1, delay: stagger(0.15) })
  }
}, [isInView]);

请问该如何正确设置初始值?


解决方法

1. 预先通过CSS设置初始状态

给目标元素添加初始的transform样式,让元素默认处于动画起始位置,避免跳变:

.anim-up {
  transform: translateY(100px);
}

或者直接使用内联样式:

<div className="anim-up" style={{ transform: "translateY(100px)" }}>
  {/* 元素内容 */}
</div>

2. 用useAnimate设置瞬时初始状态

在组件挂载时,通过useAnimate将元素设置到初始位置,设置duration: 0让状态瞬间生效:

const [scope, animate] = useAnimate();
const isInView = useInView(scope, { once: true, amount: 0.8 });

// 挂载时设置初始位置
useEffect(() => {
  animate('.anim-up', { y: 100 }, { duration: 0 });
}, []);

// 进入视口后执行动画
useEffect(() => {
  if (isInView) {
    animate('.anim-up', { y: 0 }, { duration: 1, delay: stagger(0.15) });
  }
}, [isInView]);

3. 结合motion组件的initial属性(推荐方案)

如果目标元素是motion组件,直接用initial属性定义初始状态,再通过useAnimate触发动画:

import { motion, useAnimate, useInView } from "framer-motion";
import { stagger } from "framer-motion/dom";

const YourComponent = () => {
  const [scope, animate] = useAnimate();
  const isInView = useInView(scope, { once: true, amount: 0.8 });

  useEffect(() => {
    if (isInView) {
      animate('.anim-up', { y: 0 }, { duration: 1, delay: stagger(0.15) });
    }
  }, [isInView]);

  return (
    <div ref={scope}>
      <motion.div className="anim-up" initial={{ y: 100 }}>
        {/* 元素内容 */}
      </motion.div>
      {/* 其他需要动画的元素 */}
    </div>
  );
};

内容的提问来源于stack exchange,提问作者leon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 17:12:41