@chainplatform/charts 0.0.2 → 0.0.4
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/DonutChart.js +71 -111
- package/src/LineChart.js +4 -2
package/package.json
CHANGED
package/src/DonutChart.js
CHANGED
|
@@ -13,6 +13,7 @@ class DonutChart extends PureComponent {
|
|
|
13
13
|
label: PropTypes.string,
|
|
14
14
|
value: PropTypes.number,
|
|
15
15
|
color: PropTypes.string,
|
|
16
|
+
total: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
|
|
16
17
|
})
|
|
17
18
|
).isRequired,
|
|
18
19
|
size: PropTypes.number,
|
|
@@ -50,15 +51,11 @@ class DonutChart extends PureComponent {
|
|
|
50
51
|
|
|
51
52
|
constructor(props) {
|
|
52
53
|
super(props);
|
|
53
|
-
|
|
54
|
-
this.state = {
|
|
55
|
-
tooltip: null,
|
|
56
|
-
};
|
|
54
|
+
this.state = { tooltip: null };
|
|
57
55
|
}
|
|
58
56
|
|
|
59
57
|
polarToCartesian = (cx, cy, radius, angle) => {
|
|
60
58
|
const rad = ((angle - 90) * Math.PI) / 180;
|
|
61
|
-
|
|
62
59
|
return {
|
|
63
60
|
x: cx + radius * Math.cos(rad),
|
|
64
61
|
y: cy + radius * Math.sin(rad),
|
|
@@ -68,7 +65,6 @@ class DonutChart extends PureComponent {
|
|
|
68
65
|
describeArc = (cx, cy, radius, startAngle, endAngle) => {
|
|
69
66
|
const start = this.polarToCartesian(cx, cy, radius, endAngle);
|
|
70
67
|
const end = this.polarToCartesian(cx, cy, radius, startAngle);
|
|
71
|
-
|
|
72
68
|
const largeArcFlag = endAngle - startAngle <= 180 ? '0' : '1';
|
|
73
69
|
|
|
74
70
|
return [
|
|
@@ -92,8 +88,8 @@ class DonutChart extends PureComponent {
|
|
|
92
88
|
x: point.x,
|
|
93
89
|
y: point.y,
|
|
94
90
|
label: item.label,
|
|
95
|
-
value: item.total,
|
|
96
|
-
percent
|
|
91
|
+
value: item.total ?? item.value,
|
|
92
|
+
percent,
|
|
97
93
|
color: item.color,
|
|
98
94
|
},
|
|
99
95
|
});
|
|
@@ -101,6 +97,45 @@ class DonutChart extends PureComponent {
|
|
|
101
97
|
|
|
102
98
|
hideTooltip = () => { this.setState({ tooltip: null }); };
|
|
103
99
|
|
|
100
|
+
renderSegment = ({ item, index, center, radius, strokeWidth, segmentStartAngle, segmentEndAngle, sweepAngle, roundedPercent, percentPoint, arcPath }) => {
|
|
101
|
+
const eventProps = {
|
|
102
|
+
onPress: Platform.OS !== 'web' && this.props.enableTooltip ? () => this.showTooltip(item, roundedPercent, percentPoint) : undefined,
|
|
103
|
+
onPressOut: Platform.OS !== 'web' ? this.hideTooltip : undefined,
|
|
104
|
+
onMouseEnter: Platform.OS === 'web' && this.props.enableTooltip ? () => this.showTooltip(item, roundedPercent, percentPoint) : undefined,
|
|
105
|
+
onMouseLeave: Platform.OS === 'web' ? this.hideTooltip : undefined,
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
if (sweepAngle >= 359.99) {
|
|
109
|
+
return (
|
|
110
|
+
<Circle
|
|
111
|
+
key={`segment-full-${index}`}
|
|
112
|
+
cx={center}
|
|
113
|
+
cy={center}
|
|
114
|
+
r={radius}
|
|
115
|
+
stroke={item.color}
|
|
116
|
+
strokeWidth={strokeWidth}
|
|
117
|
+
fill="transparent"
|
|
118
|
+
strokeLinecap="butt"
|
|
119
|
+
{...eventProps}
|
|
120
|
+
/>
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
if (segmentEndAngle <= segmentStartAngle) return null;
|
|
125
|
+
|
|
126
|
+
return (
|
|
127
|
+
<Path
|
|
128
|
+
key={`segment-path-${index}`}
|
|
129
|
+
d={arcPath}
|
|
130
|
+
stroke={item.color}
|
|
131
|
+
strokeWidth={strokeWidth}
|
|
132
|
+
fill="transparent"
|
|
133
|
+
strokeLinecap="butt"
|
|
134
|
+
{...eventProps}
|
|
135
|
+
/>
|
|
136
|
+
);
|
|
137
|
+
};
|
|
138
|
+
|
|
104
139
|
render() {
|
|
105
140
|
const {
|
|
106
141
|
data,
|
|
@@ -124,16 +159,11 @@ class DonutChart extends PureComponent {
|
|
|
124
159
|
|
|
125
160
|
if (!data?.length) return null;
|
|
126
161
|
|
|
127
|
-
const validData = data.filter(
|
|
128
|
-
item => item?.value && item.value > 0
|
|
129
|
-
);
|
|
162
|
+
const validData = data.filter(item => Number(item?.value) > 0);
|
|
130
163
|
|
|
131
164
|
if (!validData.length) return null;
|
|
132
165
|
|
|
133
|
-
const total = validData.reduce(
|
|
134
|
-
(sum, item) => sum + item.value,
|
|
135
|
-
0
|
|
136
|
-
);
|
|
166
|
+
const total = validData.reduce((sum, item) => sum + Number(item.value || 0), 0);
|
|
137
167
|
|
|
138
168
|
if (total <= 0) return null;
|
|
139
169
|
|
|
@@ -148,108 +178,46 @@ class DonutChart extends PureComponent {
|
|
|
148
178
|
<Circle cx={center} cy={center} r={radius} stroke={backgroundColor} strokeWidth={strokeWidth} fill="transparent" />
|
|
149
179
|
|
|
150
180
|
{validData.map((item, index) => {
|
|
151
|
-
const
|
|
181
|
+
const value = Number(item.value || 0);
|
|
182
|
+
const percent = value / total;
|
|
152
183
|
const sweepAngle = percent * 360;
|
|
153
|
-
|
|
154
|
-
const
|
|
155
|
-
|
|
156
|
-
const segmentEndAngle = currentAngle + sweepAngle -
|
|
157
|
-
|
|
184
|
+
const isFullCircle = sweepAngle >= 359.99;
|
|
185
|
+
const gap = isFullCircle ? 0 : segmentGap;
|
|
186
|
+
const segmentStartAngle = currentAngle + gap / 2;
|
|
187
|
+
const segmentEndAngle = currentAngle + sweepAngle - gap / 2;
|
|
158
188
|
const middleAngle = currentAngle + sweepAngle / 2;
|
|
159
189
|
|
|
160
190
|
currentAngle += sweepAngle;
|
|
161
191
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
const arcPath = this.describeArc(
|
|
167
|
-
center,
|
|
168
|
-
center,
|
|
169
|
-
radius,
|
|
170
|
-
segmentStartAngle,
|
|
171
|
-
segmentEndAngle
|
|
172
|
-
);
|
|
173
|
-
|
|
174
|
-
const percentPoint = this.polarToCartesian(
|
|
175
|
-
center,
|
|
176
|
-
center,
|
|
177
|
-
radius,
|
|
178
|
-
middleAngle
|
|
179
|
-
);
|
|
180
|
-
|
|
181
|
-
const innerPoint = this.polarToCartesian(
|
|
182
|
-
center,
|
|
183
|
-
center,
|
|
184
|
-
radius - strokeWidth / 2 - innerOffset,
|
|
185
|
-
middleAngle
|
|
186
|
-
);
|
|
187
|
-
|
|
192
|
+
const arcPath = this.describeArc(center, center, radius, segmentStartAngle, segmentEndAngle);
|
|
193
|
+
const percentPoint = this.polarToCartesian(center, center, radius, middleAngle);
|
|
194
|
+
const innerPoint = this.polarToCartesian(center, center, radius - strokeWidth / 2 - innerOffset, middleAngle);
|
|
188
195
|
const roundedPercent = Math.round(percent * 100);
|
|
189
196
|
|
|
190
197
|
return (
|
|
191
198
|
<React.Fragment key={`segment-${index}`}>
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
)
|
|
206
|
-
: undefined
|
|
207
|
-
}
|
|
208
|
-
onPressOut={
|
|
209
|
-
Platform.OS !== 'web'
|
|
210
|
-
? this.hideTooltip
|
|
211
|
-
: undefined
|
|
212
|
-
}
|
|
213
|
-
onMouseEnter={
|
|
214
|
-
Platform.OS === 'web' && enableTooltip
|
|
215
|
-
? () =>
|
|
216
|
-
this.showTooltip(
|
|
217
|
-
item,
|
|
218
|
-
roundedPercent,
|
|
219
|
-
percentPoint
|
|
220
|
-
)
|
|
221
|
-
: undefined
|
|
222
|
-
}
|
|
223
|
-
onMouseLeave={
|
|
224
|
-
Platform.OS === 'web'
|
|
225
|
-
? this.hideTooltip
|
|
226
|
-
: undefined
|
|
227
|
-
}
|
|
228
|
-
/>
|
|
199
|
+
{this.renderSegment({
|
|
200
|
+
item,
|
|
201
|
+
index,
|
|
202
|
+
center,
|
|
203
|
+
radius,
|
|
204
|
+
strokeWidth,
|
|
205
|
+
segmentStartAngle,
|
|
206
|
+
segmentEndAngle,
|
|
207
|
+
sweepAngle,
|
|
208
|
+
roundedPercent,
|
|
209
|
+
percentPoint,
|
|
210
|
+
arcPath,
|
|
211
|
+
})}
|
|
229
212
|
|
|
230
213
|
{showPercent && (
|
|
231
|
-
<SvgText
|
|
232
|
-
x={percentPoint.x}
|
|
233
|
-
y={percentPoint.y}
|
|
234
|
-
fill={percentColor}
|
|
235
|
-
fontSize={percentFontSize}
|
|
236
|
-
fontWeight="600"
|
|
237
|
-
textAnchor="middle"
|
|
238
|
-
alignmentBaseline="middle"
|
|
239
|
-
>
|
|
214
|
+
<SvgText x={percentPoint.x} y={percentPoint.y} fill={percentColor} fontSize={percentFontSize} fontWeight="600" textAnchor="middle" alignmentBaseline="middle">
|
|
240
215
|
{`${roundedPercent}%`}
|
|
241
216
|
</SvgText>
|
|
242
217
|
)}
|
|
243
218
|
|
|
244
|
-
{showInnerLabels && (
|
|
245
|
-
<SvgText
|
|
246
|
-
x={innerPoint.x}
|
|
247
|
-
y={innerPoint.y}
|
|
248
|
-
fill={item.color}
|
|
249
|
-
fontSize={labelFontSize}
|
|
250
|
-
textAnchor="middle"
|
|
251
|
-
alignmentBaseline="middle"
|
|
252
|
-
>
|
|
219
|
+
{showInnerLabels && !!item.label && (
|
|
220
|
+
<SvgText x={innerPoint.x} y={innerPoint.y} fill={item.color} fontSize={labelFontSize} textAnchor="middle" alignmentBaseline="middle">
|
|
253
221
|
{item.label}
|
|
254
222
|
</SvgText>
|
|
255
223
|
)}
|
|
@@ -258,15 +226,7 @@ class DonutChart extends PureComponent {
|
|
|
258
226
|
})}
|
|
259
227
|
|
|
260
228
|
{!!centerContent && (
|
|
261
|
-
<SvgText
|
|
262
|
-
x={center}
|
|
263
|
-
y={center}
|
|
264
|
-
fontSize={contentFontSize}
|
|
265
|
-
fontWeight="600"
|
|
266
|
-
fill="#333"
|
|
267
|
-
textAnchor="middle"
|
|
268
|
-
alignmentBaseline="middle"
|
|
269
|
-
>
|
|
229
|
+
<SvgText x={center} y={center} fontSize={contentFontSize} fontWeight="600" fill="#333" textAnchor="middle" alignmentBaseline="middle">
|
|
270
230
|
{centerContent}
|
|
271
231
|
</SvgText>
|
|
272
232
|
)}
|
package/src/LineChart.js
CHANGED
|
@@ -31,7 +31,7 @@ class LineChart extends PureComponent {
|
|
|
31
31
|
};
|
|
32
32
|
|
|
33
33
|
render() {
|
|
34
|
-
const { enableTooltip, data, width, height, strokeColor, strokeWidth, showDots, dotRadius, touchRadius, paddingHorizontal, paddingVertical, backgroundColor } = this.props;
|
|
34
|
+
const { enableTooltip, data, width, height, fillColor, strokeColor, strokeWidth, showDots, dotRadius, touchRadius, paddingHorizontal, paddingVertical, backgroundColor } = this.props;
|
|
35
35
|
const { tooltip } = this.state;
|
|
36
36
|
|
|
37
37
|
if (!data?.length) return null;
|
|
@@ -66,7 +66,7 @@ class LineChart extends PureComponent {
|
|
|
66
66
|
|
|
67
67
|
{points.map((point, index) => (
|
|
68
68
|
<React.Fragment key={`point-${index}`}>
|
|
69
|
-
{showDots && <Circle cx={point.x} cy={point.y} r={dotRadius} fill=
|
|
69
|
+
{showDots && <Circle cx={point.x} cy={point.y} r={dotRadius} fill={fillColor} stroke={strokeColor} strokeWidth={setSize(2)} />}
|
|
70
70
|
<Circle
|
|
71
71
|
cx={point.x}
|
|
72
72
|
cy={point.y}
|
|
@@ -93,6 +93,7 @@ LineChart.propTypes = {
|
|
|
93
93
|
width: PropTypes.number,
|
|
94
94
|
height: PropTypes.number,
|
|
95
95
|
strokeColor: PropTypes.string,
|
|
96
|
+
fillColor: PropTypes.string,
|
|
96
97
|
strokeWidth: PropTypes.number,
|
|
97
98
|
showDots: PropTypes.bool,
|
|
98
99
|
dotRadius: PropTypes.number,
|
|
@@ -108,6 +109,7 @@ LineChart.defaultProps = {
|
|
|
108
109
|
width: setSize(160),
|
|
109
110
|
height: setSize(60),
|
|
110
111
|
strokeColor: '#5B7CFA',
|
|
112
|
+
fillColor: '#FFFFFF',
|
|
111
113
|
strokeWidth: setSize(2),
|
|
112
114
|
showDots: true,
|
|
113
115
|
dotRadius: setSize(3),
|