コンポーネントの出現を滑らかにする
motion.divコンポーネントを使用する。
-
initial
propでアニメーションの初期状態を設定(透明から出現させたい時はopacity:0
を設定)。 -
animate
propでアニメーションの最終状態(出現する直前の状態)を設定。
コンポーネントの消滅を滑らかにする
motion.divコンポーネントをAnimatePresenceコンポーネントでラッピングする。
- 上記に加え、motion.divコンポーネントの
exit
propで、アニメーションの最終状態(消える直前の状態)を定義。
なお、AnimationPresenceコンポーネントのinitial
propをfalseに設定すると、最初のレンダリング時にはコンポーネントの出現時にアニメーションが効かなくなる。
その他
variantsをhashとして定義し、これをmotion.divコンポーネントのvariants propsに突っ込むことで、initial
, animate
, exit
propをこのhashのキーとして設定すると、hashのvalueがそれぞれのpropとして解釈される。
const variants: Variants = {
initial: {
opacity: 0,
},
animate: {
opacity: 1,
transition={duration: 2}
},
exit: {
opacity: 0,
transition={duration: 2}
}
};
<AnimatePresence>
{isVisible && (
<motion.div
variants={variants}
initial="initial"
animate="animate"
exit="exit"
>
<MyComponent/> // このcomponentの入出現時にアニメーションがかかる
</motion.div>
)}
</AnimatePresence>
おまけのサンプルコード
職場の先輩にかいてもらったやつ。
import { useState } from "react";
import { AnimatePresence, motion, Variants } from "framer-motion";
import "./styles.css";
const variants: Variants = {
initial: {
opacity: 0,
y: -16
},
animate: {
opacity: 1,
y: 0
},
exit: {
opacity: 0,
y: -16
}
};
export default function App() {
const [isVisible1, setIsVisible1] = useState(false);
const [isVisible2, setIsVisible2] = useState(false);
return (
<div className="App">
<div>
<button type="button" onClick={() => setIsVisible1((v) => !v)}>
Toggle
</button>
<AnimatePresence>
{isVisible1 && (
<motion.div
variants={variants}
initial="initial"
animate="animate"
exit="exit"
style={{
display: "block",
padding: "8px",
backgroundColor: "rgba(0, 0, 0, 0.06)",
borderRadius: "4px"
}}
>
initial="initial"
</motion.div>
)}
</AnimatePresence>
</div>
<div style={{ marginTop: "32px" }}>
<button type="button" onClick={() => setIsVisible2((v) => !v)}>
Toggle
</button>
<AnimatePresence>
{isVisible2 && (
<motion.div
variants={variants}
initial={false}
animate="animate"
exit="exit"
style={{
display: "block",
padding: "8px",
marginTop: "32px",
backgroundColor: "rgba(0, 0, 0, 0.06)",
borderRadius: "4px"
}}
>
initial=false
</motion.div>
)}
</AnimatePresence>
</div>
</div>
);
}