@easyv/charts 1.4.25 → 1.4.28

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.
Files changed (91) hide show
  1. package/.babelrc +8 -8
  2. package/.husky/commit-msg +3 -3
  3. package/CHANGELOG.md +18 -18
  4. package/commitlint.config.js +1 -1
  5. package/lib/components/AnimateData.js +8 -16
  6. package/lib/components/Axis.js +86 -133
  7. package/lib/components/Background.js +18 -26
  8. package/lib/components/Band.js +72 -98
  9. package/lib/components/BaseLine.js +33 -46
  10. package/lib/components/Brush.js +29 -46
  11. package/lib/components/Carousel.js +13 -40
  12. package/lib/components/CartesianChart.js +98 -146
  13. package/lib/components/Chart.js +23 -36
  14. package/lib/components/ChartContainer.js +18 -27
  15. package/lib/components/ConicalGradient.js +56 -89
  16. package/lib/components/Control.js +12 -28
  17. package/lib/components/ExtentData.js +9 -17
  18. package/lib/components/FilterData.js +16 -27
  19. package/lib/components/Indicator.js +23 -30
  20. package/lib/components/Label.js +96 -126
  21. package/lib/components/Legend.js +41 -66
  22. package/lib/components/Lighter.js +21 -50
  23. package/lib/components/Line.js +39 -59
  24. package/lib/components/LinearGradient.js +16 -22
  25. package/lib/components/Mapping.js +9 -34
  26. package/lib/components/Marquee.js +14 -30
  27. package/lib/components/PieChart.js +468 -489
  28. package/lib/components/StackData.js +8 -18
  29. package/lib/components/StereoBar.js +65 -105
  30. package/lib/components/TextOverflow.js +8 -21
  31. package/lib/components/Tooltip.js +41 -55
  32. package/lib/components/index.js +7 -28
  33. package/lib/components/pieTooltip.js +133 -0
  34. package/lib/context/index.js +0 -2
  35. package/lib/css/index.module.css +42 -42
  36. package/lib/css/piechart.module.css +26 -26
  37. package/lib/element/ConicGradient.js +29 -35
  38. package/lib/element/Line.js +9 -13
  39. package/lib/element/index.js +0 -2
  40. package/lib/formatter/index.js +0 -2
  41. package/lib/formatter/legend.js +30 -41
  42. package/lib/hooks/index.js +0 -9
  43. package/lib/hooks/useAiData.js +12 -20
  44. package/lib/hooks/useAnimateData.js +8 -21
  45. package/lib/hooks/useAxes.js +67 -117
  46. package/lib/hooks/useCarouselAxisX.js +27 -60
  47. package/lib/hooks/useExtentData.js +14 -46
  48. package/lib/hooks/useFilterData.js +13 -34
  49. package/lib/hooks/useStackData.js +12 -35
  50. package/lib/hooks/useTooltip.js +36 -53
  51. package/lib/index.js +0 -15
  52. package/lib/utils/index.js +95 -247
  53. package/package.json +55 -55
  54. package/src/components/Background.tsx +61 -61
  55. package/src/components/Band.tsx +274 -274
  56. package/src/components/Brush.js +159 -159
  57. package/src/components/CartesianChart.js +1 -1
  58. package/src/components/Chart.js +99 -99
  59. package/src/components/ChartContainer.tsx +71 -71
  60. package/src/components/ConicalGradient.js +258 -258
  61. package/src/components/Control.jsx +51 -51
  62. package/src/components/ExtentData.js +17 -17
  63. package/src/components/Indicator.js +61 -61
  64. package/src/components/Label.js +275 -275
  65. package/src/components/Legend.js +165 -165
  66. package/src/components/Lighter.jsx +173 -173
  67. package/src/components/Line.js +150 -150
  68. package/src/components/LinearGradient.js +29 -29
  69. package/src/components/Marquee.tsx +1 -1
  70. package/src/components/PieChart.js +404 -260
  71. package/src/components/PieTooltip.jsx +134 -0
  72. package/src/components/StereoBar.tsx +307 -307
  73. package/src/components/index.js +59 -57
  74. package/src/context/index.js +2 -2
  75. package/src/css/index.module.css +42 -42
  76. package/src/css/piechart.module.css +26 -26
  77. package/src/element/ConicGradient.jsx +55 -55
  78. package/src/element/Line.tsx +33 -33
  79. package/src/element/index.ts +3 -3
  80. package/src/formatter/index.js +1 -1
  81. package/src/formatter/legend.js +92 -92
  82. package/src/hooks/index.js +20 -20
  83. package/src/hooks/useAnimateData.ts +67 -67
  84. package/src/hooks/useCarouselAxisX.js +1 -1
  85. package/src/hooks/useFilterData.js +72 -72
  86. package/src/hooks/useStackData.js +101 -101
  87. package/src/hooks/useTooltip.ts +100 -100
  88. package/src/index.js +6 -6
  89. package/src/types/index.d.ts +67 -67
  90. package/src/utils/index.js +757 -757
  91. package/tsconfig.json +23 -23
@@ -11,21 +11,30 @@ import React, {
11
11
  useContext,
12
12
  useLayoutEffect,
13
13
  Fragment,
14
- } from 'react';
15
- import { ChartContainer, Carousel, Legend, ConicalGradient, Mapping, TextOverflow } from '.';
16
- import { chartContext } from '../context';
14
+ } from "react";
15
+ import {
16
+ ChartContainer,
17
+ Carousel,
18
+ Legend,
19
+ ConicalGradient,
20
+ Mapping,
21
+ TextOverflow,
22
+ } from ".";
23
+ import { chartContext } from "../context";
17
24
  import {
18
25
  getFontStyle,
19
26
  sortPie,
20
27
  getDataWithPercent,
21
28
  getColorList,
22
- } from '../utils';
23
- import { pie, arc, extent, scaleLinear } from 'd3v7';
24
- import { animate, linear } from 'popmotion';
25
- import LinearGradient from './LinearGradient';
26
- import { pieLegendFormatter as legendFormatter } from '../formatter';
27
- import ringCss from '../css/piechart.module.css';
28
- import { useAiDataOfPie } from '../hooks';
29
+ } from "../utils";
30
+ import { pie, arc, extent, scaleLinear } from "d3v7";
31
+ import { animate, linear } from "popmotion";
32
+ import LinearGradient from "./LinearGradient";
33
+ import { pieLegendFormatter as legendFormatter } from "../formatter";
34
+ import ringCss from "../css/piechart.module.css";
35
+ import { useAiDataOfPie } from "../hooks";
36
+ import { PieTooltip } from "./PieTooltip";
37
+ import { toFixed } from '@easyv/utils/lib/common/utils';
29
38
 
