如何在React中使用Framer Motion和Material-UI?(@material-ui/core)

13

我想知道是否有一种方法可以将framer-motionMaterial-Ui一起使用。 我尝试过但没有成功。

5个回答

57

Material-UI具有component属性选项,可满足此类要求,且比包裹方法更优雅。然后,只要不冲突(我不确定是否有),您可以将framer-motion软件包提供的任何道具传递给您的Material-UI组件。

 <Button
  color="inherit"
  variant='contained'
  size="large"
  component={motion.div}
  whileHover={{
    scale: 1.2,
    transition: { duration: 0.3 }
  }}
  whileTap={{ scale: 0.9 }}
>
  Button
</Button>

5

你的问题让我很好奇。我从未尝试过framer-motion,但最近正计划学习它。

所以我尝试了一下,在一个沙盒中创建了一个按钮,使用Material UI和framer motion包添加到其中。

只是使用Material UI在页面中央创建了一个小按钮。并将按钮用标签包装起来,如下所示:

import React from "react";
import { motion } from "framer-motion";
import Button from "@material-ui/core/Button";

function AnimatableDiv() {
  return (
    <motion.div
      className="animatable"
      whileHover={{
        scale: 1.2,
        transition: { duration: 0.3 }
      }}
      whileTap={{ scale: 0.9 }}
    >
      <Button size="large" className="animatable">
        Button
      </Button>
    </motion.div>
  );
}

export default AnimatableDiv;

它起作用了!

你可能会想,如果我直接在<Button>组件上使用 motion.会怎样,像这样:

<motion.Button size="large" className="animatable">
  Button
</motion.Button>

我曾经考虑过这种方法,并且也尝试了一下,但是所有Material UI应用到该按钮上的样式都丢失了!所以不要使用这种方法!我再次强调不要!

这是链接,你可以看一看: https://codesandbox.io/s/brave-sutherland-5bki9


谢谢!我认为包装是唯一的选择。 - Satyam

4

3

被接受的答案的策略是实现这一点最简单的方法,但另一种策略是使用 framer-motion 的包装。

以下是我的 TypeScript 实现,供那些可能搜索此问题的人参考。

Box.tsx

import React from "react";
import { motion } from "framer-motion";

import MuiBox, { BoxProps } from "@mui/material/Box";

const BoxComponent = React.forwardRef((props: BoxProps, ref) => (
  <MuiBox {...props} ref={ref} />
));

const Box = motion(BoxComponent);

export default Box;

然后在你的组件中使用它。
import Box from "./Box";

// The motion-wrapped Mui Box now also accepts framer-motion's props
<Box
  initial={{ opacity: 0 }}
  animate={{ x: 100, rotate: [null, 10, 20], opacity: 1 }}
  whileHover={{ scale: [null, 1.5, 1.4] }}
  width={100}
  height={100}
  border="1px solid red"
/>

这在Nextjs中效果最佳,因为component={motion.div}会在Nextjs中引发水合错误。 - Ilir
这似乎是最佳方法,也是framer-motion文档(https://www.framer.com/motion/component/#custom-components)目前推荐的方法。 我的经验是近两年前的,可能已经过时了(或者只适用于快速修复或基本要求),因为这个生态系统中的事情经常在变化。 - Ramazan Çağrı AKAR

0

我也有同样的问题,所以我在运动文档中进行了一些挖掘,发现了这个: 通过用 motion() 函数包装任何组件,可以将其转换为运动组件。 于是我就这样做了:

    import { TextField } from "@mui/material";
    import { motion } from "framer-motion";

    export default function YourComponent() {
    const TextFieldMotion = motion(TextField);
    return (
            <TextFieldMotion 
            animate={{ x: [0,20] }} 
            transition = {{ ease: "easeInOut", duration: 3 }} 
            variant="filled" 
            label="first name" 
            />
    )
     };

更多信息请参考:https://www.framer.com/docs/component/


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接