@easyv/charts 1.10.9 → 1.10.10

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.
@@ -186,7 +186,7 @@ const getArc = (
186
186
  ...rest
187
187
  },
188
188
  series_,
189
- index
189
+ index,
190
190
  ) => {
191
191
  const series =
192
192
  series_.find((s) => s.fieldName == rest.data.s) ||
@@ -268,6 +268,7 @@ const Component = memo(
268
268
  current,
269
269
  } = {},
270
270
  order,
271
+ columnsSeries,
271
272
  series,
272
273
  animation: {
273
274
  on,
@@ -378,7 +379,7 @@ const Component = memo(
378
379
  padAngle: _padAngle,
379
380
  innerRadius,
380
381
  outerRadius: scaler(arc.value),
381
- })
382
+ }),
382
383
  );
383
384
  }
384
385
  return _legendDataWithPercent.map((arc, index) => ({
@@ -410,7 +411,7 @@ const Component = memo(
410
411
  type: "onClick",
411
412
  });
412
413
  },
413
- [onEvent]
414
+ [onEvent],
414
415
  );
415
416
 
416
417
  const onMouseEnter = useCallback(
@@ -423,7 +424,7 @@ const Component = memo(
423
424
  type: "onMouseEnter",
424
425
  });
425
426
  },
426
- [onEvent, triggerOnRelative, onEmit]
427
+ [onEvent, triggerOnRelative, onEmit],
427
428
  );
428
429
 
429
430
  const onMouseLeave = useCallback(
@@ -437,7 +438,7 @@ const Component = memo(
437
438
  type: "onMouseLeave",
438
439
  });
439
440
  },
440
- [onEvent]
441
+ [onEvent],
441
442
  );
442
443
 
443
444
  useLayoutEffect(() => {
@@ -557,7 +558,7 @@ const Component = memo(
557
558
  .innerRadius(centerRadius)
558
559
  .outerRadius(centerRadius)(value);
559
560
  const dashLength = Math.ceil(
560
- (Math.PI * centerRadius * 2) / _arcs.length
561
+ (Math.PI * centerRadius * 2) / _arcs.length,
561
562
  );
562
563
  const pie = getColorList(series.color);
563
564
  return (
@@ -600,7 +601,7 @@ const Component = memo(
600
601
  </defs>
601
602
  </Fragment>
602
603
  );
603
- }
604
+ },
604
605
  )}