30
39
  const PI = Math.PI;
31
40
 
@@ -34,7 +43,7 @@ const defaultChart = {
34
43
  innerRadius: 0,
35
44
  cornerRadius: 0,
36
45
  rose: false,
37
- roseType: 'radius',
46
+ roseType: "radius",
38
47
  baseRadius: 0,
39
48
  padAngle: 0,
40
49
  };
@@ -42,14 +51,14 @@ const defaultAngle = { startAngle: 0, endAngle: 360, antiClockwise: false };
42
51
 
43
52
  const nameDy = (showValue, showPercent, mode, dir) => {
44
53
  if (showValue || showPercent) {
45
- if (mode == 'vertical') {
46
- return dir == 1 ? '1.1em' : '-2.6em';
54
+ if (mode == "vertical") {
55
+ return dir == 1 ? "1.1em" : "-2.6em";
47
56
  } else {
48
57
  return 0;
49
58
  }
50
59
  } else {
51
- if (mode == 'vertical') {
52
- return dir * 1.1 + 'em';
60
+ if (mode == "vertical") {
61
+ return dir * 1.1 + "em";
53
62
  } else {
54
63
  return 0;
55
64
  }
@@ -57,14 +66,14 @@ const nameDy = (showValue, showPercent, mode, dir) => {
57
66
  };
58
67
  const valueDy = (value1, mode, dir) => {
59
68
  if (value1) {
60
- if (mode == 'vertical') {
61
- return '1.5em';
69
+ if (mode == "vertical") {
70
+ return "1.5em";
62
71
  } else {
63
72
  return 0;
64
73
  }
65
74
  } else {
66
- if (mode == 'vertical') {
67
- return dir == 1 ? '1.1em' : '-1.1em';
75
+ if (mode == "vertical") {
76
+ return dir == 1 ? "1.1em" : "-1.1em";
68
77
  } else {
69
78
  return 0;
70
79
  }
@@ -76,14 +85,14 @@ const percentDy_ = (showName, showValue, mode, dir) => {
76
85
  return 0;
77
86
  }
78
87
  if (showName) {
79
- if (mode == 'vertical') {
80
- return '1.5em';
88
+ if (mode == "vertical") {
89
+ return "1.5em";
81
90
  } else {
82
91
  return 0;
83
92
  }
84
93
  } else {
85
- if (mode == 'vertical') {
86
- return dir * 1.1 + 'em';
94
+ if (mode == "vertical") {
95
+ return dir * 1.1 + "em";
87
96
  } else {
88
97
  return 0;
89
98
  }
@@ -92,13 +101,13 @@ const percentDy_ = (showName, showValue, mode, dir) => {
92
101
 
93
102
  const percentX = (showName, showValue, mode, x) => {
94
103
  if (showValue) {
95
- return '';
104
+ return "";
96
105
  }
97
106
  if (showName) {
98
- if (mode == 'vertical') {
107
+ if (mode == "vertical") {
99
108
  return x;
100
109
  } else {
101
- return '';
110
+ return "";
102
111
  }
103
112
  } else {
104
113
  return x;
@@ -107,13 +116,13 @@ const percentX = (showName, showValue, mode, x) => {
107
116
 
108
117
  const percentDx = (showName, showValue, mode) => {
109
118
  if (showValue) {
110
- return '0.5em';
119
+ return "0.5em";
111
120
  }
112
121
  if (showName) {
113
- if (mode == 'vertical') {
122
+ if (mode == "vertical") {
114
123
  return 0;
115
124
  } else {
116
- return '0.5em';
125
+ return "0.5em";
117
126
  }
118
127
  } else {
119
128
  return 0;
@@ -125,8 +134,8 @@ const percentDy = (showName, showValue, mode) => {
125
134
  return 0;
126
135
  }
127
136
  if (showName) {
128
- if (mode == 'vertical') {
129
- return '1.5em';
137
+ if (mode == "vertical") {
138
+ return "1.5em";
130
139
  } else {
131
140
  return 0;
132
141
  }
@@ -137,12 +146,12 @@ const percentDy = (showName, showValue, mode) => {
137
146
 
138
147
  const valueDx = (showName, mode) => {
139
148
  if (!showName) {
140
- return '';
149
+ return "";
141
150
  }
142
- if (mode == 'vertical') {
143
- return '';
151
+ if (mode == "vertical") {
152
+ return "";
144
153
  } else {
145
- return '0.5em';
154
+ return "0.5em";
146
155
  }
147
156
  };
148
157
 
@@ -179,10 +188,12 @@ const getArc = (
179
188
  series_,
180
189
  index
181
190
  ) => {
182
- const series = series_.find(s=>s.fieldName==rest.data.s) || series_[index%series_.length];
191
+ const series =
192
+ series_.find((s) => s.fieldName == rest.data.s) ||
193
+ series_[index % series_.length];
183
194
  return {
184
195
  ...rest,
185
- type: 'pie',
196
+ type: "pie",
186
197
  fieldName: series.fieldName,
187
198
  displayName: series.displayName || rest.data.s,
188
199
  series: series,
@@ -195,7 +206,7 @@ const getArc = (
195
206
  .startAngle(startAngle)
196
207
  .endAngle(endAngle)
197
208
  .padAngle(padAngle),
198
- }
209
+ };
199
210
  };
200
211
 
201
212
  const getCircleScale = ({ count, color, width, length } = tick, radius) => {
@@ -270,13 +281,15 @@ const Component = memo(
270
281
  },
271
282
  rotate = 0,
272
283
  },
284
+ tooltip = {},
273
285
  },
286
+ config,
274
287
  state: { currentIndex, trigger },
275
288
  onEvent,
276
289
  hoverEvent,
277
- data:originData = [],
290
+ data: originData = [],
278
291
  }) => {
279
- const data =originData.map(d=>({...d,y:d.y<0?0:d.y}));
292
+ const data = originData.map((d) => ({ ...d, y: d.y < 0 ? 0 : d.y }));
280
293
  const prevIndex = useRef(null);
281
294
  const { precision: legendPrecision } = legend.config.percent;
282
295
  const {
@@ -303,10 +316,10 @@ const Component = memo(
303
316
  const arcsFunc = pie()
304
317
  .startAngle((startAngle * PI) / 180)
305
318
  .endAngle((endAngle * PI) / 180)
306
- .value((d) => d.y==0?1:d.y);
319
+ .value((d) => (d.y == 0 ? 1 : d.y));
307
320
  return arcsFunc;
308
321
  }, [angle]);
309
- let judgeData = 0 //此处声明全局变量是为了父子组件传递值来判断数据是否都为零
322
+ let judgeData = 0; //此处声明全局变量是为了父子组件传递值来判断数据是否都为零
310
323
  const arcs = useMemo(() => {
311
324
  const _chart = Object.assign(defaultChart, chart);
312
325
  const {
@@ -320,29 +333,29 @@ const Component = memo(
320
333
  const _padAngle = (padAngle * Math.PI) / 180;
321
334
 
322
335
  switch (order) {
323
- case '':
336
+ case "":
324
337
  arcsFunc.sort(null);
325
338
  break;
326
- case 'desc':
339
+ case "desc":
327
340
  arcsFunc.sort((a, b) => b.y - a.y);
328
341
  break;
329
- case 'asc':
342
+ case "asc":
330
343
  arcsFunc.sort((a, b) => a.y - b.y);
331
344
  break;
332
345
  }
333
-
346
+
334
347
  //此处判断data中的y是否都为零,方便饼图都为零时展示
335
348
 
336
349
  let arcs = 0;
337
- data.forEach(function(item){
338
- judgeData+=item.y
350
+ data.forEach(function (item) {
351
+ judgeData += item.y;
339
352
  });
340
353
  if (judgeData == 0) {
341
- arcs = arcsFuncTwo(data)
354
+ arcs = arcsFuncTwo(data);
342
355
  } else {
343
- arcs = arcsFunc(data)
356
+ arcs = arcsFunc(data);
344
357
  }
345
-
358
+
346
359
  //const arcs = arcsFunc(data); 此处是原本的传输饼图data流程
347
360
  const legendDataWithPercent = getDataWithPercent(arcs, legendPrecision);
348
361
  const _legendDataWithPercent = sortPie(legendDataWithPercent, order);
@@ -356,9 +369,9 @@ const Component = memo(
356
369
  return _legendDataWithPercent.map(
357
370
  ({ startAngle, endAngle, ...arc }, index) => ({
358
371
  ...arc,
359
- id: id + '_linear_' + index,
360
- startAngle: roseType == 'area' ? angle * index : startAngle,
361
- endAngle: roseType == 'area' ? angle * (index + 1) : endAngle,
372
+ id: id + "_linear_" + index,
373
+ startAngle: roseType == "area" ? angle * index : startAngle,
374
+ endAngle: roseType == "area" ? angle * (index + 1) : endAngle,
362
375
  cornerRadius,
363
376
  padAngle: _padAngle,
364
377
  innerRadius,
@@ -368,46 +381,56 @@ const Component = memo(
368
381
  }
369
382
  return _legendDataWithPercent.map((arc, index) => ({
370
383
  ...arc,
371
- id: id + '_linear_' + index,
384
+ id: id + "_linear_" + index,
372
385
  cornerRadius,
373
386
  padAngle: _padAngle,
374
387
  innerRadius,
375
388
  outerRadius,
376
389
  }));
377
- }, [data, arcsFunc,arcsFuncTwo, chart, legendPrecision, order]);
390
+ }, [data, arcsFunc, arcsFuncTwo, chart, legendPrecision, order]);
378
391
 
379
392
  const _arcs = useMemo(() => {
380
393
  const seriesLength = series.size;
381
394
  if (!seriesLength) return [];
382
395
  const _series = [...series.values()];
383
- if(_series.length<arcs.length) console.warn("请检查数据中是否存在相同的s");
396
+ if (_series.length < arcs.length)
397
+ console.warn("请检查数据中是否存在相同的s");
384
398
  return arcs.map((arc, index) => getArc(radius, arc, _series, index));
385
399
  }, [series, arcs, radius]);
386
-
400
+
387
401
  const onClick = useCallback(
388
402
  (e) =>
389
403
  onEvent({
390
404
  currentIndex: +e.currentTarget.dataset.index,
391
- type: 'onClick',
405
+ type: "onClick",
392
406
  }),
393
407
  [onEvent]
394
408
  );
395
409
 
396
410
  const onMouseEnter = useCallback(
397
- (e) =>
411
+ (e) => {
412
+ const _data = arcs[+currentIndex].data;
413
+ triggerOnRelative(_data);
414
+ onEmit("onMouseEnter", _data);
398
415
  onEvent({
399
416
  currentIndex: +e.currentTarget.dataset.index,
400
- type: 'onMouseEnter',
401
- }),
402
- [onEvent]
417
+ type: "onMouseEnter",
418
+ });
419
+ },
420
+ [onEvent, triggerOnRelative, onEmit]
403
421
  );
404
422
 
405
423
  const onMouseLeave = useCallback(
406
- (e) =>
424
+ (e) => {
425
+ setMousePos({
426
+ x: 0,
427
+ y: 0,
428
+ });
407
429
  onEvent({
408
430
  currentIndex: +e.currentTarget.dataset.index,
409
- type: 'onMouseLeave',
410
- }),
431
+ type: "onMouseLeave",
432
+ });
433
+ },
411
434
  [onEvent]
412
435
  );
413
436
 
@@ -426,11 +449,11 @@ const Component = memo(
426
449
  onComplete: () => {
427
450
  const _data = arcs[+currentIndex].data;
428
451
  triggerOnRelative(_data);
429
- onEmit('carousel', _data);
452
+ onEmit("carousel", _data);
430
453
  },
431
454
  });
432
455
  } else {
433
- if (currentIndex !== null && trigger === 'onClick') {
456
+ if (currentIndex !== null && trigger === "onClick") {
434
457
  const _data = arcs[+currentIndex].data;
435
458
  triggerOnRelative(_data);
436
459
  onEmit(trigger, _data);
@@ -450,21 +473,21 @@ const Component = memo(
450
473
  triggerOnRelative,
451
474
  ]);
452
475
  const aiData = useAiDataOfPie(_arcs, legend);
453
- useEffect(()=>{
454
- if(aiData.length){
455
- if(!window.aiData){
456
- window.aiData={};
476
+ useEffect(() => {
477
+ if (aiData.length) {
478
+ if (!window.aiData) {
479
+ window.aiData = {};
457
480
  }
458
- window.aiData[id]={
459
- getAI:()=>{
481
+ window.aiData[id] = {
482
+ getAI: () => {
460
483
  return aiData;
461
- }
462
- }
484
+ },
485
+ };
463
486
  }
464
- return ()=>{
487
+ return () => {
465
488
  window.aiData && window.aiData[id] && delete window.aiData[id];
466
- }
467
- },[JSON.stringify(aiData),id]);
489
+ };
490
+ }, [JSON.stringify(aiData), id]);
468
491
 
469
492
  const halfChartWidth = chartWidth / 2;
470
493
  const halfChartHeight = chartHeight / 2;
@@ -480,6 +503,9 @@ const Component = memo(
480
503
  maxRadius = Math.max(maxRadius, d.outerRadius);
481
504
  });
482
505
  let centerRadius = 0.5 * maxRadius + 0.5 * _arcs[0].innerRadius;
506
+ const [mousePos, setMousePos] = useState({ x: 0, y: 0 });
507
+ const [hoverData, setHoverData] = useState(null);
508
+ const pieWarpEl = useRef(null);
483
509
  return outerDecorate ? (
484
510
  <>
485
511
  <ChartContainer //用于生成甜甜圈图,判断依据是外环装饰这个配置项(outerDecorate)
@@ -487,18 +513,19 @@ const Component = memo(
487
513
  height={height}
488
514
  marginLeft={marginLeft}
489
515
  marginTop={marginTop}
516
+ ref={pieWarpEl}
490
517
  >
491
518
  <g
492
519
  style={{
493
- transition: 'transform ease-in-out 0.3s',
520
+ transition: "transform ease-in-out 0.3s",
494
521
  transform:
495
- 'translate(' +
522
+ "translate(" +
496
523
  halfChartWidth +
497
- 'px, ' +
524
+ "px, " +
498
525
  halfChartHeight +
499
- 'px) rotate(' +
526
+ "px) rotate(" +
500
527
  rotate_ +
501
- 'deg)',
528
+ "deg)",
502
529
  }}
503
530
  >
504
531
  {
@@ -507,10 +534,10 @@ const Component = memo(
507
534
  getCircleScale(outerDecorate.tick, maxRadius)
508
535
  }
509
536
  <circle //外环装饰
510
- cx='0'
511
- cy='0'
537
+ cx="0"
538
+ cy="0"
512
539
  r={maxRadius + 2}
513
- fill='none'
540
+ fill="none"
514
541
  stroke={outerDecorate.color}
515
542
  strokeWidth={outerDecorate.width}
516
543
  />
@@ -527,7 +554,7 @@ const Component = memo(
527
554
  return (
528
555
  <Fragment key={index}>
529
556
  <path
530
- className={ringCss['inner-arc']}
557
+ className={ringCss["inner-arc"]}
531
558
  style={{
532
559
  strokeDasharray: `${dashLength},${2 * dashLength}`,
533
560
  strokeDashoffset: dashLength,
@@ -537,10 +564,22 @@ const Component = memo(
537
564
  onClick={onClick}
538
565
  onMouseEnter={onMouseEnter}
539
566
  onMouseLeave={onMouseLeave}
540
- d={path.split('L')[0]}
541
- stroke={'url(#' + id + ')'}
567
+ onMouseMove={(e)=>{
568
+ const _data = arcs[+e.currentTarget.dataset.index];
569
+ const warpBoxPos = {
570
+ x: pieWarpEl.current.getBoundingClientRect().x,
571
+ y: pieWarpEl.current.getBoundingClientRect().y,
572
+ };
573
+ setMousePos({
574
+ x: e.clientX - warpBoxPos.x,
575
+ y: e.clientY - warpBoxPos.y,
576
+ });
577
+ setHoverData(_data);
578
+ }}
579
+ d={path.split("L")[0]}
580
+ stroke={"url(#" + id + ")"}
542
581
  strokeWidth={arcWidth}
543
- fill='none'
582
+ fill="none"
544
583
  />
545
584
  <defs>
546
585
  <LinearGradient
@@ -563,7 +602,28 @@ const Component = memo(
563
602
  )}
564
603
  </g>
565
604
  </ChartContainer>
566
- <Legend {...legend} series={_arcs} formatter={formatter} judge = {judgeData}/>
605
+ {tooltip &&
606
+ mousePos &&
607
+ mousePos.x != 0 &&
608
+ mousePos.y != 0 &&
609
+ tooltip.manual && (
610
+ <PieTooltip
611
+ series={series}
612
+ data={hoverData}
613
+ config={tooltip}
614
+ pieCenter={{
615
+ x: halfChartWidth,
616
+ y: maxRadius + marginTop,
617
+ }}
618
+ mousePos={mousePos}
619
+ />
620
+ )}
621
+ <Legend
622
+ {...legend}
623
+ series={_arcs.map((arc)=>({...arc,percent:arc.percent.toFixed(legendPrecision)}))}
624
+ formatter={formatter}
625
+ judge={judgeData}
626
+ />
567
627
  </>
568
628
  ) : (
569
629
  <>
@@ -572,20 +632,25 @@ const Component = memo(
572
632
  height={height}
573
633
  marginLeft={marginLeft}
574
634
  marginTop={marginTop}
575
- onMouseEnter={()=>{hoverEvent(true)}}
576
- onMouseLeave={()=>{hoverEvent(false)}}
635
+ onMouseEnter={() => {
636
+ hoverEvent(true);
637
+ }}
638
+ onMouseLeave={() => {
639
+ hoverEvent(false);
640
+ }}
641
+ ref={pieWarpEl}
577
642
  >
578
643
  <g
579
644
  style={{
580
- transition: 'transform ease-in-out 0.3s',
645
+ transition: "transform ease-in-out 0.3s",
581
646
  transform:
582
- 'translate(' +
647
+ "translate(" +
583
648
  halfChartWidth +
584
- 'px, ' +
649
+ "px, " +
585
650
  halfChartHeight +
586
- 'px) rotate(' +
651
+ "px) rotate(" +
587
652
  rotate_ +
588
- 'deg)',
653
+ "deg)",
589
654
  }}
590
655
  >
591
656
  {_arcs.map(
@@ -618,7 +683,7 @@ const Component = memo(
618
683
  const currentPie = animateColor
619
684
  ? getColorList(animateColor)
620
685
  : getColorList(series.color);
621
- let textPath = '',
686
+ let textPath = "",
622
687
  categoryTextStyle = {};
623
688
  if (categoryText && categoryText.show) {
624
689
  //如果有类目文本,则需要计算文字路径
@@ -630,7 +695,7 @@ const Component = memo(
630
695
  .outerRadius(
631
696
  outerRadius + (current ? gap : categoryText.gap)
632
697
  )(value);
633
- let lastA = textArc.lastIndexOf('A');
698
+ let lastA = textArc.lastIndexOf("A");
634
699
  textPath = textArc.slice(
635
700
  0,
636
701
  lastA > 0 ? lastA : textArc.length
@@ -647,10 +712,22 @@ const Component = memo(
647
712
  onClick={onClick}
648
713
  onMouseEnter={onMouseEnter}
649
714
  onMouseLeave={onMouseLeave}
715
+ onMouseMove={(e) => {
716
+ const _data = arcs[+e.currentTarget.dataset.index];
717
+ const warpBoxPos = {
718
+ x: pieWarpEl.current.getBoundingClientRect().x,
719
+ y: pieWarpEl.current.getBoundingClientRect().y,
720
+ };
721
+ setMousePos({
722
+ x: e.clientX - warpBoxPos.x,
723
+ y: e.clientY - warpBoxPos.y,
724
+ });
725
+ setHoverData(_data);
726
+ }}
650
727
  d={path}
651
- stroke={show ? color : 'none'}
652
- strokeWidth={show ? strokeWidth : '0'}
653
- fill={'url(#' + id + ')'}
728
+ stroke={show ? color : "none"}
729
+ strokeWidth={show ? strokeWidth : "0"}
730
+ fill={"url(#" + id + ")"}
654
731
  fillOpacity={fillOpacity}
655
732
  />
656
733
  {
@@ -668,43 +745,43 @@ const Component = memo(
668
745
  decorate2.radiusWidth +
669
746
  (current ? radiusWidthAdd : 0)
670
747
  )(value)}
671
- stroke={show ? color : 'none'}
672
- strokeWidth={show ? strokeWidth : '0'}
673
- fill={'url(#' + id + ')'}
748
+ stroke={show ? color : "none"}
749
+ strokeWidth={show ? strokeWidth : "0"}
750
+ fill={"url(#" + id + ")"}
674
751
  fillOpacity={decorate2.opacity / 100}
675
752
  />
676
753
  )
677
754
  }
678
755
  {
679
756
  //类目文本
680
- value && categoryText && categoryText.show && (
757
+ value && categoryText && categoryText.show && (
681
758
  <g>
682
759
  <path
683
760
  onClick={onClick}
684
761
  onMouseEnter={onMouseEnter}
685
762
  onMouseLeave={onMouseLeave}
686
- id={id + '_text_' + index}
763
+ id={id + "_text_" + index}
687
764
  d={textPath}
688
- fill='none'
689
- stroke='none'
765
+ fill="none"
766
+ stroke="none"
690
767
  />
691
768
  <text
692
- textAnchor='middle'
769
+ textAnchor="middle"
693
770
  style={{
694
771
  ...categoryTextStyle,
695
772
  fontWeight: categoryTextStyle.bold
696
- ? 'bold'
697
- : 'normal',
773
+ ? "bold"
774
+ : "normal",
698
775
  fontStyle: categoryTextStyle.italic
699
- ? 'italic'
700
- : 'normal',
701
- pointerEvents: 'none',
776
+ ? "italic"
777
+ : "normal",
778
+ pointerEvents: "none",
702
779
  }}
703
780
  fill={categoryTextStyle.color}
704
781
  >
705
782
  <textPath
706
- startOffset='50%'
707
- href={'#' + id + '_text_' + index}
783
+ startOffset="50%"
784
+ href={"#" + id + "_text_" + index}
708
785
  >
709
786
  {_arcs[index].displayName ||
710
787
  _arcs[index].fieldName}
@@ -732,18 +809,18 @@ const Component = memo(
732
809
  );
733
810
  }
734
811
  )}
735
- {label && <Label config={label} arcs={_arcs} judge = {judgeData} />}
812
+ {label && <Label config={label} arcs={_arcs} judge={judgeData} />}
736
813
  {current && (
737
814
  <g
738
815
  fillOpacity={y}
739
- style={{ transform: 'rotate(' + -rotate_ + 'deg)' }}
816
+ style={{ transform: "rotate(" + -rotate_ + "deg)" }}
740
817
  >
741
818
  <Current
742
819
  config={current}
743
820
  width={width}
744
821
  height={height}
745
822
  data={_arcs}
746
- judge = {judgeData}
823
+ judge={judgeData}
747
824
  currentIndex={+currentIndex}
748
825
  />
749
826
  </g>
@@ -761,7 +838,28 @@ const Component = memo(
761
838
  radius={radius}
762
839
  />
763
840
  )}
764
- <Legend {...legend} series={_arcs} formatter={formatter} judge = {judgeData} />
841
+ {tooltip &&
842
+ mousePos &&
843
+ mousePos.x != 0 &&
844
+ mousePos.y != 0 &&
845
+ tooltip.manual && (
846
+ <PieTooltip
847
+ series={series}
848
+ data={hoverData}
849
+ config={tooltip}
850
+ pieCenter={{
851
+ x: halfChartWidth,
852
+ y: maxRadius + marginTop,
853
+ }}
854
+ mousePos={mousePos}
855
+ />
856
+ )}
857
+ <Legend
858
+ {...legend}
859
+ series={_arcs.map((arc)=>({...arc,percent:arc.percent.toFixed(legendPrecision)}))}
860
+ formatter={formatter}
861
+ judge={judgeData}
862
+ />
765
863
  </>
766
864
  );
767
865
  }
@@ -771,7 +869,14 @@ const Current = ({
771
869
  config: {
772
870
  show,
773
871
  gap,
774
- name: { show: showName, sameColor: nameColor, font: nameFont, maxWidth, textOverflow, speed },
872
+ name: {
873
+ show: showName,
874
+ sameColor: nameColor,
875
+ font: nameFont,
876
+ maxWidth,
877
+ textOverflow,
878
+ speed,
879
+ },
775
880
  percent: {
776
881
  show: showPercent,
777
882
  sameColor: percentColor,
@@ -789,8 +894,8 @@ const Current = ({
789
894
  fontSize,
790
895
  text,
791
896
  translate: { x: translateSuffixX, y: translateSuffixY },
792
- }
793
- }
897
+ },
898
+ },
794
899
  },
795
900
  width,
796
901
  height,
@@ -800,13 +905,13 @@ const Current = ({
800
905
  }) => {
801
906
  const _data = useMemo(() => {
802
907
  const legendDataWithPercent = getDataWithPercent(data, precision);
803
- return sortPie(legendDataWithPercent, '');
908
+ return sortPie(legendDataWithPercent, "");
804
909
  }, [data, precision]);
805
-
910
+
806
911
  //数据容错,当data都为零那么需要进行以下容错
807
912
  if (judge == 0) {
808
913
  _data.forEach((d) => {
809
- d.percent = 0, d.value = 0;
914
+ (d.percent = 0), (d.value = 0);
810
915
  });
811
916
  }
812
917
 
@@ -822,34 +927,41 @@ const Current = ({
822
927
  width,
823
928
  height,
824
929
  transform: `translate(-${width / 2}px,-${height / 2}px)`,
825
- pointerEvents: 'none',
930
+ pointerEvents: "none",
826
931
  },
827
932
  boxStyle = {
828
933
  //弹性盒子样式,用于当前值的上下居中对齐等
829
934
  width,
830
935
  height,
831
- display: 'flex',
832
- flexDirection: 'column',
833
- justifyContent: 'center',
834
- alignItems: 'center',
936
+ display: "flex",
937
+ flexDirection: "column",
938
+ justifyContent: "center",
939
+ alignItems: "center",
835
940
  };
836
941
  let seriesColor = currentData.series.color;
837
942
  seriesColor =
838
- seriesColor.type == 'pure'
943
+ seriesColor.type == "pure"
839
944
  ? seriesColor.pure
840
945
  : seriesColor.linear.stops[0].color;
841
946
  return (
842
947
  show && (
843
948
  <foreignObject style={foreignStyle}>
844
949
  <div style={boxStyle}>
845
- {showName &&<TextOverflow type={textOverflow} value={nameTemp} speed={speed} style={{
846
- maxWidth,
847
- display:textOverflow=="marquee"?"flex":"bolck",
848
- justifyContent:"center",
849
- ...getFontStyle(nameFont),
850
- margin: gap / 2 + 'px 0',
851
- color: nameColor ? seriesColor : nameFont.color,
852
- }}></TextOverflow>}
950
+ {showName && (
951
+ <TextOverflow
952
+ type={textOverflow}
953
+ value={nameTemp}
954
+ speed={speed}
955
+ style={{
956
+ maxWidth,
957
+ display: textOverflow == "marquee" ? "flex" : "bolck",
958
+ justifyContent: "center",
959
+ ...getFontStyle(nameFont),
960
+ margin: gap / 2 + "px 0",
961
+ color: nameColor ? seriesColor : nameFont.color,
962
+ }}
963
+ ></TextOverflow>
964
+ )}
853
965
  {
854
966
  //真实值
855
967
  showValue && (
@@ -857,12 +969,12 @@ const Current = ({
857
969
  style={{
858
970
  ...getFontStyle(valueFont),
859
971
  transform:
860
- 'translate(' +
972
+ "translate(" +
861
973
  translateValueX +
862
- 'px,' +
974
+ "px," +
863
975
  translateValueY +
864
- 'px)',
865
- margin: gap / 2 + 'px 0',
976
+ "px)",
977
+ margin: gap / 2 + "px 0",
866
978
  color: valueColor ? seriesColor : valueFont.color,
867
979
  }}
868
980
  >
@@ -870,13 +982,13 @@ const Current = ({
870
982
  {showSuffix && text && (
871
983
  <span
872
984
  style={{
873
- display:"inline-block",
985
+ display: "inline-block",
874
986
  transform:
875
- 'translate(' +
987
+ "translate(" +
876
988
  translateSuffixX +
877
- 'px,' +
989
+ "px," +
878
990
  translateSuffixY +
879
- 'px)',
991
+ "px)",
880
992
  fontSize: fontSize,
881
993
  }}
882
994
  >
@@ -892,17 +1004,17 @@ const Current = ({
892
1004
  <span
893
1005
  style={{
894
1006
  transform:
895
- 'translate(' +
1007
+ "translate(" +
896
1008
  translatePercentX +
897
- 'px,' +
1009
+ "px," +
898
1010
  translatePercentY +
899
- 'px)',
1011
+ "px)",
900
1012
  ...getFontStyle(percentFont),
901
- margin: gap / 2 + 'px 0',
1013
+ margin: gap / 2 + "px 0",
902
1014
  color: percentColor ? seriesColor : percentFont.color,
903
1015
  }}
904
1016
  >
905
- {percent + '%'}
1017
+ {percent + "%"}
906
1018
  </span>
907
1019
  )
908
1020
  }
@@ -930,13 +1042,9 @@ const Label = ({
930
1042
  text,
931
1043
  fontSize: suffixFontSize,
932
1044
  translate: { x: suffixTranslateX, y: suffixTranslateY },
933
- }
934
- },
935
- percent: {
936
- show: showPercent,
937
- font: percentFont,
938
- precision
1045
+ },
939
1046
  },
1047
+ percent: { show: showPercent, font: percentFont, precision },
940
1048
  },
941
1049
  arcs,
942
1050
  judge,
@@ -946,12 +1054,12 @@ const Label = ({
946
1054
  () => getDataWithPercent(arcs, precision),
947
1055
  [arcs, precision]
948
1056
  );
949
- //数据做出容错
1057
+ //数据做出容错
950
1058
  if (judge == 0) {
951
1059
  _arcs.forEach((d) => {
952
- d.percent=0
953
- })
954
- }
1060
+ d.percent = 0;
1061
+ });
1062
+ }
955
1063
  return (
956
1064
  <g>
957
1065
  {_arcs.map(
@@ -999,70 +1107,90 @@ const Label = ({
999
1107
  (_showName || showPercent || showValue) && (
1000
1108
  <g key={index}>
1001
1109
  <path
1002
- className={animation ? ringCss['label-line'] : ''}
1110
+ className={animation ? ringCss["label-line"] : ""}
1003
1111
  style={{
1004
1112
  animationDelay: `${
1005
1113
  animation ? (actualIndex + 1) * 2000 - 800 : 0
1006
1114
  }ms`,
1007
1115
  }}
1008
1116
  d={
1009
- 'M' +
1117
+ "M" +
1010
1118
  x1 +
1011
- ', ' +
1119
+ ", " +
1012
1120
  y1 +
1013
- 'L' +
1121
+ "L" +
1014
1122
  x2 +
1015
- ', ' +
1123
+ ", " +
1016
1124
  y2 +
1017
- 'L' +
1125
+ "L" +
1018
1126
  x3 +
1019
- ', ' +
1127
+ ", " +
1020
1128
  y2
1021
1129
  }
1022
1130
  stroke={
1023
1131
  lineColor
1024
1132
  ? lineColor
1025
- : type == 'pure'
1133
+ : type == "pure"
1026
1134
  ? pure
1027
1135
  : stops[0].color
1028
1136
  }
1029
- fill='none'
1137
+ fill="none"
1030
1138
  />
1031
- <foreignObject width="1" height="1" x={_x} y={y2+translateY} style={{overflow:"visible"}}>
1032
- <div className={animation? ringCss['label-text']:""} style={{
1033
- transform:"translate(0,-50%)",
1034
- whiteSpace:"nowrap",
1035
- float:x3>=0?"left":"right",
1036
- width:"max-content"
1037
- }}>
1038
- {_showName &&<TextOverflow type={textOverflow} value={displayName+((showValue || showPercent)?":":"")} speed={speed} style={{
1039
- maxWidth,
1040
- ...nameStyle,
1041
- float:mode=="horizontal"?"left":"none"
1042
- }}></TextOverflow>}
1043
- {
1044
- showValue && <span style={getFontStyle(valueFont)}>
1139
+ <foreignObject
1140
+ width="1"
1141
+ height="1"
1142
+ x={_x}
1143
+ y={y2 + translateY}
1144
+ style={{ overflow: "visible" }}
1145
+ >
1146
+ <div
1147
+ className={animation ? ringCss["label-text"] : ""}
1148
+ style={{
1149
+ transform: "translate(0,-50%)",
1150
+ whiteSpace: "nowrap",
1151
+ float: x3 >= 0 ? "left" : "right",
1152
+ width: "max-content",
1153
+ }}
1154
+ >
1155
+ {_showName && (
1156
+ <TextOverflow
1157
+ type={textOverflow}
1158
+ value={
1159
+ displayName + (showValue || showPercent ? ":" : "")
1160
+ }
1161
+ speed={speed}
1162
+ style={{
1163
+ maxWidth,
1164
+ ...nameStyle,
1165
+ float: mode == "horizontal" ? "left" : "none",
1166
+ }}
1167
+ ></TextOverflow>
1168
+ )}
1169
+ {showValue && (
1170
+ <span style={getFontStyle(valueFont)}>
1045
1171
  {data.y}
1046
- {showSuffix && <span style={{
1047
- position:"relative",
1048
- fontSize:suffixFontSize,
1049
- marginLeft:suffixTranslateX,
1050
- top:suffixTranslateY
1051
- }}>
1052
- { text }
1053
- </span>}
1172
+ {showSuffix && (
1173
+ <span
1174
+ style={{
1175
+ position: "relative",
1176
+ fontSize: suffixFontSize,
1177
+ marginLeft: suffixTranslateX,
1178
+ top: suffixTranslateY,
1179
+ }}
1180
+ >
1181
+ {text}
1182
+ </span>
1183
+ )}
1054
1184
  </span>
1055
- }
1056
- {
1057
- showPercent && <span style={getFontStyle(percentFont)}>
1058
- {
1059
- (_showValue ? '(' : '') +
1185
+ )}
1186
+ {showPercent && (
1187
+ <span style={getFontStyle(percentFont)}>
1188
+ {(_showValue ? "(" : "") +
1060
1189
  percent +
1061
- '%' +
1062
- (_showValue ? '' : '')
1063
- }
1190
+ "%" +
1191
+ (_showValue ? "" : "")}
1064
1192
  </span>
1065
- }
1193
+ )}
1066
1194
  </div>
1067
1195
  </foreignObject>
1068
1196
  </g>
@@ -1092,13 +1220,9 @@ const RingLabel = ({
1092
1220
  text,
1093
1221
  fontSize: suffixFontSize,
1094
1222
  translate: { x: suffixTranslateX, y: suffixTranslateY },
1095
- }
1096
- },
1097
- percent: {
1098
- show: showPercent,
1099
- font: percentFont,
1100
- precision
1223
+ },
1101
1224
  },
1225
+ percent: { show: showPercent, font: percentFont, precision },
1102
1226
  },
1103
1227
  judge,
1104
1228
  arcs,
@@ -1107,13 +1231,13 @@ const RingLabel = ({
1107
1231
  () => getDataWithPercent(arcs, precision),
1108
1232
  [arcs, precision]
1109
1233
  );
1110
-
1111
- //数据做出容错
1112
- if (judge == 0) {
1113
- _arcs.forEach((d) => {
1114
- d.percent=0
1115
- })
1116
- }
1234
+
1235
+ //数据做出容错
1236
+ if (judge == 0) {
1237
+ _arcs.forEach((d) => {
1238
+ d.percent = 0;
1239
+ });
1240
+ }
1117
1241
 
1118
1242
  return (
1119
1243
  <g>
@@ -1162,69 +1286,89 @@ const RingLabel = ({
1162
1286
  (_showName || showPercent || _showValue) && (
1163
1287
  <g key={index}>
1164
1288
  <path
1165
- className={ringCss['label-line']}
1289
+ className={ringCss["label-line"]}
1166
1290
  style={{
1167
1291
  animationDelay: `${(actualIndex + 1) * 2000 - 800}ms`,
1168
1292
  }}
1169
1293
  d={
1170
- 'M' +
1294
+ "M" +
1171
1295
  x1 +
1172
- ', ' +
1296
+ ", " +
1173
1297
  y1 +
1174
- 'L' +
1298
+ "L" +
1175
1299
  x2 +
1176
- ', ' +
1300
+ ", " +
1177
1301
  y2 +
1178
- 'L' +
1302
+ "L" +
1179
1303
  x3 +
1180
- ', ' +
1304
+ ", " +
1181
1305
  y2
1182
1306
  }
1183
1307
  stroke={
1184
1308
  lineColor
1185
1309
  ? lineColor
1186
- : type == 'pure'
1310
+ : type == "pure"
1187
1311
  ? pure
1188
1312
  : stops[0].color
1189
1313
  }
1190
- fill='none'
1314
+ fill="none"
1191
1315
  />
1192
- <foreignObject width="1" height="1" x={_x} y={y2+translateY} style={{overflow:"visible"}}>
1193
- <div className={ringCss['label-text']} style={{
1194
- transform:"translate(0,-50%)",
1195
- whiteSpace:"nowrap",
1196
- float:x3>=0?"left":"right",
1197
- width:"max-content",
1198
- animationDelay: `${(actualIndex + 1) * 2000 - 800}ms`,
1199
- }}>
1200
- {_showName &&<TextOverflow type={textOverflow} value={displayName+((showValue || showPercent)?":":"")} speed={speed} style={{
1201
- maxWidth,
1202
- ...getFontStyle(nameFont),
1203
- float:mode=="horizontal"?"left":"none"
1204
- }}></TextOverflow>}
1205
- {
1206
- showValue && <span style={getFontStyle(valueFont)}>
1316
+ <foreignObject
1317
+ width="1"
1318
+ height="1"
1319
+ x={_x}
1320
+ y={y2 + translateY}
1321
+ style={{ overflow: "visible" }}
1322
+ >
1323
+ <div
1324
+ className={ringCss["label-text"]}
1325
+ style={{
1326
+ transform: "translate(0,-50%)",
1327
+ whiteSpace: "nowrap",
1328
+ float: x3 >= 0 ? "left" : "right",
1329
+ width: "max-content",
1330
+ animationDelay: `${(actualIndex + 1) * 2000 - 800}ms`,
1331
+ }}
1332
+ >
1333
+ {_showName && (
1334
+ <TextOverflow
1335
+ type={textOverflow}
1336
+ value={
1337
+ displayName + (showValue || showPercent ? ":" : "")
1338
+ }
1339
+ speed={speed}
1340
+ style={{
1341
+ maxWidth,
1342
+ ...getFontStyle(nameFont),
1343
+ float: mode == "horizontal" ? "left" : "none",
1344
+ }}
1345
+ ></TextOverflow>
1346
+ )}
1347
+ {showValue && (
1348
+ <span style={getFontStyle(valueFont)}>
1207
1349
  {realData.y}
1208
- {showSuffix && <span style={{
1209
- position:"relative",
1210
- fontSize:suffixFontSize,
1211
- marginLeft:suffixTranslateX,
1212
- top:suffixTranslateY
1213
- }}>
1214
- { text }
1215
- </span>}
1350
+ {showSuffix && (
1351
+ <span
1352
+ style={{
1353
+ position: "relative",
1354
+ fontSize: suffixFontSize,
1355
+ marginLeft: suffixTranslateX,
1356
+ top: suffixTranslateY,
1357
+ }}
1358
+ >
1359
+ {text}
1360
+ </span>
1361
+ )}
1216
1362
  </span>
1217
- }
1218
- {
1219
- showPercent && <span style={getFontStyle(percentFont)}>
1220
- {
1221
- (_showValue ? '(' : '') +
1363
+ )}
1364
+ {showPercent && (
1365
+ <span style={getFontStyle(percentFont)}>
1366
+ {(_showValue ? "(" : "") +
1222
1367
  percent +
1223
- '%' +
1224
- (_showValue ? '' : '')
1225
- }
1368
+ "%" +
1369
+ (_showValue ? "" : "")}
1226
1370
  </span>
1227
- }
1371
+ )}
1228
1372
  </div>
1229
1373
  </foreignObject>
1230
1374
  </g>