You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 11:45:03