@easyv/charts 1.4.25 → 1.4.26

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