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

如何在MUI的CircularProgressBar中添加两种变体颜色并通过React自定义组件

自定义MUI环形进度条及重写组件实现方案

自定义MUI组件的环形进度条

一、为MUI CircularProgress添加双变体颜色实现

方案1:叠加双进度条实现双颜色效果

通过嵌套两个CircularProgress组件,分别配置不同的进度值和颜色,实现环形进度条的双颜色变体:

import { CircularProgress, Box } from '@mui/material';

const DualColorCircularProgress = ({ 
  progress1, 
  progress2, 
  color1 = 'primary', 
  color2 = 'secondary', 
  size = 80 
}) => {
  return (
    <Box position="relative">
      <CircularProgress
        size={size}
        variant="determinate"
        value={progress1}
        color={color1}
        sx={{ position: 'absolute' }}
      />
      <CircularProgress
        size={size}
        variant="determinate"
        value={progress2}
        color={color2}
        sx={{
          position: 'absolute',
          '& .MuiCircularProgress-circle': {
            strokeDashoffset: `calc(471.24 - (471.24 * ${progress2}) / 100)`,
            strokeDasharray: '471.24',
            strokeLinecap: 'round',
          },
        }}
      />
    </Box>
  );
};

// 使用示例
<DualColorCircularProgress progress1={60} progress2={30} color1="success" color2="warning" />

方案2:自定义样式变体

利用MUI的styled工具创建支持两种自定义颜色变体的进度条组件:

import { CircularProgress } from '@mui/material';
import { styled } from '@mui/material/styles';

const StyledCircularProgress = styled(CircularProgress)(({ theme, variant }) => ({
  '& .MuiCircularProgress-circle': {
    stroke: variant === 'custom-blue' 
      ? theme.palette.primary.main 
      : theme.palette.warning.main,
  },
}));

// 使用示例
<StyledCircularProgress variant="custom-blue" value={70} />
<StyledCircularProgress variant="custom-orange" value={50} />

二、React重写MUI组件的实现方案

方式1:基于MUI组件扩展(推荐)

继承MUI原有组件,通过样式覆盖和属性扩展实现自定义,保留MUI的主题适配能力:

import { Button as MuiButton } from '@mui/material';
import { styled } from '@mui/material/styles';

// 重写Button组件,添加自定义变体
const Button = styled(MuiButton)(({ theme, customVariant }) => ({
  ...(customVariant === 'outline-dashed' && {
    border: `2px dashed ${theme.palette.primary.main}`,
    backgroundColor: 'transparent',
    '&:hover': {
      backgroundColor: theme.palette.primary.light,
    },
  }),
}));

// 使用自定义组件
<Button customVariant="outline-dashed" variant="contained">自定义按钮</Button>

方式2:完全自定义组件结构

如果需要彻底脱离MUI组件的默认结构,直接用原生元素结合MUI主题hooks构建:

import { useTheme } from '@mui/material/styles';
import PropTypes from 'prop-types';

const CustomCircularProgress = ({ value, color = 'primary', size = 80 }) => {
  const theme = useTheme();
  const strokeWidth = 4;
  const radius = (size - strokeWidth) / 2;
  const circumference = 2 * Math.PI * radius;
  const strokeDashoffset = circumference - (value / 100) * circumference;

  return (
    <svg width={size} height={size}>
      {/* 背景环 */}
      <circle
        cx={size / 2}
        cy={size / 2}
        r={radius}
        fill="none"
        stroke={theme.palette.grey[300]}
        strokeWidth={strokeWidth}
      />
      {/* 进度环 */}
      <circle
        cx={size / 2}
        cy={size / 2}
        r={radius}
        fill="none"
        stroke={theme.palette[color].main}
        strokeWidth={strokeWidth}
        strokeDasharray={circumference}
        strokeDashoffset={strokeDashoffset}
        strokeLinecap="round"
        transform={`rotate(-90 ${size / 2} ${size / 2})`}
      />
    </svg>
  );
};

CustomCircularProgress.propTypes = {
  value: PropTypes.number.isRequired,
  color: PropTypes.string,
  size: PropTypes.number,
};

// 使用示例
<CustomCircularProgress value={75} color="secondary" size={100} />

方式3:扩展组件逻辑

在重写的基础上添加自定义交互或状态管理,比如进度条的加载控制:

import { useState } from 'react';
import CustomCircularProgress from './CustomCircularProgress';

const ProgressWithToggle = () => {
  const [isLoading, setIsLoading] = useState(true);
  const [progress, setProgress] = useState(0);

  // 模拟进度增长
  useState(() => {
    if (!isLoading) return;
    const timer = setInterval(() => {
      setProgress(prev => (prev >= 100 ? 0 : prev + 10));
    }, 500);
    return () => clearInterval(timer);
  }, [isLoading]);

  return (
    <div>
      <CustomCircularProgress value={progress} />
      <button onClick={() => setIsLoading(!isLoading)}>
        {isLoading ? '暂停' : '开始'}
      </button>
    </div>
  );
};

内容的提问来源于stack exchange,提问作者gopi mudumal

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 02:47:04