如何在MUI v5中实现自定义SVG Spinner组件的旋转动画效果
问题核心原因
你自定义的Spinner组件没有接收并透传styled-components生成的className属性,导致动画样式无法挂载到实际的SVG DOM元素上。而next/image的Image组件内部默认会处理外部传入的className,所以动画可以正常生效。
方案1:修改Spinner组件透传属性(推荐)
步骤1:用React.forwardRef包裹组件,透传className和ref
把你的Spinner组件改成如下写法,确保外部传入的样式类、ref都能正确传递到内部的svg标签:
import { forwardRef } from 'react'; export const Spinner = forwardRef(({ color, size, className }, ref) => ( <svg ref={ref} className={className} version="1.0" width={size} height={size} viewBox="0 0 150.000000 150.000000" preserveAspectRatio="xMidYMid meet" > <g transform="translate(0.000000,150.000000) scale(0.100000,-0.100000)" fill={color} stroke="none" > <path d="M520 1476 c-240 -84 -422 -277 -492 -522 -29 -102 -31 -276 -4 -374 58 -214 197 -384 390 -479 80 -40 187 -71 236 -70 14 0 -2 6 -35 14 -328 71 -556 354 -556 688 0 122 16 191 73 307 33 68 58 102 127 171 73 73 101 93 181 132 52 25 111 48 130 52 72 14 100 53 64 89 -20 21 -35 20 -114 -8z"/> <path d="M708 23 c12 -2 32 -2 45 0 12 2 2 4 -23 4 -25 0 -35 -2 -22 -4z" /> </g> </svg> ));
步骤2:优化动画样式定义
为了避免keyframes命名冲突,推荐用styled.keyframes定义动画,同时补充transform-origin确保旋转中心正确:
import styled, { keyframes } from 'styled-components'; const loaderSpin = keyframes` from { transform: rotate(0deg); } to { transform: rotate(360deg); } `; export const StyledSpinner = styled(Spinner)(({ theme }) => ({ animation: `${loaderSpin} infinite 700ms linear`, transformOrigin: 'center', transformBox: 'fill-box', }));
方案2:不改原Spinner组件,外层套容器加动画
如果你不想修改原Spinner组件的代码,可以在外层包裹一个块级元素,给外层元素加旋转动画:
import styled, { keyframes } from 'styled-components'; const loaderSpin = keyframes` from { transform: rotate(0deg); } to { transform: rotate(360deg); } `; const SpinContainer = styled.div` animation: ${loaderSpin} infinite 700ms linear; transform-origin: center; width: fit-content; height: fit-content; `; // 使用的时候套一层即可 <SpinContainer> <Spinner color={theme.palette.secondary.main} size={300} /> </SpinContainer>
两种方案都可以正常实现旋转动画效果,方案1无额外DOM节点,性能更优。
内容的提问来源于stack exchange,提问作者Edward Lee
相关产品推荐
相关产品推荐

