如何在MUI的CircularProgressBar中添加两种变体颜色并通过React自定义组件
自定义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
相关产品推荐
相关产品推荐

