Framer Motion 的幻灯片效果

Slideshow effect with Framer Motion

当我的组件中的某些道具在成帧器运动中发生变化时,我想将 属性 淡出,然后淡入“新”属性 值?

这是我想象中的动画时间线:

但我看到用 framer 做到这一点的唯一方法是使用超时。除了使用超时还有其他方法可以达到这种效果吗?

Codesandbox

import { motion } from "framer-motion";
import { useEffect, useState } from "react";
import "./styles.css";

export default function App() {
  const [seconds, setSeconds] = useState(0);
  const [anim, setAnim] = useState("in");
  useEffect(() => {
    const interval = setInterval(() => {
      setSeconds((seconds) => seconds + 1);
      setAnim("in");
      setTimeout(() => {
        setAnim("out");
      }, 500);
    }, 1000);
    return () => clearInterval(interval);
  }, []);

  const variants = {
    out: {
      opacity: 0
    },
    in: {
      opacity: 1,
      transition: {
        duration: 0.5
      }
    }
  };

  return (
    <motion.div
      animate={anim}
      variants={variants}
      className="App"
      style={{ fontSize: 100 }}
    >
      {seconds}
    </motion.div>
  );
}

您可以使用 AnimatePresence 来做到这一点。

AnimatePresence 标签包裹 motion.div,并使用 seconds 作为 div 的唯一键。每次更改时,更改键都会触发 AnimatePresence 使 div 进出动画(因为新键意味着它是一个不同的元素)。

要使其正常工作,您需要在 initialanimateexit 道具上定义动画。

您还需要确保在 AnimatePresence 上设置 exitBeforeEnter 属性,以便淡出动画在淡入开始之前完成。

Sandbox Example

export default function App() {
  const [seconds, setSeconds] = useState(0);

  useEffect(() => {
    const interval = setInterval(() => {
      setSeconds((seconds) => seconds + 1);
    }, 1000);
    return () => clearInterval(interval);
  }, []);


  return (
    <AnimatePresence exitBeforeEnter>
      <motion.div
        initial={{opacity:0}}
        animate = {{opacity: 1, transition:{duration: 0.5}}}
        exit={{opacity: 0 }}
        
        className="App"
        style={{ fontSize: 100 }}
        key={seconds}
      >
        {seconds}
      </motion.div>
    </AnimatePresence>
  );
}