Ant Design 圆形进度条

https://ant.design/components/progress-cn/

circle.jpg

  1. <div class="ant-progress ant-progress-circle ant-progress-status-normal ant-progress-show-info ant-progress-default">
  2. <div class="ant-progress-inner" style="width: 120px; height: 120px; font-size: 24px;">
  3. <svg class="ant-progress-circle " viewBox="0 0 100 100">
  4. <path class="ant-progress-circle-trail" d="M 50,50 m 0,-47
  5. a 47,47 0 1 1 0,94
  6. 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>
  7. <path class="ant-progress-circle-path" d="M 50,50 m 0,-47
  8. a 47,47 0 1 1 0,94
  9. 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>
  10. </svg>
  11. <span class="ant-progress-text" title="75%">75%</span>
  12. </div>
  13. </div>
  1. .ant-progress-inner {
  2. position: relative;
  3. display: inline-block;
  4. width: 100%;
  5. overflow: hidden;
  6. vertical-align: middle;
  7. background-color: #f5f5f5;
  8. border-radius: 100px;
  9. }
  10. .ant-progress-circle .ant-progress-inner {
  11. position: relative;
  12. line-height: 1;
  13. background-color: transparent;
  14. }
  15. .ant-progress-circle-trail {
  16. stroke: #f5f5f5;
  17. }
  18. .ant-progress-inner:not(.ant-progress-circle-gradient) .ant-progress-circle-path {
  19. stroke: #1890ff;
  20. }
  21. .ant-progress-text {
  22. display: inline-block;
  23. width: 2em;
  24. margin-left: 8px;
  25. color: rgba(0,0,0,.45);
  26. font-size: 1em;
  27. line-height: 1;
  28. white-space: nowrap;
  29. text-align: left;
  30. vertical-align: middle;
  31. word-break: normal;
  32. }
  33. .ant-progress-circle .ant-progress-text {
  34. position: absolute;
  35. top: 50%;
  36. left: 50%;
  37. width: 100%;
  38. margin: 0;
  39. padding: 0;
  40. color: rgba(0,0,0,.65);
  41. font-size: 1em;
  42. line-height: 1;
  43. white-space: normal;
  44. text-align: center;
  45. -webkit-transform: translate(-50%,-50%);
  46. transform: translate(-50%,-50%);
  47. }

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

以上所有命令均允许小写字母。大写表示绝对定位,小写表示相对定位。

svg-a.png

  • rx, ry 起始点
  • x1, y1 终点
  • rotation 椭圆的旋转角度
  • large-arc-flag 指定采用椭圆上大的那部分圆弧(1)还是小的那部分(0)
  • sweep-flag 指定采用顺时针的椭圆路径(1)还是逆时针的(0),如图中右边的(1)和左边的椭圆(0)

上面的 SVG 代码中 a 47,47 0 1 1 0,94a 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 代码

  1. function getPathStyles(offset, percent, strokeColor, strokeWidth, gapDegree = 0, gapPosition) {
  2. const radius = 50 - strokeWidth / 2;
  3. let beginPositionX = 0;
  4. let beginPositionY = -radius;
  5. let endPositionX = 0;
  6. let endPositionY = -2 * radius;
  7. switch (gapPosition) {
  8. case 'left':
  9. beginPositionX = -radius;
  10. beginPositionY = 0;
  11. endPositionX = 2 * radius;
  12. endPositionY = 0;
  13. break;
  14. case 'right':
  15. beginPositionX = radius;
  16. beginPositionY = 0;
  17. endPositionX = -2 * radius;
  18. endPositionY = 0;
  19. break;
  20. case 'bottom':
  21. beginPositionY = radius;
  22. endPositionY = 2 * radius;
  23. break;
  24. default:
  25. }
  26. const pathString = `M 50,50 m ${beginPositionX},${beginPositionY}
  27. a ${radius},${radius} 0 1 1 ${endPositionX},${-endPositionY}
  28. a ${radius},${radius} 0 1 1 ${-endPositionX},${endPositionY}`;
  29. const len = Math.PI * 2 * radius;
  30. const pathStyle = {
  31. stroke: strokeColor,
  32. strokeDasharray: `${(percent / 100) * (len - gapDegree)}px ${len}px`,
  33. strokeDashoffset: `-${gapDegree / 2 + (offset / 100) * (len - gapDegree)}px`,
  34. transition:
  35. 'stroke-dashoffset .3s ease 0s, stroke-dasharray .3s ease 0s, stroke .3s, stroke-width .06s ease .3s', // eslint-disable-line
  36. };
  37. return {
  38. pathString,
  39. pathStyle,
  40. };
  41. }