如何在 MUI 中应用自定义动画效果@keyframes?

Posted

技术标签:

【中文标题】如何在 MUI 中应用自定义动画效果@keyframes?【英文标题】:How to apply custom animation effect @keyframes in MUI? 【发布时间】:2020-03-15 20:22:27 【问题描述】:

我学会了使用@keyframe 在 CSS 中使用动画。但是,我想将自定义动画代码写入我的 React 项目(使用 MUI)。我的挑战是如何编写 javascript 代码来使用 MUI 中的 makeStyle() 自定义我的动画。

我希望能够以百分比自定义转换过程 这次是在 MUI。我需要能够在makeStyle() 中编写这样的代码,但我似乎不知道该怎么做。

@keyframes myEffect 
 0%
  opacity:0;
  transform: translateY(-200%); 
 

100% 
  opacity:1;
  transform: translateY(0);
 

【问题讨论】:

【参考方案1】:

这是一个示例,演示 makeStyles 中的 keyframes 语法:

import React from "react";
import ReactDOM from "react-dom";

import  makeStyles  from "@material-ui/core/styles";
import Button from "@material-ui/core/Button";
import clsx from "clsx";

const useStyles = makeStyles(theme => (
  animatedItem: 
    animation: `$myEffect 3000ms $theme.transitions.easing.easeInOut`
  ,
  animatedItemExiting: 
    animation: `$myEffectExit 3000ms $theme.transitions.easing.easeInOut`,
    opacity: 0,
    transform: "translateY(-200%)"
  ,
  "@keyframes myEffect": 
    "0%": 
      opacity: 0,
      transform: "translateY(-200%)"
    ,
    "100%": 
      opacity: 1,
      transform: "translateY(0)"
    
  ,
  "@keyframes myEffectExit": 
    "0%": 
      opacity: 1,
      transform: "translateY(0)"
    ,
    "100%": 
      opacity: 0,
      transform: "translateY(-200%)"
    
  
));

function App() 
  const classes = useStyles();
  const [exit, setExit] = React.useState(false);
  return (
    <>
      <div
        className=clsx(classes.animatedItem, 
          [classes.animatedItemExiting]: exit
        )
      >
        <h1>Hello CodeSandbox</h1>
        <h2>Start editing to see some magic happen!</h2>
        <Button onClick=() => setExit(true)>Click to exit</Button>
      </div>
      exit && <Button onClick=() => setExit(false)>Click to enter</Button>
    </>
  );


const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

文档:https://cssinjs.org/jss-syntax/?v=v10.0.0#keyframes-animation


对于那些已经开始使用 Material-UI v5 并想知道如何使用 Emotion 而不是 makeStyles 的人,下面是使用 Emotion 进行等效样式的一种方法示例。

/** @jsxImportSource @emotion/react */
import React from "react";
import ReactDOM from "react-dom";

import  css, keyframes  from "@emotion/react";
import  useTheme  from "@mui/material/styles";
import Button from "@mui/material/Button";

const myEffect = keyframes`
  0% 
    opacity: 0;
    transform: translateY(-200%);
  
  100% 
    opacity: 1;
    transform: translateY(0);
  
`;
const myEffectExit = keyframes`
  0% 
    opacity: 1;
    transform: translateY(0);
  
  100% 
    opacity: 0;
    transform: translateY(-200%);
  
`;

function App() 
  const theme = useTheme();
  const animatedItem = css`
    animation: $myEffect 3000ms $theme.transitions.easing.easeInOut;
  `;
  const animatedItemExiting = css`
    animation: $myEffectExit 3000ms $theme.transitions.easing.easeInOut;
    opacity: 0;
    transform: translateY(-200%);
  `;
  const [exit, setExit] = React.useState(false);
  return (
    <>
      <div css=exit ? animatedItemExiting : animatedItem>
        <h1>Hello CodeSandbox</h1>
        <h2>Start editing to see some magic happen!</h2>
        <Button onClick=() => setExit(true)>Click to exit</Button>
      </div>
      exit && <Button onClick=() => setExit(false)>Click to enter</Button>
    </>
  );


const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

情感关键帧文档:https://emotion.sh/docs/keyframes

【讨论】:

【参考方案2】:

V5

在 v5 中,您可以使用 keyframes 函数(默认是 emotion 中的 re-exported)来生成关键帧的样式表:

import  styled  from '@mui/material/styles';
import  keyframes  from '@mui/system';

const spin = keyframes`
  from 
    transform: rotate(0deg);
  
  to 
    transform: rotate(360deg);
  
`;

const RotatedBox = styled("div")(
  backgroundColor: "pink",
  width: 30,
  height: 30,
  animation: `$spin 1s infinite ease`
);

因为styled/sx 属性在内部都使用了情感,所以可以将相同的样式对象传递给sx 属性:

<Box
  sx=
    backgroundColor: "pink",
    width: 30,
    height: 30,
    animation: `$spin 1s infinite ease`
  
/>

V4

只是在@Ryan's answer 之上的一些注释。如果您使用makeStyles 定义keyframe。请记住在动画名称前加上$。我第一次错过了这个小细节,我的代码不起作用,在下面的示例中

const useStyles = makeStyles(
  "@keyframes fadeIn": 
    "0%": 
      opacity: 0,
      transform: "translateY(5rem)"
    ,
    "100%": 
      opacity: 1,
      transform: "translateY(0)"
    
  ,
  selector: 
    animation: "$fadeIn .2s ease-in-out"
  
);

代替

animation: "fadeIn .2s ease-in-out"

应该是

animation: "$fadeIn .2s ease-in-out"

但是如果你在全局范围内定义keyframe。这里不需要前缀

const useStyles = makeStyles(
  "@global": 
    "@keyframes fadeIn": 
      "0%": 
        opacity: 0,
        transform: "translateY(5rem)"
      ,
      "100%": 
        opacity: 1,
        transform: "translateY(0)"
      
    
  ,
  selector: 
    animation: "fadeIn .2s ease-in-out" // --> this works
  
);

在 github 上关注 issue 以获取更多关于此的讨论。

【讨论】:

以上是关于如何在 MUI 中应用自定义动画效果@keyframes?的主要内容,如果未能解决你的问题,请参考以下文章

html5如何让图片3d旋转?

mui aniShow 动画属性

Flutter CustomScrollView 自定义滑动效果

如何在 Blend 中自定义动画?

mui拍照后如何保存到自定义目录中?mui代码如何建文件夹?

MUI框架-03-自定义MUI控件样式