简体   繁体   English

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

[英]How can i switch between react components using framer motion?

In my react app i need to switch between components like in a carousel.在我的反应应用程序中,我需要在轮播中的组件之间切换。 I found this example to build an image carousel only using framer motion: https://codesandbox.io/s/framer-motion-image-gallery-pqvx3?file=/src/Example.tsx:1715-1725我发现此示例仅使用成帧器运动构建图像轮播: https://codesandbox.io/s/framer-motion-image-gallery-pqvx3?file=/src/Example.tsx:1715-1725

I want to adapt this to switching between components.我想调整它以适应组件之间的切换。 At the moment my page looks something like this:目前我的页面看起来像这样:

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>
 )
}

how would I have to build the logic to be able to switch dynamic between my components (slides)?我将如何构建逻辑才能在我的组件(幻灯片)之间动态切换? In the codesandbox example the images were changed via an array:在代码框示例中,图像是通过数组更改的:

const imageIndex = wrap(0, images.length, page);

<motion.img key={page} src={images[imageIndex]} />

How could i do that to switch between jsx elements?我怎么能这样做以在 jsx 元素之间切换?

Edit编辑

The answer from Joshua Wootonn is correct, but you need to add the custom prop also to the TestComp to get the animation working with dynamic variants like this: Joshua Wootonn 的答案是正确的,但是您还需要将custom道具添加到TestComp以使 animation 使用如下动态变体:

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,
    }}
  />
)

Your components should return <motion.div> (or <motion.section> , <motion.span> etc.).您的组件应返回<motion.div> (或<motion.section><motion.span>等)。 And in the page component you should use <AnimatePresence /> component (like in the example):在页面组件中,您应该使用<AnimatePresence />组件(如示例中所示):

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

Then you have to decide which component will appear:然后你必须决定哪个组件会出现:

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

The animations you can control with variants .您可以使用variants控制的动画。

You can see a quick demo here: https://codesandbox.io/s/quizzical-hypatia-7wqjc?file=/src/App.tsx您可以在此处查看快速演示: https://codesandbox.io/s/quizzical-hypatia-7wqjc?file=/src/App.tsx

A couple of things were missing from the above answer to get exit animations working.上述答案中缺少一些东西来使退出动画正常工作。

  1. If you want exit animations to work within AnimationPresense you need to set keys on its children如果您希望退出动画在 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. If you want to animate something in while something is still animating out without having massive content shifting, you need to take them out of the flow.如果您想在某些内容仍在制作动画的同时进行动画处理,而无需进行大量内容转换,则需要将它们从流程中移除。 (use absolute positioning and wrap with relatively positioned container) (使用绝对定位并用相对定位的容器包裹)
      <div style={{ position: "relative", height: "300px", width: "300px" }}>
        <AnimatePresence initial={false} custom={direction}>
          ...
        </AnimatePresence>
      </div>

and on the child components在子组件上

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

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM