Ant Design 圆形进度条
<div class="ant-progress ant-progress-circle ant-progress-status-normal ant-progress-show-info ant-progress-default">
<div class="ant-progress-inner" style="width: 120px; height: 120px; font-size: 24px;">
<svg class="ant-progress-circle " viewBox="0 0 100 100">
<path class="ant-progress-circle-trail" d="M 50,50 m 0,-47
a 47,47 0 1 1 0,94
a 47,47 0 1 1 0,-94" stroke-linecap="round" stroke-width="6" fill-opacity="0" style="stroke-dasharray: 295.31px, 295.31px; stroke-dashoffset: 0px; transition: stroke-dashoffset 0.3s ease 0s, stroke-dasharray 0.3s ease 0s, stroke 0.3s ease 0s, stroke-width 0.06s ease 0.3s;"></path>
<path class="ant-progress-circle-path" d="M 50,50 m 0,-47
a 47,47 0 1 1 0,94
a 47,47 0 1 1 0,-94" stroke="" stroke-linecap="round" stroke-width="6" opacity="1" fill-opacity="0" style="stroke-dasharray: 221.482px, 295.31px; stroke-dashoffset: 0px; transition: stroke-dashoffset 0.3s ease 0s, stroke-dasharray 0.3s ease 0s, stroke 0.3s ease 0s, stroke-width 0.06s ease 0.3s;"></path>
</svg>
<span class="ant-progress-text" title="75%">75%</span>
</div>
</div>
.ant-progress-inner {
position: relative;
display: inline-block;
width: 100%;
overflow: hidden;
vertical-align: middle;
background-color: #f5f5f5;
border-radius: 100px;
}
.ant-progress-circle .ant-progress-inner {
position: relative;
line-height: 1;
background-color: transparent;
}
.ant-progress-circle-trail {
stroke: #f5f5f5;
}
.ant-progress-inner:not(.ant-progress-circle-gradient) .ant-progress-circle-path {
stroke: #1890ff;
}
.ant-progress-text {
display: inline-block;
width: 2em;
margin-left: 8px;
color: rgba(0,0,0,.45);
font-size: 1em;
line-height: 1;
white-space: nowrap;
text-align: left;
vertical-align: middle;
word-break: normal;
}
.ant-progress-circle .ant-progress-text {
position: absolute;
top: 50%;
left: 50%;
width: 100%;
margin: 0;
padding: 0;
color: rgba(0,0,0,.65);
font-size: 1em;
line-height: 1;
white-space: normal;
text-align: center;
-webkit-transform: translate(-50%,-50%);
transform: translate(-50%,-50%);
}
SVG path 圆弧(A)指令
M = moveto L = lineto H = horizontal lineto V = vertical lineto C = curveto S = smooth curveto Q = quadratic Bézier curve T = smooth quadratic Bézier curveto A = elliptical Arc Z = closepath
以上所有命令均允许小写字母。大写表示绝对定位,小写表示相对定位。
- rx, ry 起始点
- x1, y1 终点
- rotation 椭圆的旋转角度
- large-arc-flag 指定采用椭圆上大的那部分圆弧(1)还是小的那部分(0)
- sweep-flag 指定采用顺时针的椭圆路径(1)还是逆时针的(0),如图中右边的(1)和左边的椭圆(0)
上面的 SVG 代码中 a 47,47 0 1 1 0,94
和 a 47,47 0 1 1 0,-94
表示顺时针画了2个半圆。
stroke-dasharray
是一个
和 数列,数与数之间用逗号或者空白隔开,指定短划线和缺口的长度。如果提供了奇数个值,则这个值的数列重复一次,从而变成偶数个值。因此,5,3,2 等同于 5,3,2,5,3,2。
stroke-dashoffset 表示向左偏移的距离,常与 stroke-dasharray 一起使用,实现一些好看的动画效果。
例如上面的代码中,
- 第一个 path 设置的
stroke-dasharray: 295.31px, 295.31px; stroke-dashoffset: 0px;
,其中 295.31px 是圆周长,这句代码实际上是画了个圆; - 第二个 path 设置的
stroke-dasharray: 221.482px, 295.31px; stroke-dashoffset: 0px; transition: stroke-dashoffset 0.3s ease 0s, stroke-dasharray 0.3s ease 0s, stroke 0.3s ease 0s, stroke-width 0.06s ease 0.3s;
,221.482px 是 75% 的进度条弧长,这句代码是在画带动效的进度条。
动态计算 style 代码
function getPathStyles(offset, percent, strokeColor, strokeWidth, gapDegree = 0, gapPosition) {
const radius = 50 - strokeWidth / 2;
let beginPositionX = 0;
let beginPositionY = -radius;
let endPositionX = 0;
let endPositionY = -2 * radius;
switch (gapPosition) {
case 'left':
beginPositionX = -radius;
beginPositionY = 0;
endPositionX = 2 * radius;
endPositionY = 0;
break;
case 'right':
beginPositionX = radius;
beginPositionY = 0;
endPositionX = -2 * radius;
endPositionY = 0;
break;
case 'bottom':
beginPositionY = radius;
endPositionY = 2 * radius;
break;
default:
}
const pathString = `M 50,50 m ${beginPositionX},${beginPositionY}
a ${radius},${radius} 0 1 1 ${endPositionX},${-endPositionY}
a ${radius},${radius} 0 1 1 ${-endPositionX},${endPositionY}`;
const len = Math.PI * 2 * radius;
const pathStyle = {
stroke: strokeColor,
strokeDasharray: `${(percent / 100) * (len - gapDegree)}px ${len}px`,
strokeDashoffset: `-${gapDegree / 2 + (offset / 100) * (len - gapDegree)}px`,
transition:
'stroke-dashoffset .3s ease 0s, stroke-dasharray .3s ease 0s, stroke .3s, stroke-width .06s ease .3s', // eslint-disable-line
};
return {
pathString,
pathStyle,
};
}