如何创建底部裁剪的圆形进度条?优先采用Material UI实现
底部裁剪圆形进度条的Material UI实现思路
方案一:基于CircularProgress二次封装
利用Material UI内置的CircularProgress组件,通过SVG遮罩精准裁剪底部区域,叠加背景和进度两层进度条实现效果:
import { CircularProgress, Box } from '@mui/material'; const ClippedCircularProgress = ({ value, size = 200, thickness = 4 }) => { return ( <Box sx={{ position: 'relative', width: size, height: size }}> {/* 定义遮罩,保留顶部85%的圆形区域 */} <svg width={size} height={size} style={{ position: 'absolute' }}> <defs> <mask id="bottomClipMask"> <rect width="100%" height="85%" fill="white" /> <circle cx="50%" cy="50%" r={size / 2} fill="white" /> </mask> </defs> </svg> {/* 灰色背景进度条 */} <CircularProgress variant="determinate" value={100} size={size} thickness={thickness} sx={{ position: 'absolute', color: 'rgba(0, 0, 0, 0.12)', mask: 'url(#bottomClipMask)', }} /> {/* 彩色实际进度条 */} <CircularProgress variant="determinate" value={value} size={size} thickness={thickness} sx={{ position: 'absolute', mask: 'url(#bottomClipMask)', }} /> </Box> ); }; // 使用示例 // <ClippedCircularProgress value={70} />
方案二:自定义SVG进度条
如果需要更灵活的样式控制,直接用SVG绘制圆弧并添加裁剪,完全自定义进度条形态:
import { Box } from '@mui/material'; import { useTheme } from '@mui/material/styles'; const CustomClippedProgress = ({ value = 0, size = 200, strokeWidth = 4 }) => { const theme = useTheme(); const radius = (size - strokeWidth) / 2; const circumference = 2 * Math.PI * radius; const strokeOffset = circumference - (value / 100) * circumference; return ( <Box sx={{ width: size, height: size }}> <svg width={size} height={size} viewBox={`0 0 ${size} ${size}`}> <defs> {/* 裁剪路径:隐藏底部15%区域 */} <clipPath id="progressClip"> <rect x="0" y="0" width={size} height={size * 0.85} /> </clipPath> </defs> {/* 背景圆弧 */} <circle cx={size / 2} cy={size / 2} r={radius} fill="none" stroke={theme.palette.grey[300]} strokeWidth={strokeWidth} clipPath="url(#progressClip)" /> {/* 进度圆弧 */} <circle cx={size / 2} cy={size / 2} r={radius} fill="none" stroke={theme.palette.primary.main} strokeWidth={strokeWidth} strokeDasharray={circumference} strokeDashoffset={strokeOffset} strokeLinecap="round" transform={`rotate(-90 ${size / 2} ${size / 2})`} clipPath="url(#progressClip)" style={{ transition: 'stroke-dashoffset 0.3s ease-in-out' }} /> </svg> </Box> ); }; // 使用示例 // <CustomClippedProgress value={65} />
调整技巧
- 裁剪范围:修改代码中
85%或0.85的数值,数值越小,底部裁剪区域越大 - 样式定制:通过
stroke属性修改颜色,strokeWidth调整进度条粗细,strokeLinecap设置端点样式(圆角/直角) - 动画优化:自定义SVG方案中添加
transition属性,让进度变化更平滑
内容的提问来源于stack exchange,提问作者Ivan Kraev
相关产品推荐
相关产品推荐

