UNPKG

5.79 kBJavaScriptView Raw
1import _extends from "@babel/runtime/helpers/esm/extends";
2import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
3import _typeof from "@babel/runtime/helpers/esm/typeof";
4import _objectWithoutProperties from "@babel/runtime/helpers/esm/objectWithoutProperties";
5var _excluded = ["id", "prefixCls", "strokeWidth", "trailWidth", "gapDegree", "gapPosition", "trailColor", "strokeLinecap", "style", "className", "strokeColor", "percent"];
6import * as React from 'react';
7import classNames from 'classnames';
8import { useTransitionDuration, defaultProps } from './common';
9import useId from './hooks/useId';
10
11function stripPercentToNumber(percent) {
12 return +percent.replace('%', '');
13}
14
15function toArray(value) {
16 var mergedValue = value !== null && value !== void 0 ? value : [];
17 return Array.isArray(mergedValue) ? mergedValue : [mergedValue];
18}
19
20var VIEW_BOX_SIZE = 100;
21
22var getCircleStyle = function getCircleStyle(radius, offset, percent, strokeColor) {
23 var gapDegree = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 0;
24 var gapPosition = arguments.length > 5 ? arguments[5] : undefined;
25 var strokeLinecap = arguments.length > 6 ? arguments[6] : undefined;
26 var strokeWidth = arguments.length > 7 ? arguments[7] : undefined;
27 var rotateDeg = gapDegree > 0 ? 90 + gapDegree / 2 : -90;
28 var perimeter = Math.PI * 2 * radius;
29 var perimeterWithoutGap = perimeter * ((360 - gapDegree) / 360);
30 var offsetDeg = offset / 100 * 360 * ((360 - gapDegree) / 360);
31 var positionDeg = gapDegree === 0 ? 0 : {
32 bottom: 0,
33 top: 180,
34 left: 90,
35 right: -90
36 }[gapPosition];
37 var strokeDashoffset = (100 - percent) / 100 * perimeterWithoutGap; // Fix percent accuracy when strokeLinecap is round
38 // https://github.com/ant-design/ant-design/issues/35009
39
40 if (strokeLinecap === 'round' && percent !== 100) {
41 strokeDashoffset += strokeWidth / 2; // when percent is small enough (<= 1%), keep smallest value to avoid it's disapperance
42
43 if (strokeDashoffset >= perimeterWithoutGap) {
44 strokeDashoffset = perimeterWithoutGap - 0.01;
45 }
46 }
47
48 return {
49 stroke: typeof strokeColor === 'string' ? strokeColor : undefined,
50 strokeDasharray: "".concat(perimeterWithoutGap, "px ").concat(perimeter),
51 strokeDashoffset: strokeDashoffset,
52 transform: percent === 100 ? undefined : "rotate(".concat(rotateDeg + offsetDeg + positionDeg, "deg)"),
53 transformOrigin: '50% 50%',
54 transition: 'stroke-dashoffset .3s ease 0s, stroke-dasharray .3s ease 0s, stroke .3s, stroke-width .06s ease .3s, opacity .3s ease 0s',
55 fillOpacity: 0
56 };
57};
58
59var Circle = function Circle(_ref) {
60 var id = _ref.id,
61 prefixCls = _ref.prefixCls,
62 strokeWidth = _ref.strokeWidth,
63 trailWidth = _ref.trailWidth,
64 gapDegree = _ref.gapDegree,
65 gapPosition = _ref.gapPosition,
66 trailColor = _ref.trailColor,
67 strokeLinecap = _ref.strokeLinecap,
68 style = _ref.style,
69 className = _ref.className,
70 strokeColor = _ref.strokeColor,
71 percent = _ref.percent,
72 restProps = _objectWithoutProperties(_ref, _excluded);
73
74 var mergedId = useId(id);
75 var gradientId = "".concat(mergedId, "-gradient");
76 var radius = VIEW_BOX_SIZE / 2 - strokeWidth / 2;
77 var circleStyle = getCircleStyle(radius, 0, 100, trailColor, gapDegree, gapPosition, strokeLinecap, strokeWidth);
78 var percentList = toArray(percent);
79 var strokeColorList = toArray(strokeColor);
80 var gradient = strokeColorList.find(function (color) {
81 return color && _typeof(color) === 'object';
82 });
83
84 var _useTransitionDuratio = useTransitionDuration(percentList),
85 _useTransitionDuratio2 = _slicedToArray(_useTransitionDuratio, 1),
86 paths = _useTransitionDuratio2[0];
87
88 var getStokeList = function getStokeList() {
89 var stackPtg = 0;
90 return percentList.map(function (ptg, index) {
91 var color = strokeColorList[index] || strokeColorList[strokeColorList.length - 1];
92 var stroke = color && _typeof(color) === 'object' ? "url(#".concat(gradientId, ")") : undefined;
93 var circleStyleForStack = getCircleStyle(radius, stackPtg, ptg, color, gapDegree, gapPosition, strokeLinecap, strokeWidth);
94 stackPtg += ptg;
95 return /*#__PURE__*/React.createElement("circle", {
96 key: index,
97 className: "".concat(prefixCls, "-circle-path"),
98 r: radius,
99 cx: VIEW_BOX_SIZE / 2,
100 cy: VIEW_BOX_SIZE / 2,
101 stroke: stroke,
102 strokeLinecap: strokeLinecap,
103 strokeWidth: strokeWidth,
104 opacity: ptg === 0 ? 0 : 1,
105 style: circleStyleForStack,
106 ref: paths[index]
107 });
108 }).reverse();
109 };
110
111 return /*#__PURE__*/React.createElement("svg", _extends({
112 className: classNames("".concat(prefixCls, "-circle"), className),
113 viewBox: "0 0 ".concat(VIEW_BOX_SIZE, " ").concat(VIEW_BOX_SIZE),
114 style: style,
115 id: id
116 }, restProps), gradient && /*#__PURE__*/React.createElement("defs", null, /*#__PURE__*/React.createElement("linearGradient", {
117 id: gradientId,
118 x1: "100%",
119 y1: "0%",
120 x2: "0%",
121 y2: "0%"
122 }, Object.keys(gradient).sort(function (a, b) {
123 return stripPercentToNumber(a) - stripPercentToNumber(b);
124 }).map(function (key, index) {
125 return /*#__PURE__*/React.createElement("stop", {
126 key: index,
127 offset: key,
128 stopColor: gradient[key]
129 });
130 }))), /*#__PURE__*/React.createElement("circle", {
131 className: "".concat(prefixCls, "-circle-trail"),
132 r: radius,
133 cx: VIEW_BOX_SIZE / 2,
134 cy: VIEW_BOX_SIZE / 2,
135 stroke: trailColor,
136 strokeLinecap: strokeLinecap,
137 strokeWidth: trailWidth || strokeWidth,
138 style: circleStyle
139 }), getStokeList());
140};
141
142Circle.defaultProps = defaultProps;
143Circle.displayName = 'Circle';
144export default Circle;
\No newline at end of file