javascript 每次元素进入视图时从头开始重复动画

k3bvogb1  于 2023-08-02  发布在  Java
关注(0)|答案(2)|浏览(111)

我创建了一个动画,需要几秒钟的时间播放。动画应该只在元素在视图中时运行,所以我使用了whileInView。这是正确的,但是当我向下滚动时(因此元素不在视图中),动画似乎向后运行,因为当我再次向上滚动时,我可以看到动画不是从开始开始,而是从它向后运行时到达的点开始,当元素再次进入视图时。我希望动画从头开始运行。
我创建了一个小沙箱来演示这个问题:
https://codesandbox.io/s/dreamy-cache-mk2dq2?file=/src/App.js

import "./styles.css";
import { motion } from "framer-motion";

export default function App() {
  return (
    <div style={{ height: "1000px" }}>
      <motion.div
        id="box"
        initial={{ x: 0 }}
        whileInView={{ x: 300 }}
        transition={{ duration: 5, ease: "linear" }}
      >
        <p>
          The box should be moving now. Scroll down and then up again. The
          animation will not instantly reset but run backwards.
        </p>
      </motion.div>
    </div>
  );
}

字符串
当你打开沙盒时,蓝色的盒子会移动。动画需要5秒。向下滚动,然后再向上滚动(在5秒内)。动画将从某个点开始运行,而不是从开始运行。
如何使动画在元素进入视图时从头开始运行?

fgw7neuy

fgw7neuy1#

  • 我使用useInView来跟踪div何时滚动过去,并在发生变化时调用useEffectuseInView reference
  • 当它在视图中时,它运行你的动画&当视图外时,它会做一个快速的反向动画(也许这第二部分可以做得更好,但它工作)。
  • 我还使用了useAnimate而不是div定义see more about useAnimate here
  • 我在你的codesandbox上编辑了App.js,但没有帐户来保存和共享链接。如果你将下面的代码粘贴到你的沙盒的App.js中,它应该会给予你你想要的。
import "./styles.css";
import { motion, useInView, useAnimate  } from "framer-motion";
import { useEffect, useRef } from "react";

export default function App() {
  const [scope, animate] = useAnimate()
  const motionDiv = useRef(null)
  const isInView = useInView(motionDiv)

  useEffect(()=>{
    if(isInView){
      animate("div", { x: 300 }, { duration:5, ease: "linear" })
    }else{
      animate("div", { x: 0 }, { duration:0 })
    }
  },[isInView, animate])

  return (
    <div ref={scope}  style={{ height: "1000px" }} >
    <div ref={motionDiv}>
      <motion.div
        id="box"
      >
        <p>
          The box should be moving now. Scroll down and then up again. The
          animation will not instantly reset but run backwards.
        </p>
      </motion.div>
    </div>
    </div>
  );
}

字符串

wtlkbnrh

wtlkbnrh2#

p7dxb的回答给了我一个想法。我找到了一个非常简单的解决办法。您只需为initialwhileInView设置不同的过渡值。对initial使用0秒的持续时间:

import "./styles.css";
import { motion } from "framer-motion";

export default function App() {
  return (
    <div style={{ height: "1000px" }}>
      <motion.div
        id="box"
        initial={{ x: 0, transition: { duration: 0 } }}
        whileInView={{ x: 300, transition: { duration: 5, ease: "linear" } }}
      >
        <p>
          The box should be moving now. Scroll down and then up again. The
          animation will not instantly reset but run backwards.
        </p>
      </motion.div>
    </div>
  );
}

字符串
下面是新的沙盒:https://codesandbox.io/s/objective-elgamal-p49wdq

相关问题