605
606
  {label && (
606
607
  <RingLabel
@@ -649,6 +650,8 @@ const Component = memo(
649
650
  <Legend
650
651
  {...legend}
651
652
  height={chartHeight}
653
+ columnsSeries={columnsSeries}
654
+ data={data}
652
655
  series={_arcs.map((arc) => ({
653
656
  ...arc,
654
657
  percent: arc.percent.toFixed(legendPrecision),
@@ -697,7 +700,7 @@ const Component = memo(
697
700
  outerRadius,
698
701
  index: dataIndex,
699
702
  },
700
- index
703
+ index,
701
704
  ) => {
702
705
  const current = index == currentIndex;
703
706
  const prev = index == prevIndex.current;
@@ -706,14 +709,14 @@ const Component = memo(
706
709
  const fillOpacity = animateColor
707
710
  ? 1
708
711
  : current
709
- ? opacity / 100
710
- : 1;
712
+ ? opacity / 100
713
+ : 1;
711
714
  const deltaWidthen = offset * widthen;
712
715
  const deltaHeighten = offset * heighten;
713
716
  const path = arc
714
717
  .innerRadius(innerRadius + deltaWidthen)
715
718
  .outerRadius(outerRadius + deltaHeighten + deltaWidthen)(
716
- value
719
+ value,
717
720
  );
718
721
  const pie = getColorList(series.color);
719
722
  const currentPie = animateColor
@@ -726,15 +729,15 @@ const Component = memo(
726
729
  //let offsetWidth=decorate2.radiusWidth/2 + radiusWidthAdd/2; //当前文字需生成在装饰物内,故而半径需要减小
727
730
  let textArc = arc
728
731
  .innerRadius(
729
- outerRadius + (current ? gap : categoryText.gap)
732
+ outerRadius + (current ? gap : categoryText.gap),
730
733
  )
731
734
  .outerRadius(
732
- outerRadius + (current ? gap : categoryText.gap)
735
+ outerRadius + (current ? gap : categoryText.gap),
733
736
  )(value);
734
737
  let lastA = textArc.lastIndexOf("A");
735
738
  textPath = textArc.slice(
736
739
  0,
737
- lastA > 0 ? lastA : textArc.length
740
+ lastA > 0 ? lastA : textArc.length,
738
741
  ); //文字路径
739
742
  categoryTextStyle = current
740
743
  ? animateCTS
@@ -779,7 +782,7 @@ const Component = memo(
779
782
  .outerRadius(
780
783
  outerRadius +
781
784
  decorate2.radiusWidth +
782
- (current ? radiusWidthAdd : 0)
785
+ (current ? radiusWidthAdd : 0),
783
786
  )(value)}
784
787
  stroke={show ? color : "none"}
785
788
  strokeWidth={show ? strokeWidth : "0"}
@@ -843,7 +846,7 @@ const Component = memo(
843
846
  </defs>
844
847
  </Fragment>
845
848
  );
846
- }
849
+ },
847
850
  )}
848
851
  {label && (
849
852
  <Label
@@ -918,6 +921,8 @@ const Component = memo(
918
921
  <Legend
919
922
  {...legend}
920
923
  height={chartHeight}
924
+ data={data}
925
+ columnsSeries={columnsSeries}
921
926
  series={_arcs.map((arc) => ({
922
927
  ...arc,
923
928
  percent: arc.percent.toFixed(legendPrecision),
@@ -928,7 +933,7 @@ const Component = memo(
928
933
  />
929
934
  </div>
930
935
  );
931
- }
936
+ },
932
937
  );
933
938
 
934
939
  const Current = ({
@@ -979,7 +984,7 @@ const Current = ({
979
984
  //数据容错,当data都为零那么需要进行以下容错
980
985
  if (judge == 0) {
981
986
  _data.forEach((d) => {
982
- (d.percent = 0), (d.value = 0);
987
+ ((d.percent = 0), (d.value = 0));
983
988
  });
984
989
  }
985
990
 
@@ -1143,7 +1148,7 @@ const Label = ({
1143
1148
  }) => {
1144
1149
  const _arcs = useMemo(
1145
1150
  () => getDataWithPercent(arcs, precision),
1146
- [arcs, precision]
1151
+ [arcs, precision],
1147
1152
  );
1148
1153
  //数据做出容错
1149
1154
  if (judge == 0) {
@@ -1171,14 +1176,14 @@ const Label = ({
1171
1176
  outerRadius,
1172
1177
  index: actualIndex,
1173
1178
  },
1174
- index
1179
+ index,
1175
1180
  ) => {
1176
1181
  const [x, y] = arc.centroid();
1177
1182
  const midAngle = Math.atan2(y, x);
1178
1183
 
1179
1184
  const [x1, y1] = getCoord(
1180
1185
  midAngle,
1181
- maxRadius ? maxRadius : outerRadius
1186
+ maxRadius ? maxRadius : outerRadius,
1182
1187
  );
1183
1188
 
1184
1189
  const radius = (maxRadius ? maxRadius : outerRadius) + distance;
@@ -1223,8 +1228,8 @@ const Label = ({
1223
1228
  lineColor
1224
1229
  ? lineColor
1225
1230
  : type == "pure"
1226
- ? pure
1227
- : stops[0].color
1231
+ ? pure
1232
+ : stops[0].color
1228
1233
  }
1229
1234
  fill="none"
1230
1235
  />
@@ -1253,8 +1258,8 @@ const Label = ({
1253
1258
  align == "left"
1254
1259
  ? "flex-start"
1255
1260
  : align == "center"
1256
- ? "center"
1257
- : "flex-end",
1261
+ ? "center"
1262
+ : "flex-end",
1258
1263
  justifyContent: "center",
1259
1264
  }}
1260
1265
  >
@@ -1315,7 +1320,7 @@ const Label = ({
1315
1320
  </g>
1316
1321
  )
1317
1322
  );
1318
- }
1323
+ },
1319
1324
  )}
1320
1325
  </g>
1321
1326
  );
@@ -1376,7 +1381,7 @@ const RingLabel = ({
1376
1381
  }) => {
1377
1382
  const _arcs = useMemo(
1378
1383
  () => getDataWithPercent(arcs, precision),
1379
- [arcs, precision]
1384
+ [arcs, precision],
1380
1385
  );
1381
1386
 
1382
1387
  //数据做出容错
@@ -1406,14 +1411,14 @@ const RingLabel = ({
1406
1411
  outerRadius,
1407
1412
  index: actualIndex,
1408
1413
  },
1409
- index
1414
+ index,
1410
1415
  ) => {
1411
1416
  const [x, y] = arc.centroid();
1412
1417
  const midAngle = Math.atan2(y, x);
1413
1418
 
1414
1419
  const [x1, y1] = getCoord(
1415
1420
  midAngle,
1416
- maxRadius ? maxRadius : outerRadius
1421
+ maxRadius ? maxRadius : outerRadius,
1417
1422
  );
1418
1423
 
1419
1424
  const radius = (maxRadius ? maxRadius : outerRadius) + distance;
@@ -1456,8 +1461,8 @@ const RingLabel = ({
1456
1461
  lineColor
1457
1462
  ? lineColor
1458
1463
  : type == "pure"
1459
- ? pure
1460
- : stops[0].color
1464
+ ? pure
1465
+ : stops[0].color
1461
1466
  }
1462
1467
  fill="none"
1463
1468
  />
@@ -1546,7 +1551,7 @@ const RingLabel = ({
1546
1551
  </g>
1547
1552
  )
1548
1553
  );
1549
- }
1554
+ },
1550
1555
  )}
1551
1556
  </g>
1552
1557
  );
@@ -42,6 +42,48 @@ export const pieLegendFormatter = (series, props) => {
42
42
  translate: { x: percentX, y: percentY },
43
43
  },
44
44
  } = props;
45
+ const fieldColumnKeys = props.fieldColumnKeys ?? [];
46
+ const fieldsColumnWidths = props.fieldsColumnWidths ?? [];
47
+ //获取文本所占宽度
48
+ function getStringWidth(text, fontStyle = "14px sans-serif") {
49
+ const canvas = document.createElement("canvas");
50
+ const ctx = canvas.getContext("2d");
51
+ ctx.font = fontStyle;
52
+ return ctx.measureText(text).width;
53
+ }
54
+ const alignToJustify = (align) =>
55
+ align == "left" ? "flex-start" : align == "right" ? "flex-end" : "center";
56
+ const alignToTextAlign = (align) =>
57
+ align === "left" ? "left" : align === "right" ? "right" : "center";
58
+ if (fieldColumnKeys.length > 0) {
59
+ //处理除name、value、percent外的列
60
+ series.fieldsData = fieldColumnKeys
61
+ .map((key, fieldsColumnIndex) => {
62
+ if (!series.fields?.[key] || !series.data?.hasOwnProperty(key)) {
63
+ return null;
64
+ }
65
+ return {
66
+ ...series.fields[key],
67
+ value: series.data[key],
68
+ fieldsColumnIndex,
69
+ };
70
+ })
71
+ .filter(Boolean);
72
+ } else {
73
+ series.fieldsData = Object.entries(series.fields || {}).reduce(
74
+ (arr, [key, config]) => {
75
+ if (series.data.hasOwnProperty(key)) {
76
+ arr.push({
77
+ ...config,
78
+ value: series.data[key],
79
+ fieldsColumnIndex: arr.length,
80
+ });
81
+ }
82
+ return arr;
83
+ },
84
+ [],
85
+ );
86
+ }
45
87
  const {
46
88
  type: seriesColorType,
47
89
  pure,
@@ -56,6 +98,43 @@ export const pieLegendFormatter = (series, props) => {
56
98
  if (showName) columns.push(`${props.nameMaxWidth}px`);
57
99
  if (showValue) columns.push(`${props.valueMaxWidth + valueGap}px`);
58
100
  if (showPercent) columns.push(`${props.percentMaxWidth + percentGap}px`);
101
+ if (series.fieldsData.length > 0) {
102
+ //网格布局新增的各列宽度
103
+ series.fieldsData.forEach((item) => {
104
+ const idx = item.fieldsColumnIndex ?? 0;
105
+ const measured = getStringWidth(
106
+ item.value,
107
+ `${item.font.fontSize}px ${item.font.fontFamily}`,
108
+ );
109
+ const suf = item.suffix;
110
+ const suffixWidth =
111
+ suf?.show && suf?.text != null && String(suf.text) !== ""
112
+ ? getStringWidth(
113
+ String(suf.text),
114
+ `${suf.fontSize ?? item.font?.fontSize}px ${item.font.fontFamily}`,
115
+ )
116
+ : 0;
117
+ const tx = Math.max(0, Number(item.translate?.x) || 0);
118
+ const stx =
119
+ suf?.show && suf?.text != null && String(suf.text) !== ""
120
+ ? Math.max(0, Number(suf.translate?.x) || 0)
121
+ : 0;
122
+ const flowW = measured + suffixWidth + tx + stx;
123
+ let colW;
124
+ if (fieldsColumnWidths.length > idx && fieldsColumnWidths[idx] > 0) {
125
+ colW = Math.max(
126
+ Number(fieldsColumnWidths[idx]) || 0,
127
+ Number(item.maxWidth) || 0,
128
+ flowW,
129
+ );
130
+ } else {
131
+ const fromConfig = Number(item.maxWidth) || 0;
132
+ colW = Math.max(flowW, fromConfig);
133
+ }
134
+ columns.push(`${colW}px`);
135
+ });
136
+ }
137
+
59
138
  return (
60
139
  <>
61
140
  {icon && (
@@ -76,6 +155,7 @@ export const pieLegendFormatter = (series, props) => {
76
155
  style={{
77
156
  width: `calc( 100% + ${textMarginLeft + valueGap + percentGap}px )`,
78
157
  gridTemplateColumns: columns.join(" "),
158
+ overflowX: "visible",
79
159
  }}
80
160
  >
81
161
  {showName && (
@@ -101,18 +181,8 @@ export const pieLegendFormatter = (series, props) => {
101
181
  transform: `translate(${valueX}px,${valueY}px)`,
102
182
  color: valueSameColor ? _color : valueFont.color,
103
183
  alignItems: "center",
104
- justifyContent:
105
- valueAlign == "left"
106
- ? "flex-start"
107
- : valueAlign == "right"
108
- ? "flex-end"
109
- : "center",
110
- textAlign:
111
- valueAlign === "left"
112
- ? "left"
113
- : valueAlign === "right"
114
- ? "right"
115
- : "center",
184
+ justifyContent: alignToJustify(valueAlign ?? "center"),
185
+ textAlign: alignToTextAlign(valueAlign),
116
186
  }}
117
187
  >
118
188
  <span>
@@ -134,29 +204,69 @@ export const pieLegendFormatter = (series, props) => {
134
204
  {showPercent && (
135
205
  <span
136
206
  style={{
207
+ display: "flex",
137
208
  whiteSpace: "nowrap",
138
209
  ...getFontStyle(percentFont),
139
210
  marginLeft: percentGap,
140
211
  transform: `translate(${percentX}px,${percentY}px)`,
141
212
  color: percentSameColor ? _color : percentFont.color,
142
213
  alignItems: "center",
143
- justifyContent:
144
- percentAlign == "left"
145
- ? "flex-start"
146
- : percentAlign == "right"
147
- ? "flex-end"
148
- : "center",
149
- textAlign:
150
- percentAlign === "left"
151
- ? "left"
152
- : percentAlign === "right"
153
- ? "right"
154
- : "center",
214
+ justifyContent: alignToJustify(percentAlign),
215
+ textAlign: alignToTextAlign(percentAlign),
155
216
  }}
156
217
  >
157
218
  {percent + "%"}
158
219
  </span>
159
220
  )}
221
+ {series.fieldsData?.map(
222
+ (
223
+ item,
224
+ index, //渲染网格布局新增的各列
225
+ ) => (
226
+ <span
227
+ key={fieldColumnKeys[item.fieldsColumnIndex ?? index] ?? index}
228
+ style={{
229
+ display: "flex",
230
+ boxSizing: "border-box",
231
+ width: "100%",
232
+ minWidth: 0,
233
+ alignItems: "center",
234
+ justifyContent: alignToJustify(item.align ?? "center"),
235
+ textAlign: alignToTextAlign(item.align ?? "center"),
236
+ overflow: "visible",
237
+ ...getFontStyle(item.font),
238
+ color: item.sameColor ? _color : item.font.color,
239
+ }}
240
+ >
241
+ <span
242
+ style={{
243
+ display: "inline-flex",
244
+ alignItems: "center",
245
+ flexWrap: "nowrap",
246
+ whiteSpace: "nowrap",
247
+ marginLeft: item.translate?.x ?? 0,
248
+ marginTop: item.translate?.y ?? 0,
249
+ }}
250
+ >
251
+ <span style={{ whiteSpace: "nowrap" }}>{item.value}</span>
252
+ {item.suffix?.show &&
253
+ item.suffix?.text != null &&
254
+ String(item.suffix.text) !== "" && (
255
+ <span
256
+ style={{
257
+ whiteSpace: "nowrap",
258
+ fontSize: item.suffix.fontSize,
259
+ marginLeft: item.suffix.translate?.x ?? 0,
260
+ marginTop: item.suffix.translate?.y ?? 0,
261
+ }}
262
+ >
263
+ {item.suffix.text}
264
+ </span>
265
+ )}
266
+ </span>
267
+ </span>
268
+ ),
269
+ )}
160
270
  </div>
161
271
  </>
162
272
  );