如何使用成帧器运动在反应组件之间切换



在我的react应用程序中,我需要在组件之间切换,比如在旋转木马中。我发现这个例子只使用帧器运动来构建图像转盘:https://codesandbox.io/s/framer-motion-image-gallery-pqvx3?file=/src/Example.tsx:1715-1725

我想使其适应组件之间的切换。现在我的页面看起来像这样:

const variants = {
enter: (direction: number) => {
return {
x: direction > 0 ? 100 : -100,
opacity: 0,
}
},
center: {
zIndex: 1,
x: 0,
opacity: 1,
},
exit: (direction: number) => {
return {
zIndex: 0,
x: direction < 0 ? 100 : -100,
opacity: 0,
}
},
}
const Page = () => {
const [[page, direction], setPage] = useState([0, 0])
const paginate = (newDirection: number) => {
setPage([page + newDirection, newDirection])
}
return (
<motion.div
key={page}
custom={direction}
variants={variants}
initial="enter"
animate="center"
exit="exit"
>
<!-- my components, between which I want to switch, should appear here -->
</motion.div>
)
}

我必须如何构建逻辑才能在我的组件(幻灯片(之间动态切换?在codesandbox的例子中,图像是通过一个数组更改的:

const imageIndex = wrap(0, images.length, page);
<motion.img key={page} src={images[imageIndex]} />

我该如何在jsx元素之间切换?

编辑

Joshua Wootonn的答案是正确的,但你需要将custom道具也添加到TestComp中,以使动画与这样的动态变体一起工作:

const TestComp = ({ bg }: { bg: string }) => (
<motion.div
custom={direction}
variants={variants}
initial="enter"
animate="center"
exit="exit"
transition={{
x: { type: "spring", stiffness: 100, damping: 30 },
opacity: { duration: 0.2 },
}}
className="absolute w-full h-full"
style={{
background: bg,
}}
/>
)

上面的答案中缺少了一些东西来使退出动画正常工作。

  1. 如果希望退出动画在AnimationPresense中工作,则需要在其子项上设置关键帧
<AnimatePresence initial={false} custom={direction}>
{page === 0 && <TestComp key="0" bg="rgb(171, 135, 255)" />}
{page === 1 && <TestComp key="1" bg="rgb(68, 109, 246)" />}
{page === 2 && <TestComp key="2" bg="rgb(172, 236, 161)" />}
</AnimatePresence>
  1. 如果你想在某个东西仍在制作动画而没有大量内容转移的情况下制作动画,你需要将它们从流中删除。(使用绝对定位并用相对定位的容器包裹(
<div style={{ position: "relative", height: "300px", width: "300px" }}>
<AnimatePresence initial={false} custom={direction}>
...
</AnimatePresence>
</div>

以及子组件

height: 100%;
width: 100%;
position: absolute;

工作代码沙盒:https://codesandbox.io/s/framer-motion-carousel-animation-wetrf?file=/src/App.tsx:658-708

您的组件应该返回<motion.div>(或<motion.section><motion.span>等(。在页面组件中,您应该使用<AnimatePresence />组件(如示例中所示(:

<AnimatePresence initial={false} custom={direction}>
{COMPONENTS}
</AnimatePresence>

然后你必须决定哪个组件将出现:

{page === 0 && <ComponentOne />}
{page === 1 && <ComponentTwo/>}
{page === 2 && <ComponentThree/>}

可以使用variants控制的动画。

你可以在这里看到一个快速演示:https://codesandbox.io/s/quizzical-hypatia-7wqjc?file=/src/App.tsx

使用<AbsencePresence>,模式为wait,初始设置为假

<AnimatePresence mode="wait" initial={false}>
{itemKey === 0 && (
<motion.div
key="0"
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
/>
)}
{itemKey === 1 && (
<motion.div
key="1"
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
/>
)}
</AnimatePresence>