gifted-charts-core 0.0.45 → 0.0.47
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/PieChart/index.d.ts +0 -13
- package/src/PieChart/index.js +8 -159
- package/src/PieChart/index.ts +5 -240
- package/src/PieChart/pro.d.ts +22 -0
- package/src/PieChart/pro.js +178 -0
- package/src/PieChart/pro.ts +261 -0
package/package.json
CHANGED
package/src/PieChart/index.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { type pieDataItem, type PieChartPropsType } from './types';
|
|
2
2
|
import { type ColorValue } from 'react-native';
|
|
3
|
-
import { LabelsPosition } from '../utils/types';
|
|
4
3
|
interface IusePieChart {
|
|
5
4
|
radius: number;
|
|
6
5
|
extraRadiusForFocused: number;
|
|
@@ -30,18 +29,6 @@ interface IusePieChart {
|
|
|
30
29
|
isDataShifted: boolean;
|
|
31
30
|
paddingHorizontal: number;
|
|
32
31
|
paddingVertical: number;
|
|
33
|
-
isAnimated: boolean;
|
|
34
|
-
animationDuration: number;
|
|
35
|
-
initial: string;
|
|
36
|
-
dInitial: string[];
|
|
37
|
-
dFinal: string[];
|
|
38
|
-
isAnimating: boolean;
|
|
39
|
-
getStartCaps: (index: number, item: pieDataItem) => string;
|
|
40
|
-
getEndCaps: (index: number, item: pieDataItem) => string;
|
|
41
|
-
getTextCoordinates: (index: number, labelPos?: LabelsPosition) => {
|
|
42
|
-
x: number;
|
|
43
|
-
y: number;
|
|
44
|
-
};
|
|
45
32
|
}
|
|
46
33
|
interface IPieChartPropsType extends PieChartPropsType {
|
|
47
34
|
pro?: boolean;
|
package/src/PieChart/index.js
CHANGED
|
@@ -16,16 +16,15 @@ var __read = (this && this.__read) || function (o, n) {
|
|
|
16
16
|
};
|
|
17
17
|
import { useEffect, useState } from 'react';
|
|
18
18
|
import { getTextSizeForPieLabels } from '../utils';
|
|
19
|
-
import { defaultAnimationDuration } from '../utils/constants';
|
|
20
19
|
export var usePieChart = function (props) {
|
|
21
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u
|
|
20
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u;
|
|
22
21
|
var radius = (_a = props.radius) !== null && _a !== void 0 ? _a : 120;
|
|
23
22
|
var extraRadiusForFocused = (_b = props.extraRadiusForFocused) !== null && _b !== void 0 ? _b : (((_c = props.focusOnPress) !== null && _c !== void 0 ? _c : props.sectionAutoFocus) ? radius / 10 : 0);
|
|
24
23
|
var pi = props.semiCircle ? Math.PI / 2 : Math.PI;
|
|
25
|
-
var
|
|
24
|
+
var _v = __read(useState(-1), 2), selectedIndex = _v[0], setSelectedIndex = _v[1]; // at the start, nothing is selected
|
|
26
25
|
// because we're going to use a useEffect, we need startAngle and total to be state variables
|
|
27
|
-
var
|
|
28
|
-
var
|
|
26
|
+
var _w = __read(useState((_d = props.initialAngle) !== null && _d !== void 0 ? _d : (props.semiCircle ? -pi : 0)), 2), startAngle = _w[0], setStartAngle = _w[1];
|
|
27
|
+
var _x = __read(useState(0), 2), total = _x[0], setTotal = _x[1];
|
|
29
28
|
useEffect(function () {
|
|
30
29
|
var _a;
|
|
31
30
|
// Update the total, this could be use to replace the forEach : const newTotal = props.data.reduce((acc, item) => acc + item.value, 0);
|
|
@@ -64,7 +63,8 @@ export var usePieChart = function (props) {
|
|
|
64
63
|
}
|
|
65
64
|
}
|
|
66
65
|
}, [selectedIndex]);
|
|
67
|
-
var pro = props.pro, data = props.data, donut = props.donut, isThreeD = props.isThreeD, semiCircle = props.semiCircle,
|
|
66
|
+
var pro = props.pro, data = props.data, donut = props.donut, isThreeD = props.isThreeD, semiCircle = props.semiCircle, _y = props.inwardExtraLengthForFocused, inwardExtraLengthForFocused = _y === void 0 ? 0 : _y, _z = props.isAnimated, isAnimated = _z === void 0 ? false : _z, edgesRadius = props.edgesRadius;
|
|
67
|
+
var endAngle = (_e = props.endAngle) !== null && _e !== void 0 ? _e : startAngle + Math.PI * (semiCircle ? 1 : 2);
|
|
68
68
|
var canvasWidth = radius * 2;
|
|
69
69
|
var canvasHeight = isThreeD ? radius * 2.3 : radius * 2;
|
|
70
70
|
var strokeWidth = (_f = props.strokeWidth) !== null && _f !== void 0 ? _f : 0;
|
|
@@ -88,154 +88,13 @@ export var usePieChart = function (props) {
|
|
|
88
88
|
var paddingVertical = ((_t = props.paddingVertical) !== null && _t !== void 0 ? _t : props.labelsPosition === 'onBorder')
|
|
89
89
|
? ((_u = props.textBackgroundRadius) !== null && _u !== void 0 ? _u : textSize) * 2 + 6
|
|
90
90
|
: 0;
|
|
91
|
-
/********************************** PRO **********************/
|
|
92
|
-
var startAngleForPro = (_v = props.startAngle) !== null && _v !== void 0 ? _v : 0;
|
|
93
|
-
var animationDuration = (_w = props.animationDuration) !== null && _w !== void 0 ? _w : defaultAnimationDuration;
|
|
94
|
-
var _3 = __read(useState(isAnimated), 2), isAnimating = _3[0], setIsAnimating = _3[1];
|
|
95
|
-
useEffect(function () {
|
|
96
|
-
if (isAnimated) {
|
|
97
|
-
setIsAnimating(true);
|
|
98
|
-
setTimeout(function () { return setIsAnimating(false); }, animationDuration);
|
|
99
|
-
}
|
|
100
|
-
}, []);
|
|
101
|
-
var endAngleLocal = 0;
|
|
102
|
-
var addValues = function (index) {
|
|
103
|
-
if (index < 0)
|
|
104
|
-
return 0;
|
|
105
|
-
var sum = 0;
|
|
106
|
-
for (var i = 0; i <= index; i++)
|
|
107
|
-
sum += data[i].value;
|
|
108
|
-
return sum;
|
|
109
|
-
};
|
|
110
|
-
var labelsPosition = props.labelsPosition
|
|
111
|
-
? props.labelsPosition
|
|
112
|
-
: donut || props.centerLabelComponent
|
|
113
|
-
? 'outward'
|
|
114
|
-
: 'mid';
|
|
115
|
-
var getCoordinates = function (index, additionalValue, addInOnlyStart, addInOnlyEnd) {
|
|
116
|
-
var addedValue = addValues(index - 1) + (addInOnlyEnd ? 0 : additionalValue !== null && additionalValue !== void 0 ? additionalValue : 0);
|
|
117
|
-
var angle = (addedValue / total) * endAngleLocal + startAngleForPro;
|
|
118
|
-
var startInnerX = radius + Math.cos(angle) * innerRadius;
|
|
119
|
-
var startInnerY = radius - Math.sin(angle) * innerRadius;
|
|
120
|
-
var startOuterX = radius + Math.cos(angle) * radius;
|
|
121
|
-
var startOuterY = radius - Math.sin(angle) * radius;
|
|
122
|
-
var value = addValues(index - 1) +
|
|
123
|
-
data[index].value +
|
|
124
|
-
(addInOnlyStart ? 0 : additionalValue !== null && additionalValue !== void 0 ? additionalValue : 0);
|
|
125
|
-
angle = (value / total) * endAngleLocal + startAngleForPro;
|
|
126
|
-
var endOuterX = radius + Math.cos(angle) * radius;
|
|
127
|
-
var endOuterY = radius - Math.sin(angle) * radius;
|
|
128
|
-
var endInnerX = radius + Math.cos(angle) * innerRadius;
|
|
129
|
-
var endInnerY = radius - Math.sin(angle) * innerRadius;
|
|
130
|
-
return {
|
|
131
|
-
startInnerX: startInnerX,
|
|
132
|
-
startInnerY: startInnerY,
|
|
133
|
-
startOuterX: startOuterX,
|
|
134
|
-
startOuterY: startOuterY,
|
|
135
|
-
endOuterX: endOuterX,
|
|
136
|
-
endOuterY: endOuterY,
|
|
137
|
-
endInnerX: endInnerX,
|
|
138
|
-
endInnerY: endInnerY
|
|
139
|
-
};
|
|
140
|
-
};
|
|
141
|
-
var getTextCoordinates = function (index, labelPos) {
|
|
142
|
-
var value = addValues(index - 1) + data[index].value / 2;
|
|
143
|
-
var angle = (value / total) * endAngleLocal + startAngleForPro;
|
|
144
|
-
var labelPosition = labelPos || labelsPosition;
|
|
145
|
-
var x = radius +
|
|
146
|
-
Math.cos(angle) *
|
|
147
|
-
radius *
|
|
148
|
-
(labelPosition === 'inward'
|
|
149
|
-
? 0.25
|
|
150
|
-
: labelPosition === 'mid'
|
|
151
|
-
? 0.5
|
|
152
|
-
: labelPosition === 'outward'
|
|
153
|
-
? 0.75
|
|
154
|
-
: 1);
|
|
155
|
-
var y = radius -
|
|
156
|
-
Math.sin(angle) *
|
|
157
|
-
radius *
|
|
158
|
-
(labelPosition === 'inward'
|
|
159
|
-
? 0.25
|
|
160
|
-
: labelPosition === 'mid'
|
|
161
|
-
? 0.5
|
|
162
|
-
: labelPosition === 'outward'
|
|
163
|
-
? 0.75
|
|
164
|
-
: 1);
|
|
165
|
-
return { x: x, y: y };
|
|
166
|
-
};
|
|
167
|
-
var initial = '';
|
|
168
|
-
var getInitial = function (item) {
|
|
169
|
-
if (item.isStartEdgeCurved || item.startEdgeRadius) {
|
|
170
|
-
var _a = getCoordinates(0, (radius - innerRadius) / (radius / 20)), startInnerX = _a.startInnerX, startInnerY = _a.startInnerY, startOuterX = _a.startOuterX, startOuterY = _a.startOuterY;
|
|
171
|
-
return "M".concat(startInnerX, ",").concat(startInnerY, " L").concat(startOuterX, ",").concat(startOuterY, " ");
|
|
172
|
-
}
|
|
173
|
-
return "M".concat(radius + innerRadius, ",").concat(radius, " h").concat(radius - innerRadius, " ");
|
|
174
|
-
};
|
|
175
|
-
var getPath = function (index) {
|
|
176
|
-
var _a;
|
|
177
|
-
var _b = getCoordinates(index), endOuterX = _b.endOuterX, endOuterY = _b.endOuterY;
|
|
178
|
-
var isLargeArc = data[index].value / total > 0.5 ? 1 : 0;
|
|
179
|
-
var arc = "A".concat(radius + ((_a = props.strokeWidth) !== null && _a !== void 0 ? _a : 0) / 2, ",").concat(radius, " 0 ").concat(isLargeArc, " 0 ");
|
|
180
|
-
var path = "".concat(arc, " ").concat(endOuterX, ", ").concat(endOuterY, "\n L").concat(radius, ",").concat(radius, " ");
|
|
181
|
-
initial = "M".concat(radius, ",").concat(radius, " L").concat(endOuterX, ",").concat(endOuterY);
|
|
182
|
-
return path;
|
|
183
|
-
};
|
|
184
|
-
var getDonutPath = function (index, item) {
|
|
185
|
-
var _a;
|
|
186
|
-
var additionalForStart = item.isStartEdgeCurved || item.startEdgeRadius
|
|
187
|
-
? (radius - innerRadius) / (radius / 20)
|
|
188
|
-
: 0;
|
|
189
|
-
var additionalForEnd = item.isEndEdgeCurved || item.endEdgeRadius
|
|
190
|
-
? (radius - innerRadius) / (radius / -20)
|
|
191
|
-
: 0;
|
|
192
|
-
var cropAtEnd = !!(index === data.length - 1 &&
|
|
193
|
-
(item.isEndEdgeCurved || item.endEdgeRadius));
|
|
194
|
-
var _b = getCoordinates(index, cropAtEnd ? additionalForEnd : additionalForStart, !cropAtEnd, cropAtEnd), startInnerX = _b.startInnerX, startInnerY = _b.startInnerY, endOuterX = _b.endOuterX, endOuterY = _b.endOuterY, endInnerX = _b.endInnerX, endInnerY = _b.endInnerY;
|
|
195
|
-
var isLargeArc = data[index].value / total > 0.5 ? 1 : 0;
|
|
196
|
-
var innerArc = "A".concat(innerRadius, ",").concat(innerRadius, " 0 ").concat(isLargeArc, " 1 ");
|
|
197
|
-
var outerArc = "A".concat(radius + ((_a = props.strokeWidth) !== null && _a !== void 0 ? _a : 0) / 2, ",").concat(radius, " 0 ").concat(isLargeArc, " 0 ");
|
|
198
|
-
var path = "".concat(outerArc, " ").concat(endOuterX, ", ").concat(endOuterY, "\n L").concat(endInnerX, ",").concat(endInnerY, " M").concat(endInnerX, ",").concat(endInnerY, " ").concat(innerArc, " ").concat(startInnerX, ",").concat(startInnerY);
|
|
199
|
-
initial = "M".concat(endInnerX, ",").concat(endInnerY, " L").concat(endOuterX, ",").concat(endOuterY, " ");
|
|
200
|
-
return path;
|
|
201
|
-
};
|
|
202
|
-
var getStartCaps = function (index, item) {
|
|
203
|
-
var _a, _b;
|
|
204
|
-
var edgeRadius = (_b = (_a = item.startEdgeRadius) !== null && _a !== void 0 ? _a : edgesRadius) !== null && _b !== void 0 ? _b : 1;
|
|
205
|
-
var additional = (item.isStartEdgeCurved || item.startEdgeRadius
|
|
206
|
-
? (radius - innerRadius) / (radius / 20)
|
|
207
|
-
: 0) +
|
|
208
|
-
strokeWidth / 2;
|
|
209
|
-
var _c = getCoordinates(index, additional), startInnerX = _c.startInnerX, startInnerY = _c.startInnerY, startOuterX = _c.startOuterX, startOuterY = _c.startOuterY;
|
|
210
|
-
var path = "M".concat(startInnerX, ",").concat(startInnerY, " A").concat(edgeRadius, ",").concat(edgeRadius, " 0 0 0 ").concat(startOuterX, ",").concat(startOuterY);
|
|
211
|
-
return path;
|
|
212
|
-
};
|
|
213
|
-
var getEndCaps = function (index, item) {
|
|
214
|
-
var _a, _b;
|
|
215
|
-
var edgeRadius = (_b = (_a = item.endEdgeRadius) !== null && _a !== void 0 ? _a : edgesRadius) !== null && _b !== void 0 ? _b : 1;
|
|
216
|
-
var additional = (item.isEndEdgeCurved || item.endEdgeRadius
|
|
217
|
-
? (radius - innerRadius) / (radius / 20)
|
|
218
|
-
: 0) -
|
|
219
|
-
strokeWidth / 2;
|
|
220
|
-
var _c = getCoordinates(index, -additional), endInnerX = _c.endInnerX, endInnerY = _c.endInnerY, endOuterX = _c.endOuterX, endOuterY = _c.endOuterY;
|
|
221
|
-
var path = "M".concat(endInnerX, ",").concat(endInnerY, " A").concat(edgeRadius, ",").concat(edgeRadius, " 0 0 1 ").concat(endOuterX, ",").concat(endOuterY);
|
|
222
|
-
return path;
|
|
223
|
-
};
|
|
224
|
-
var dInitial = data.map(function (item, index) {
|
|
225
|
-
return "".concat(initial || getInitial(item), " ").concat(donut ? getDonutPath(index, item) : getPath(index));
|
|
226
|
-
});
|
|
227
|
-
endAngleLocal = endAngle;
|
|
228
|
-
initial = '';
|
|
229
|
-
var dFinal = data.map(function (item, index) {
|
|
230
|
-
return "".concat(initial || getInitial(item), " ").concat(donut ? getDonutPath(index, item) : getPath(index));
|
|
231
|
-
});
|
|
232
91
|
return {
|
|
233
92
|
radius: radius,
|
|
234
93
|
extraRadiusForFocused: extraRadiusForFocused,
|
|
235
94
|
pi: pi,
|
|
236
95
|
selectedIndex: selectedIndex,
|
|
237
96
|
setSelectedIndex: setSelectedIndex,
|
|
238
|
-
startAngle:
|
|
97
|
+
startAngle: startAngle,
|
|
239
98
|
endAngle: endAngle,
|
|
240
99
|
setStartAngle: setStartAngle,
|
|
241
100
|
total: total,
|
|
@@ -257,16 +116,6 @@ export var usePieChart = function (props) {
|
|
|
257
116
|
tiltAngle: tiltAngle,
|
|
258
117
|
isDataShifted: isDataShifted,
|
|
259
118
|
paddingHorizontal: paddingHorizontal,
|
|
260
|
-
paddingVertical: paddingVertical
|
|
261
|
-
isAnimated: isAnimated,
|
|
262
|
-
animationDuration: animationDuration / 1000,
|
|
263
|
-
// PRO
|
|
264
|
-
initial: initial,
|
|
265
|
-
dInitial: dInitial,
|
|
266
|
-
dFinal: dFinal,
|
|
267
|
-
isAnimating: isAnimating,
|
|
268
|
-
getStartCaps: getStartCaps,
|
|
269
|
-
getEndCaps: getEndCaps,
|
|
270
|
-
getTextCoordinates: getTextCoordinates
|
|
119
|
+
paddingVertical: paddingVertical
|
|
271
120
|
};
|
|
272
121
|
};
|
package/src/PieChart/index.ts
CHANGED
|
@@ -2,8 +2,6 @@ import { useEffect, useState } from 'react'
|
|
|
2
2
|
import { type pieDataItem, type PieChartPropsType } from './types'
|
|
3
3
|
import { getTextSizeForPieLabels } from '../utils'
|
|
4
4
|
import { type ColorValue } from 'react-native'
|
|
5
|
-
import { defaultAnimationDuration } from '../utils/constants'
|
|
6
|
-
import { LabelsPosition } from '../utils/types'
|
|
7
5
|
|
|
8
6
|
interface IusePieChart {
|
|
9
7
|
radius: number
|
|
@@ -34,18 +32,6 @@ interface IusePieChart {
|
|
|
34
32
|
isDataShifted: boolean
|
|
35
33
|
paddingHorizontal: number
|
|
36
34
|
paddingVertical: number
|
|
37
|
-
isAnimated: boolean
|
|
38
|
-
animationDuration: number
|
|
39
|
-
initial: string
|
|
40
|
-
dInitial: string[]
|
|
41
|
-
dFinal: string[]
|
|
42
|
-
isAnimating: boolean
|
|
43
|
-
getStartCaps: (index: number, item: pieDataItem) => string
|
|
44
|
-
getEndCaps: (index: number, item: pieDataItem) => string
|
|
45
|
-
getTextCoordinates: (
|
|
46
|
-
index: number,
|
|
47
|
-
labelPos?: LabelsPosition
|
|
48
|
-
) => { x: number; y: number }
|
|
49
35
|
}
|
|
50
36
|
|
|
51
37
|
interface IPieChartPropsType extends PieChartPropsType {
|
|
@@ -116,10 +102,11 @@ export const usePieChart = (props: IPieChartPropsType): IusePieChart => {
|
|
|
116
102
|
semiCircle,
|
|
117
103
|
inwardExtraLengthForFocused = 0,
|
|
118
104
|
isAnimated = false,
|
|
119
|
-
edgesRadius
|
|
120
|
-
endAngle = props.endAngle ?? startAngle + Math.PI * 2
|
|
105
|
+
edgesRadius
|
|
121
106
|
} = props
|
|
122
107
|
|
|
108
|
+
let endAngle = props.endAngle ?? startAngle + Math.PI * (semiCircle ? 1 : 2)
|
|
109
|
+
|
|
123
110
|
const canvasWidth = radius * 2
|
|
124
111
|
const canvasHeight = isThreeD ? radius * 2.3 : radius * 2
|
|
125
112
|
|
|
@@ -154,223 +141,13 @@ export const usePieChart = (props: IPieChartPropsType): IusePieChart => {
|
|
|
154
141
|
? (props.textBackgroundRadius ?? textSize) * 2 + 6
|
|
155
142
|
: 0
|
|
156
143
|
|
|
157
|
-
/********************************** PRO **********************/
|
|
158
|
-
|
|
159
|
-
const startAngleForPro = props.startAngle ?? 0
|
|
160
|
-
const animationDuration = props.animationDuration ?? defaultAnimationDuration
|
|
161
|
-
|
|
162
|
-
const [isAnimating, setIsAnimating] = useState(isAnimated)
|
|
163
|
-
|
|
164
|
-
useEffect(() => {
|
|
165
|
-
if (isAnimated) {
|
|
166
|
-
setIsAnimating(true)
|
|
167
|
-
setTimeout(() => setIsAnimating(false), animationDuration)
|
|
168
|
-
}
|
|
169
|
-
}, [])
|
|
170
|
-
|
|
171
|
-
let endAngleLocal = 0
|
|
172
|
-
|
|
173
|
-
const addValues = (index: number) => {
|
|
174
|
-
if (index < 0) return 0
|
|
175
|
-
let sum = 0
|
|
176
|
-
for (let i = 0; i <= index; i++) sum += data[i].value
|
|
177
|
-
return sum
|
|
178
|
-
}
|
|
179
|
-
const labelsPosition = props.labelsPosition
|
|
180
|
-
? props.labelsPosition
|
|
181
|
-
: donut || props.centerLabelComponent
|
|
182
|
-
? 'outward'
|
|
183
|
-
: 'mid'
|
|
184
|
-
|
|
185
|
-
const getCoordinates = (
|
|
186
|
-
index: number,
|
|
187
|
-
additionalValue?: number,
|
|
188
|
-
addInOnlyStart?: boolean,
|
|
189
|
-
addInOnlyEnd?: boolean
|
|
190
|
-
) => {
|
|
191
|
-
const addedValue =
|
|
192
|
-
addValues(index - 1) + (addInOnlyEnd ? 0 : additionalValue ?? 0)
|
|
193
|
-
let angle = (addedValue / total) * endAngleLocal + startAngleForPro
|
|
194
|
-
const startInnerX = radius + Math.cos(angle) * innerRadius
|
|
195
|
-
const startInnerY = radius - Math.sin(angle) * innerRadius
|
|
196
|
-
const startOuterX = radius + Math.cos(angle) * radius
|
|
197
|
-
const startOuterY = radius - Math.sin(angle) * radius
|
|
198
|
-
|
|
199
|
-
const value =
|
|
200
|
-
addValues(index - 1) +
|
|
201
|
-
data[index].value +
|
|
202
|
-
(addInOnlyStart ? 0 : additionalValue ?? 0)
|
|
203
|
-
angle = (value / total) * endAngleLocal + startAngleForPro
|
|
204
|
-
|
|
205
|
-
const endOuterX = radius + Math.cos(angle) * radius
|
|
206
|
-
const endOuterY = radius - Math.sin(angle) * radius
|
|
207
|
-
|
|
208
|
-
const endInnerX = radius + Math.cos(angle) * innerRadius
|
|
209
|
-
const endInnerY = radius - Math.sin(angle) * innerRadius
|
|
210
|
-
|
|
211
|
-
return {
|
|
212
|
-
startInnerX,
|
|
213
|
-
startInnerY,
|
|
214
|
-
startOuterX,
|
|
215
|
-
startOuterY,
|
|
216
|
-
endOuterX,
|
|
217
|
-
endOuterY,
|
|
218
|
-
endInnerX,
|
|
219
|
-
endInnerY
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
const getTextCoordinates = (index: number, labelPos?: LabelsPosition) => {
|
|
224
|
-
const value = addValues(index - 1) + data[index].value / 2
|
|
225
|
-
const angle = (value / total) * endAngleLocal + startAngleForPro
|
|
226
|
-
|
|
227
|
-
const labelPosition: LabelsPosition = labelPos || labelsPosition
|
|
228
|
-
|
|
229
|
-
let x =
|
|
230
|
-
radius +
|
|
231
|
-
Math.cos(angle) *
|
|
232
|
-
radius *
|
|
233
|
-
(labelPosition === 'inward'
|
|
234
|
-
? 0.25
|
|
235
|
-
: labelPosition === 'mid'
|
|
236
|
-
? 0.5
|
|
237
|
-
: labelPosition === 'outward'
|
|
238
|
-
? 0.75
|
|
239
|
-
: 1)
|
|
240
|
-
let y =
|
|
241
|
-
radius -
|
|
242
|
-
Math.sin(angle) *
|
|
243
|
-
radius *
|
|
244
|
-
(labelPosition === 'inward'
|
|
245
|
-
? 0.25
|
|
246
|
-
: labelPosition === 'mid'
|
|
247
|
-
? 0.5
|
|
248
|
-
: labelPosition === 'outward'
|
|
249
|
-
? 0.75
|
|
250
|
-
: 1)
|
|
251
|
-
|
|
252
|
-
return { x, y }
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
var initial = ''
|
|
256
|
-
const getInitial = (item: pieDataItem) => {
|
|
257
|
-
if (item.isStartEdgeCurved || item.startEdgeRadius) {
|
|
258
|
-
const { startInnerX, startInnerY, startOuterX, startOuterY } =
|
|
259
|
-
getCoordinates(0, (radius - innerRadius) / (radius / 20))
|
|
260
|
-
|
|
261
|
-
return `M${startInnerX},${startInnerY} L${startOuterX},${startOuterY} `
|
|
262
|
-
}
|
|
263
|
-
return `M${radius + innerRadius},${radius} h${radius - innerRadius} `
|
|
264
|
-
}
|
|
265
|
-
const getPath = (index: number) => {
|
|
266
|
-
const { endOuterX, endOuterY } = getCoordinates(index)
|
|
267
|
-
|
|
268
|
-
const isLargeArc = data[index].value / total > 0.5 ? 1 : 0
|
|
269
|
-
|
|
270
|
-
const arc = `A${
|
|
271
|
-
radius + (props.strokeWidth ?? 0) / 2
|
|
272
|
-
},${radius} 0 ${isLargeArc} 0 `
|
|
273
|
-
const path = `${arc} ${endOuterX}, ${endOuterY}
|
|
274
|
-
L${radius},${radius} `
|
|
275
|
-
|
|
276
|
-
initial = `M${radius},${radius} L${endOuterX},${endOuterY}`
|
|
277
|
-
|
|
278
|
-
return path
|
|
279
|
-
}
|
|
280
|
-
const getDonutPath = (index: number, item: pieDataItem) => {
|
|
281
|
-
const additionalForStart =
|
|
282
|
-
item.isStartEdgeCurved || item.startEdgeRadius
|
|
283
|
-
? (radius - innerRadius) / (radius / 20)
|
|
284
|
-
: 0
|
|
285
|
-
|
|
286
|
-
const additionalForEnd =
|
|
287
|
-
item.isEndEdgeCurved || item.endEdgeRadius
|
|
288
|
-
? (radius - innerRadius) / (radius / -20)
|
|
289
|
-
: 0
|
|
290
|
-
|
|
291
|
-
const cropAtEnd = !!(
|
|
292
|
-
index === data.length - 1 &&
|
|
293
|
-
(item.isEndEdgeCurved || item.endEdgeRadius)
|
|
294
|
-
)
|
|
295
|
-
const {
|
|
296
|
-
startInnerX,
|
|
297
|
-
startInnerY,
|
|
298
|
-
endOuterX,
|
|
299
|
-
endOuterY,
|
|
300
|
-
endInnerX,
|
|
301
|
-
endInnerY
|
|
302
|
-
} = getCoordinates(
|
|
303
|
-
index,
|
|
304
|
-
cropAtEnd ? additionalForEnd : additionalForStart,
|
|
305
|
-
!cropAtEnd,
|
|
306
|
-
cropAtEnd
|
|
307
|
-
)
|
|
308
|
-
|
|
309
|
-
const isLargeArc = data[index].value / total > 0.5 ? 1 : 0
|
|
310
|
-
|
|
311
|
-
const innerArc = `A${innerRadius},${innerRadius} 0 ${isLargeArc} 1 `
|
|
312
|
-
const outerArc = `A${
|
|
313
|
-
radius + (props.strokeWidth ?? 0) / 2
|
|
314
|
-
},${radius} 0 ${isLargeArc} 0 `
|
|
315
|
-
const path = `${outerArc} ${endOuterX}, ${endOuterY}
|
|
316
|
-
L${endInnerX},${endInnerY} M${endInnerX},${endInnerY} ${innerArc} ${startInnerX},${startInnerY}`
|
|
317
|
-
|
|
318
|
-
initial = `M${endInnerX},${endInnerY} L${endOuterX},${endOuterY} `
|
|
319
|
-
|
|
320
|
-
return path
|
|
321
|
-
}
|
|
322
|
-
const getStartCaps = (index: number, item: pieDataItem) => {
|
|
323
|
-
const edgeRadius = item.startEdgeRadius ?? edgesRadius ?? 1
|
|
324
|
-
const additional =
|
|
325
|
-
(item.isStartEdgeCurved || item.startEdgeRadius
|
|
326
|
-
? (radius - innerRadius) / (radius / 20)
|
|
327
|
-
: 0) +
|
|
328
|
-
strokeWidth / 2
|
|
329
|
-
const { startInnerX, startInnerY, startOuterX, startOuterY } =
|
|
330
|
-
getCoordinates(index, additional)
|
|
331
|
-
|
|
332
|
-
const path = `M${startInnerX},${startInnerY} A${edgeRadius},${edgeRadius} 0 0 0 ${startOuterX},${startOuterY}`
|
|
333
|
-
return path
|
|
334
|
-
}
|
|
335
|
-
const getEndCaps = (index: number, item: pieDataItem) => {
|
|
336
|
-
const edgeRadius = item.endEdgeRadius ?? edgesRadius ?? 1
|
|
337
|
-
const additional =
|
|
338
|
-
(item.isEndEdgeCurved || item.endEdgeRadius
|
|
339
|
-
? (radius - innerRadius) / (radius / 20)
|
|
340
|
-
: 0) -
|
|
341
|
-
strokeWidth / 2
|
|
342
|
-
const { endInnerX, endInnerY, endOuterX, endOuterY } = getCoordinates(
|
|
343
|
-
index,
|
|
344
|
-
-additional
|
|
345
|
-
)
|
|
346
|
-
|
|
347
|
-
const path = `M${endInnerX},${endInnerY} A${edgeRadius},${edgeRadius} 0 0 1 ${endOuterX},${endOuterY}`
|
|
348
|
-
return path
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
const dInitial = data.map(
|
|
352
|
-
(item, index) =>
|
|
353
|
-
`${initial || getInitial(item)} ${
|
|
354
|
-
donut ? getDonutPath(index, item) : getPath(index)
|
|
355
|
-
}`
|
|
356
|
-
)
|
|
357
|
-
|
|
358
|
-
endAngleLocal = endAngle
|
|
359
|
-
initial = ''
|
|
360
|
-
const dFinal = data.map(
|
|
361
|
-
(item, index) =>
|
|
362
|
-
`${initial || getInitial(item)} ${
|
|
363
|
-
donut ? getDonutPath(index, item) : getPath(index)
|
|
364
|
-
}`
|
|
365
|
-
)
|
|
366
|
-
|
|
367
144
|
return {
|
|
368
145
|
radius,
|
|
369
146
|
extraRadiusForFocused,
|
|
370
147
|
pi,
|
|
371
148
|
selectedIndex,
|
|
372
149
|
setSelectedIndex,
|
|
373
|
-
startAngle
|
|
150
|
+
startAngle,
|
|
374
151
|
endAngle,
|
|
375
152
|
setStartAngle,
|
|
376
153
|
total,
|
|
@@ -392,18 +169,6 @@ export const usePieChart = (props: IPieChartPropsType): IusePieChart => {
|
|
|
392
169
|
tiltAngle,
|
|
393
170
|
isDataShifted,
|
|
394
171
|
paddingHorizontal,
|
|
395
|
-
paddingVertical
|
|
396
|
-
isAnimated,
|
|
397
|
-
animationDuration: animationDuration / 1000,
|
|
398
|
-
|
|
399
|
-
// PRO
|
|
400
|
-
|
|
401
|
-
initial,
|
|
402
|
-
dInitial,
|
|
403
|
-
dFinal,
|
|
404
|
-
isAnimating,
|
|
405
|
-
getStartCaps,
|
|
406
|
-
getEndCaps,
|
|
407
|
-
getTextCoordinates
|
|
172
|
+
paddingVertical
|
|
408
173
|
}
|
|
409
174
|
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { PieChartPropsType, pieDataItem } from './types';
|
|
2
|
+
import { LabelsPosition } from '../utils/types';
|
|
3
|
+
interface IusePiePro {
|
|
4
|
+
radius: number;
|
|
5
|
+
total: number;
|
|
6
|
+
donut?: boolean;
|
|
7
|
+
strokeWidth: number;
|
|
8
|
+
isAnimated?: boolean;
|
|
9
|
+
animationDuration: number;
|
|
10
|
+
initial: string;
|
|
11
|
+
dInitial: string[];
|
|
12
|
+
dFinal: string[];
|
|
13
|
+
isAnimating?: boolean;
|
|
14
|
+
getStartCaps: (index: number, item: pieDataItem) => string;
|
|
15
|
+
getEndCaps: (index: number, item: pieDataItem) => string;
|
|
16
|
+
getTextCoordinates: (index: number, labelPos?: LabelsPosition) => {
|
|
17
|
+
x: number;
|
|
18
|
+
y: number;
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
export declare const usePiePro: (props: PieChartPropsType) => IusePiePro;
|
|
22
|
+
export {};
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
var __read = (this && this.__read) || function (o, n) {
|
|
2
|
+
var m = typeof Symbol === "function" && o[Symbol.iterator];
|
|
3
|
+
if (!m) return o;
|
|
4
|
+
var i = m.call(o), r, ar = [], e;
|
|
5
|
+
try {
|
|
6
|
+
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
|
|
7
|
+
}
|
|
8
|
+
catch (error) { e = { error: error }; }
|
|
9
|
+
finally {
|
|
10
|
+
try {
|
|
11
|
+
if (r && !r.done && (m = i["return"])) m.call(i);
|
|
12
|
+
}
|
|
13
|
+
finally { if (e) throw e.error; }
|
|
14
|
+
}
|
|
15
|
+
return ar;
|
|
16
|
+
};
|
|
17
|
+
import { useEffect, useState } from 'react';
|
|
18
|
+
import { defaultAnimationDuration } from '../utils/constants';
|
|
19
|
+
export var usePiePro = function (props) {
|
|
20
|
+
var _a, _b;
|
|
21
|
+
var data = props.data, isAnimated = props.isAnimated, donut = props.donut, semiCircle = props.semiCircle, _c = props.radius, radius = _c === void 0 ? 120 : _c, _d = props.innerRadius, innerRadius = _d === void 0 ? radius / 2.5 : _d, _e = props.strokeWidth, strokeWidth = _e === void 0 ? 0 : _e, _f = props.edgesRadius, edgesRadius = _f === void 0 ? 0 : _f, _g = props.startAngle, startAngle = _g === void 0 ? 0 : _g;
|
|
22
|
+
var endAngle = (_a = props.endAngle) !== null && _a !== void 0 ? _a : startAngle + Math.PI * (semiCircle ? 1 : 2);
|
|
23
|
+
var total = data.reduce(function (acc, item) { return acc + item.value; }, 0);
|
|
24
|
+
var animationDuration = (_b = props.animationDuration) !== null && _b !== void 0 ? _b : defaultAnimationDuration;
|
|
25
|
+
var _h = __read(useState(isAnimated), 2), isAnimating = _h[0], setIsAnimating = _h[1];
|
|
26
|
+
useEffect(function () {
|
|
27
|
+
if (isAnimated) {
|
|
28
|
+
setIsAnimating(true);
|
|
29
|
+
setTimeout(function () { return setIsAnimating(false); }, animationDuration);
|
|
30
|
+
}
|
|
31
|
+
}, []);
|
|
32
|
+
var endAngleLocal = 0;
|
|
33
|
+
var addValues = function (index) {
|
|
34
|
+
if (index < 0)
|
|
35
|
+
return 0;
|
|
36
|
+
var sum = 0;
|
|
37
|
+
for (var i = 0; i <= index; i++)
|
|
38
|
+
sum += data[i].value;
|
|
39
|
+
return sum;
|
|
40
|
+
};
|
|
41
|
+
var labelsPosition = props.labelsPosition
|
|
42
|
+
? props.labelsPosition
|
|
43
|
+
: donut || props.centerLabelComponent
|
|
44
|
+
? 'outward'
|
|
45
|
+
: 'mid';
|
|
46
|
+
var getCoordinates = function (index, additionalValue, addInOnlyStart, addInOnlyEnd) {
|
|
47
|
+
var addedValue = addValues(index - 1) + (addInOnlyEnd ? 0 : additionalValue !== null && additionalValue !== void 0 ? additionalValue : 0);
|
|
48
|
+
var angle = (addedValue / total) * endAngleLocal + startAngle;
|
|
49
|
+
var startInnerX = radius + Math.cos(angle) * innerRadius;
|
|
50
|
+
var startInnerY = radius - Math.sin(angle) * innerRadius;
|
|
51
|
+
var startOuterX = radius + Math.cos(angle) * radius;
|
|
52
|
+
var startOuterY = radius - Math.sin(angle) * radius;
|
|
53
|
+
var value = addValues(index - 1) +
|
|
54
|
+
data[index].value +
|
|
55
|
+
(addInOnlyStart ? 0 : additionalValue !== null && additionalValue !== void 0 ? additionalValue : 0);
|
|
56
|
+
angle = (value / total) * endAngleLocal + startAngle;
|
|
57
|
+
var endOuterX = radius + Math.cos(angle) * radius;
|
|
58
|
+
var endOuterY = radius - Math.sin(angle) * radius;
|
|
59
|
+
var endInnerX = radius + Math.cos(angle) * innerRadius;
|
|
60
|
+
var endInnerY = radius - Math.sin(angle) * innerRadius;
|
|
61
|
+
return {
|
|
62
|
+
startInnerX: startInnerX,
|
|
63
|
+
startInnerY: startInnerY,
|
|
64
|
+
startOuterX: startOuterX,
|
|
65
|
+
startOuterY: startOuterY,
|
|
66
|
+
endOuterX: endOuterX,
|
|
67
|
+
endOuterY: endOuterY,
|
|
68
|
+
endInnerX: endInnerX,
|
|
69
|
+
endInnerY: endInnerY
|
|
70
|
+
};
|
|
71
|
+
};
|
|
72
|
+
var getTextCoordinates = function (index, labelPos) {
|
|
73
|
+
var value = addValues(index - 1) + data[index].value / 2;
|
|
74
|
+
var angle = (value / total) * endAngleLocal + startAngle;
|
|
75
|
+
var labelPosition = labelPos || labelsPosition;
|
|
76
|
+
var x = radius +
|
|
77
|
+
Math.cos(angle) *
|
|
78
|
+
radius *
|
|
79
|
+
(labelPosition === 'inward'
|
|
80
|
+
? 0.25
|
|
81
|
+
: labelPosition === 'mid'
|
|
82
|
+
? 0.5
|
|
83
|
+
: labelPosition === 'outward'
|
|
84
|
+
? 0.75
|
|
85
|
+
: 1);
|
|
86
|
+
var y = radius -
|
|
87
|
+
Math.sin(angle) *
|
|
88
|
+
radius *
|
|
89
|
+
(labelPosition === 'inward'
|
|
90
|
+
? 0.25
|
|
91
|
+
: labelPosition === 'mid'
|
|
92
|
+
? 0.5
|
|
93
|
+
: labelPosition === 'outward'
|
|
94
|
+
? 0.75
|
|
95
|
+
: 1);
|
|
96
|
+
return { x: x, y: y };
|
|
97
|
+
};
|
|
98
|
+
var initial = '';
|
|
99
|
+
var getInitial = function (item) {
|
|
100
|
+
if (item.isStartEdgeCurved || item.startEdgeRadius) {
|
|
101
|
+
var _a = getCoordinates(0, (radius - innerRadius) / (radius / 20)), startInnerX = _a.startInnerX, startInnerY = _a.startInnerY, startOuterX = _a.startOuterX, startOuterY = _a.startOuterY;
|
|
102
|
+
return "M".concat(startInnerX, ",").concat(startInnerY, " L").concat(startOuterX, ",").concat(startOuterY, " ");
|
|
103
|
+
}
|
|
104
|
+
return "M".concat(radius + innerRadius, ",").concat(radius, " h").concat(radius - innerRadius, " ");
|
|
105
|
+
};
|
|
106
|
+
var getPath = function (index) {
|
|
107
|
+
var _a;
|
|
108
|
+
var _b = getCoordinates(index), endOuterX = _b.endOuterX, endOuterY = _b.endOuterY;
|
|
109
|
+
var isLargeArc = data[index].value / total > 0.5 ? 1 : 0;
|
|
110
|
+
var arc = "A".concat(radius + ((_a = props.strokeWidth) !== null && _a !== void 0 ? _a : 0) / 2, ",").concat(radius, " 0 ").concat(isLargeArc, " 0 ");
|
|
111
|
+
var path = "".concat(arc, " ").concat(endOuterX, ", ").concat(endOuterY, "\n L").concat(radius, ",").concat(radius, " ");
|
|
112
|
+
initial = "M".concat(radius, ",").concat(radius, " L").concat(endOuterX, ",").concat(endOuterY);
|
|
113
|
+
return path;
|
|
114
|
+
};
|
|
115
|
+
var getDonutPath = function (index, item) {
|
|
116
|
+
var _a;
|
|
117
|
+
var additionalForStart = item.isStartEdgeCurved || item.startEdgeRadius
|
|
118
|
+
? (radius - innerRadius) / (radius / 20)
|
|
119
|
+
: 0;
|
|
120
|
+
var additionalForEnd = item.isEndEdgeCurved || item.endEdgeRadius
|
|
121
|
+
? (radius - innerRadius) / (radius / -20)
|
|
122
|
+
: 0;
|
|
123
|
+
var cropAtEnd = !!(index === data.length - 1 &&
|
|
124
|
+
(item.isEndEdgeCurved || item.endEdgeRadius));
|
|
125
|
+
var _b = getCoordinates(index, cropAtEnd ? additionalForEnd : additionalForStart, !cropAtEnd, cropAtEnd), startInnerX = _b.startInnerX, startInnerY = _b.startInnerY, endOuterX = _b.endOuterX, endOuterY = _b.endOuterY, endInnerX = _b.endInnerX, endInnerY = _b.endInnerY;
|
|
126
|
+
var isLargeArc = data[index].value / total > 0.5 ? 1 : 0;
|
|
127
|
+
var innerArc = "A".concat(innerRadius, ",").concat(innerRadius, " 0 ").concat(isLargeArc, " 1 ");
|
|
128
|
+
var outerArc = "A".concat(radius + ((_a = props.strokeWidth) !== null && _a !== void 0 ? _a : 0) / 2, ",").concat(radius, " 0 ").concat(isLargeArc, " 0 ");
|
|
129
|
+
var path = "".concat(outerArc, " ").concat(endOuterX, ", ").concat(endOuterY, "\n L").concat(endInnerX, ",").concat(endInnerY, " M").concat(endInnerX, ",").concat(endInnerY, " ").concat(innerArc, " ").concat(startInnerX, ",").concat(startInnerY);
|
|
130
|
+
initial = "M".concat(endInnerX, ",").concat(endInnerY, " L").concat(endOuterX, ",").concat(endOuterY, " ");
|
|
131
|
+
return path;
|
|
132
|
+
};
|
|
133
|
+
var getStartCaps = function (index, item) {
|
|
134
|
+
var _a, _b;
|
|
135
|
+
var edgeRadius = (_b = (_a = item.startEdgeRadius) !== null && _a !== void 0 ? _a : edgesRadius) !== null && _b !== void 0 ? _b : 1;
|
|
136
|
+
var additional = (item.isStartEdgeCurved || item.startEdgeRadius
|
|
137
|
+
? (radius - innerRadius) / (radius / 20)
|
|
138
|
+
: 0) +
|
|
139
|
+
strokeWidth / 2;
|
|
140
|
+
var _c = getCoordinates(index, additional), startInnerX = _c.startInnerX, startInnerY = _c.startInnerY, startOuterX = _c.startOuterX, startOuterY = _c.startOuterY;
|
|
141
|
+
var path = "M".concat(startInnerX, ",").concat(startInnerY, " A").concat(edgeRadius, ",").concat(edgeRadius, " 0 0 0 ").concat(startOuterX, ",").concat(startOuterY);
|
|
142
|
+
return path;
|
|
143
|
+
};
|
|
144
|
+
var getEndCaps = function (index, item) {
|
|
145
|
+
var _a, _b;
|
|
146
|
+
var edgeRadius = (_b = (_a = item.endEdgeRadius) !== null && _a !== void 0 ? _a : edgesRadius) !== null && _b !== void 0 ? _b : 1;
|
|
147
|
+
var additional = (item.isEndEdgeCurved || item.endEdgeRadius
|
|
148
|
+
? (radius - innerRadius) / (radius / 20)
|
|
149
|
+
: 0) -
|
|
150
|
+
strokeWidth / 2;
|
|
151
|
+
var _c = getCoordinates(index, -additional), endInnerX = _c.endInnerX, endInnerY = _c.endInnerY, endOuterX = _c.endOuterX, endOuterY = _c.endOuterY;
|
|
152
|
+
var path = "M".concat(endInnerX, ",").concat(endInnerY, " A").concat(edgeRadius, ",").concat(edgeRadius, " 0 0 1 ").concat(endOuterX, ",").concat(endOuterY);
|
|
153
|
+
return path;
|
|
154
|
+
};
|
|
155
|
+
var dInitial = data.map(function (item, index) {
|
|
156
|
+
return "".concat(initial || getInitial(item), " ").concat(donut ? getDonutPath(index, item) : getPath(index));
|
|
157
|
+
});
|
|
158
|
+
endAngleLocal = endAngle;
|
|
159
|
+
initial = '';
|
|
160
|
+
var dFinal = data.map(function (item, index) {
|
|
161
|
+
return "".concat(initial || getInitial(item), " ").concat(donut ? getDonutPath(index, item) : getPath(index));
|
|
162
|
+
});
|
|
163
|
+
return {
|
|
164
|
+
radius: radius,
|
|
165
|
+
total: total,
|
|
166
|
+
donut: donut,
|
|
167
|
+
strokeWidth: strokeWidth,
|
|
168
|
+
isAnimated: isAnimated,
|
|
169
|
+
animationDuration: animationDuration,
|
|
170
|
+
initial: initial,
|
|
171
|
+
dInitial: dInitial,
|
|
172
|
+
dFinal: dFinal,
|
|
173
|
+
isAnimating: isAnimating,
|
|
174
|
+
getStartCaps: getStartCaps,
|
|
175
|
+
getEndCaps: getEndCaps,
|
|
176
|
+
getTextCoordinates: getTextCoordinates
|
|
177
|
+
};
|
|
178
|
+
};
|
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
import { useEffect, useState } from 'react'
|
|
2
|
+
import { defaultAnimationDuration } from '../utils/constants'
|
|
3
|
+
import { PieChartPropsType, pieDataItem } from './types'
|
|
4
|
+
import { LabelsPosition } from '../utils/types'
|
|
5
|
+
|
|
6
|
+
interface IusePiePro {
|
|
7
|
+
radius: number
|
|
8
|
+
total: number
|
|
9
|
+
donut?: boolean
|
|
10
|
+
strokeWidth: number
|
|
11
|
+
isAnimated?: boolean
|
|
12
|
+
animationDuration: number
|
|
13
|
+
initial: string
|
|
14
|
+
dInitial: string[]
|
|
15
|
+
dFinal: string[]
|
|
16
|
+
isAnimating?: boolean
|
|
17
|
+
getStartCaps: (index: number, item: pieDataItem) => string
|
|
18
|
+
getEndCaps: (index: number, item: pieDataItem) => string
|
|
19
|
+
getTextCoordinates: (
|
|
20
|
+
index: number,
|
|
21
|
+
labelPos?: LabelsPosition
|
|
22
|
+
) => { x: number; y: number }
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export const usePiePro = (props: PieChartPropsType): IusePiePro => {
|
|
26
|
+
const {
|
|
27
|
+
data,
|
|
28
|
+
isAnimated,
|
|
29
|
+
donut,
|
|
30
|
+
semiCircle,
|
|
31
|
+
radius = 120,
|
|
32
|
+
innerRadius = radius / 2.5,
|
|
33
|
+
strokeWidth = 0,
|
|
34
|
+
edgesRadius = 0,
|
|
35
|
+
startAngle = 0
|
|
36
|
+
} = props
|
|
37
|
+
let endAngle = props.endAngle ?? startAngle + Math.PI * (semiCircle ? 1 : 2)
|
|
38
|
+
const total = data.reduce((acc, item) => acc + item.value, 0)
|
|
39
|
+
const animationDuration = props.animationDuration ?? defaultAnimationDuration
|
|
40
|
+
|
|
41
|
+
const [isAnimating, setIsAnimating] = useState(isAnimated)
|
|
42
|
+
|
|
43
|
+
useEffect(() => {
|
|
44
|
+
if (isAnimated) {
|
|
45
|
+
setIsAnimating(true)
|
|
46
|
+
setTimeout(() => setIsAnimating(false), animationDuration)
|
|
47
|
+
}
|
|
48
|
+
}, [])
|
|
49
|
+
|
|
50
|
+
let endAngleLocal = 0
|
|
51
|
+
|
|
52
|
+
const addValues = (index: number) => {
|
|
53
|
+
if (index < 0) return 0
|
|
54
|
+
let sum = 0
|
|
55
|
+
for (let i = 0; i <= index; i++) sum += data[i].value
|
|
56
|
+
return sum
|
|
57
|
+
}
|
|
58
|
+
const labelsPosition = props.labelsPosition
|
|
59
|
+
? props.labelsPosition
|
|
60
|
+
: donut || props.centerLabelComponent
|
|
61
|
+
? 'outward'
|
|
62
|
+
: 'mid'
|
|
63
|
+
|
|
64
|
+
const getCoordinates = (
|
|
65
|
+
index: number,
|
|
66
|
+
additionalValue?: number,
|
|
67
|
+
addInOnlyStart?: boolean,
|
|
68
|
+
addInOnlyEnd?: boolean
|
|
69
|
+
) => {
|
|
70
|
+
const addedValue =
|
|
71
|
+
addValues(index - 1) + (addInOnlyEnd ? 0 : additionalValue ?? 0)
|
|
72
|
+
let angle = (addedValue / total) * endAngleLocal + startAngle
|
|
73
|
+
const startInnerX = radius + Math.cos(angle) * innerRadius
|
|
74
|
+
const startInnerY = radius - Math.sin(angle) * innerRadius
|
|
75
|
+
const startOuterX = radius + Math.cos(angle) * radius
|
|
76
|
+
const startOuterY = radius - Math.sin(angle) * radius
|
|
77
|
+
|
|
78
|
+
const value =
|
|
79
|
+
addValues(index - 1) +
|
|
80
|
+
data[index].value +
|
|
81
|
+
(addInOnlyStart ? 0 : additionalValue ?? 0)
|
|
82
|
+
angle = (value / total) * endAngleLocal + startAngle
|
|
83
|
+
|
|
84
|
+
const endOuterX = radius + Math.cos(angle) * radius
|
|
85
|
+
const endOuterY = radius - Math.sin(angle) * radius
|
|
86
|
+
|
|
87
|
+
const endInnerX = radius + Math.cos(angle) * innerRadius
|
|
88
|
+
const endInnerY = radius - Math.sin(angle) * innerRadius
|
|
89
|
+
|
|
90
|
+
return {
|
|
91
|
+
startInnerX,
|
|
92
|
+
startInnerY,
|
|
93
|
+
startOuterX,
|
|
94
|
+
startOuterY,
|
|
95
|
+
endOuterX,
|
|
96
|
+
endOuterY,
|
|
97
|
+
endInnerX,
|
|
98
|
+
endInnerY
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const getTextCoordinates = (index: number, labelPos?: LabelsPosition) => {
|
|
103
|
+
const value = addValues(index - 1) + data[index].value / 2
|
|
104
|
+
const angle = (value / total) * endAngleLocal + startAngle
|
|
105
|
+
|
|
106
|
+
const labelPosition: LabelsPosition = labelPos || labelsPosition
|
|
107
|
+
|
|
108
|
+
let x =
|
|
109
|
+
radius +
|
|
110
|
+
Math.cos(angle) *
|
|
111
|
+
radius *
|
|
112
|
+
(labelPosition === 'inward'
|
|
113
|
+
? 0.25
|
|
114
|
+
: labelPosition === 'mid'
|
|
115
|
+
? 0.5
|
|
116
|
+
: labelPosition === 'outward'
|
|
117
|
+
? 0.75
|
|
118
|
+
: 1)
|
|
119
|
+
let y =
|
|
120
|
+
radius -
|
|
121
|
+
Math.sin(angle) *
|
|
122
|
+
radius *
|
|
123
|
+
(labelPosition === 'inward'
|
|
124
|
+
? 0.25
|
|
125
|
+
: labelPosition === 'mid'
|
|
126
|
+
? 0.5
|
|
127
|
+
: labelPosition === 'outward'
|
|
128
|
+
? 0.75
|
|
129
|
+
: 1)
|
|
130
|
+
|
|
131
|
+
return { x, y }
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
var initial = ''
|
|
135
|
+
const getInitial = (item: pieDataItem) => {
|
|
136
|
+
if (item.isStartEdgeCurved || item.startEdgeRadius) {
|
|
137
|
+
const { startInnerX, startInnerY, startOuterX, startOuterY } =
|
|
138
|
+
getCoordinates(0, (radius - innerRadius) / (radius / 20))
|
|
139
|
+
|
|
140
|
+
return `M${startInnerX},${startInnerY} L${startOuterX},${startOuterY} `
|
|
141
|
+
}
|
|
142
|
+
return `M${radius + innerRadius},${radius} h${radius - innerRadius} `
|
|
143
|
+
}
|
|
144
|
+
const getPath = (index: number) => {
|
|
145
|
+
const { endOuterX, endOuterY } = getCoordinates(index)
|
|
146
|
+
|
|
147
|
+
const isLargeArc = data[index].value / total > 0.5 ? 1 : 0
|
|
148
|
+
|
|
149
|
+
const arc = `A${
|
|
150
|
+
radius + (props.strokeWidth ?? 0) / 2
|
|
151
|
+
},${radius} 0 ${isLargeArc} 0 `
|
|
152
|
+
const path = `${arc} ${endOuterX}, ${endOuterY}
|
|
153
|
+
L${radius},${radius} `
|
|
154
|
+
|
|
155
|
+
initial = `M${radius},${radius} L${endOuterX},${endOuterY}`
|
|
156
|
+
|
|
157
|
+
return path
|
|
158
|
+
}
|
|
159
|
+
const getDonutPath = (index: number, item: pieDataItem) => {
|
|
160
|
+
const additionalForStart =
|
|
161
|
+
item.isStartEdgeCurved || item.startEdgeRadius
|
|
162
|
+
? (radius - innerRadius) / (radius / 20)
|
|
163
|
+
: 0
|
|
164
|
+
|
|
165
|
+
const additionalForEnd =
|
|
166
|
+
item.isEndEdgeCurved || item.endEdgeRadius
|
|
167
|
+
? (radius - innerRadius) / (radius / -20)
|
|
168
|
+
: 0
|
|
169
|
+
|
|
170
|
+
const cropAtEnd = !!(
|
|
171
|
+
index === data.length - 1 &&
|
|
172
|
+
(item.isEndEdgeCurved || item.endEdgeRadius)
|
|
173
|
+
)
|
|
174
|
+
const {
|
|
175
|
+
startInnerX,
|
|
176
|
+
startInnerY,
|
|
177
|
+
endOuterX,
|
|
178
|
+
endOuterY,
|
|
179
|
+
endInnerX,
|
|
180
|
+
endInnerY
|
|
181
|
+
} = getCoordinates(
|
|
182
|
+
index,
|
|
183
|
+
cropAtEnd ? additionalForEnd : additionalForStart,
|
|
184
|
+
!cropAtEnd,
|
|
185
|
+
cropAtEnd
|
|
186
|
+
)
|
|
187
|
+
|
|
188
|
+
const isLargeArc = data[index].value / total > 0.5 ? 1 : 0
|
|
189
|
+
|
|
190
|
+
const innerArc = `A${innerRadius},${innerRadius} 0 ${isLargeArc} 1 `
|
|
191
|
+
const outerArc = `A${
|
|
192
|
+
radius + (props.strokeWidth ?? 0) / 2
|
|
193
|
+
},${radius} 0 ${isLargeArc} 0 `
|
|
194
|
+
const path = `${outerArc} ${endOuterX}, ${endOuterY}
|
|
195
|
+
L${endInnerX},${endInnerY} M${endInnerX},${endInnerY} ${innerArc} ${startInnerX},${startInnerY}`
|
|
196
|
+
|
|
197
|
+
initial = `M${endInnerX},${endInnerY} L${endOuterX},${endOuterY} `
|
|
198
|
+
|
|
199
|
+
return path
|
|
200
|
+
}
|
|
201
|
+
const getStartCaps = (index: number, item: pieDataItem) => {
|
|
202
|
+
const edgeRadius = item.startEdgeRadius ?? edgesRadius ?? 1
|
|
203
|
+
const additional =
|
|
204
|
+
(item.isStartEdgeCurved || item.startEdgeRadius
|
|
205
|
+
? (radius - innerRadius) / (radius / 20)
|
|
206
|
+
: 0) +
|
|
207
|
+
strokeWidth / 2
|
|
208
|
+
const { startInnerX, startInnerY, startOuterX, startOuterY } =
|
|
209
|
+
getCoordinates(index, additional)
|
|
210
|
+
|
|
211
|
+
const path = `M${startInnerX},${startInnerY} A${edgeRadius},${edgeRadius} 0 0 0 ${startOuterX},${startOuterY}`
|
|
212
|
+
return path
|
|
213
|
+
}
|
|
214
|
+
const getEndCaps = (index: number, item: pieDataItem) => {
|
|
215
|
+
const edgeRadius = item.endEdgeRadius ?? edgesRadius ?? 1
|
|
216
|
+
const additional =
|
|
217
|
+
(item.isEndEdgeCurved || item.endEdgeRadius
|
|
218
|
+
? (radius - innerRadius) / (radius / 20)
|
|
219
|
+
: 0) -
|
|
220
|
+
strokeWidth / 2
|
|
221
|
+
const { endInnerX, endInnerY, endOuterX, endOuterY } = getCoordinates(
|
|
222
|
+
index,
|
|
223
|
+
-additional
|
|
224
|
+
)
|
|
225
|
+
|
|
226
|
+
const path = `M${endInnerX},${endInnerY} A${edgeRadius},${edgeRadius} 0 0 1 ${endOuterX},${endOuterY}`
|
|
227
|
+
return path
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
const dInitial = data.map(
|
|
231
|
+
(item, index) =>
|
|
232
|
+
`${initial || getInitial(item)} ${
|
|
233
|
+
donut ? getDonutPath(index, item) : getPath(index)
|
|
234
|
+
}`
|
|
235
|
+
)
|
|
236
|
+
|
|
237
|
+
endAngleLocal = endAngle
|
|
238
|
+
initial = ''
|
|
239
|
+
const dFinal = data.map(
|
|
240
|
+
(item, index) =>
|
|
241
|
+
`${initial || getInitial(item)} ${
|
|
242
|
+
donut ? getDonutPath(index, item) : getPath(index)
|
|
243
|
+
}`
|
|
244
|
+
)
|
|
245
|
+
|
|
246
|
+
return {
|
|
247
|
+
radius,
|
|
248
|
+
total,
|
|
249
|
+
donut,
|
|
250
|
+
strokeWidth,
|
|
251
|
+
isAnimated,
|
|
252
|
+
animationDuration,
|
|
253
|
+
initial,
|
|
254
|
+
dInitial,
|
|
255
|
+
dFinal,
|
|
256
|
+
isAnimating,
|
|
257
|
+
getStartCaps,
|
|
258
|
+
getEndCaps,
|
|
259
|
+
getTextCoordinates
|
|
260
|
+
}
|
|
261
|
+
}
|