问题描述
我有一个 Spinner 组件,它基本上是一个加载图标。我正在尝试将道具传递给 JSS 样式,以便可以对其进行自定义。但是如果我将道具传递给关键帧,动画似乎不起作用。
下面是组件。当我使用动画 $spinnertest
时它工作正常。如果我使用 $spinners
,它不会加载动画(在检查元素时,animation-name
甚至不会出现在类中,让我相信它不会生成。)。
**Example CodeSandBox of issue(只需将动画更改为spinners
):https://codesandbox.io/s/exciting-shirley-pqt1o?fontsize=14&hidenavigation=1&theme=dark
const useStyles = makeStyles(theme => ({
root: props => ({
width: props.size,height: props.size,position: 'relative',contain: 'paint',display: 'inline-block',}),spinner: props => ({
width: props.size*0.3125,height: props.size*0.3125,background: props.color,position: 'absolute',animationDuration: props.duration,animationIterationCount: 'infinite',animationTimingFunction: 'ease-in-out',spinnerAnimation: {
animationName: '$spinners',},square2: props => ({
animationDelay: -props.duration/2,'@keyframes spinnertest': {
'25%': {
transform: 'translateX(22px) rotate(-90deg) scale(.5)','50%': {
transform: 'translateX(22px) translateY(22px) rotate(-180deg)','75%': {
transform: 'translateX(0) translateY(22px) rotate(-270deg) scale(.5)','to': {
transform: 'rotate(-1turn)','@keyframes spinners': props => ({
'25%': {
transform: `translateX(${props.translate}px) rotate(-90deg) scale(.5)`,'50%': {
transform: `translateX(${props.translate}px) translateY(${props.translate}px) rotate(-180deg)`,'75%': {
transform: `translateX(0) translateY(${props.translate}px) rotate(-270deg) scale(.5)`,'to': {
transform: `rotate(-1turn)`,}));
export default function Spinner(props) {
const {duration,size,color} = props;
const classes = useStyles({
duration: duration,size: size,color: color,translate: size*(1-0.3125),});
return (
<Box className={classes.root}>
<Box className={clsx(classes.spinner,classes.spinnerAnimation)} />
<Box className={clsx(classes.spinner,classes.square2,classes.spinnerAnimation)} />
</Box>
)
}
Spinner.defaultProps = {
duration: 1800,size: 32,color: #fff,}
解决方法
我有一个周转的解决方案,它有效(不是那么漂亮)。您可以将 withStyles
转换为采用 keyframesProps
的柯里化函数,并且在您的关键帧定义处,您将使用返回对象及其属性的 IIFE:
const useStyles = keyframesProps => makeStyles((theme) => ({
... all other styles,// you need to call an IIFE because keyframes doesn't receive a function
"@keyframes spinners": ((props) => ({
"25%": {
transform: `translateX(${props.translate}px) rotate(-90deg) scale(.5)`
},"50%": {
transform: `translateX(${props.translate}px) translateY(${props.translate}px) rotate(-180deg)`
},"75%": {
transform: `translateX(0) translateY(${props.translate}px) rotate(-270deg) scale(.5)`
},to: {
transform: `rotate(-1turn)`
}
}))(keyframesProps)
}));
在您的组件中,您可以像这样定义 classes
:
const styleProps = {
duration: duration,size: size,color: color
}
const framesProps = {
translate: size * (1 - 0.3125)
}
const classes = useStyles(framesProps)(styleProps);
,
听起来 MUI 在 makeStyles @keyframes
中的 props 有一个错误
#16673
正如 Olivier Tassinari 所说,此错误将在 v5 中修复,其中 MUI 将使用新的样式解决方案 styled-components
RCF #22342。
这个问题更加普遍:
箭头函数(有或没有道具)在 makeStyles 中不起作用
#21011
将道具传递给定义的关键帧中的规则将修复它(希望在 v5 可用后)
"@keyframes spinners": {
"25%": {
transform: (props) =>
// console.log(props) and template generation will be created correctly.
`translateX(${props.translate}px) rotate(-90deg) scale(.5)`
},// ...
}
在此之前,您可以使用更高阶的 useStyle creator 来嵌入您的关键帧,如@buzatto 所建议的那样。
或者在您的主题对象中定义您的动画预设,并在您的项目中全局使用它们。
const theme = createMuiTheme({
animation: {
presets: {
duration: 180,// or even function
rotateDeg: (angle) => `{angle}deg`
//...
}
}
});
// usage
const useStyles = makeStyles(theme => ({
"@keyframes spinners": {
"25%": {
transform: `translateX(${
theme.animation.presets.duration * 10
}px) rotate(${theme.animation.presets.rotateDeg(-90)}) scale(.5)`,},}