@easyv/charts 1.4.24 → 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.
@@ -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,50 +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) => {
398
411
  const _data = arcs[+currentIndex].data;
399
412
  triggerOnRelative(_data);
400
- onEmit('onMouseEnter', _data);
413
+ onEmit("onMouseEnter", _data);
401
414
  onEvent({
402
415
  currentIndex: +e.currentTarget.dataset.index,
403
- type: 'onMouseEnter',
404
- })
416
+ type: "onMouseEnter",
417
+ });
405
418
  },
406
- [onEvent,triggerOnRelative,onEmit]
419
+ [onEvent, triggerOnRelative, onEmit]
407
420
  );
408
421
 
409
422
  const onMouseLeave = useCallback(
410
- (e) =>
423
+ (e) => {
424
+ setMousePos({
425
+ x: 0,
426
+ y: 0,
427
+ });
411
428
  onEvent({
412
429
  currentIndex: +e.currentTarget.dataset.index,
413
- type: 'onMouseLeave',
414
- }),
430
+ type: "onMouseLeave",
431
+ });
432
+ },
415
433
  [onEvent]
416
434
  );
417
435
 
@@ -430,11 +448,11 @@ const Component = memo(
430
448
  onComplete: () => {
431
449
  const _data = arcs[+currentIndex].data;
432
450
  triggerOnRelative(_data);
433
- onEmit('carousel', _data);
451
+ onEmit("carousel", _data);
434
452
  },
435
453
  });
436
454
  } else {
437
- if (currentIndex !== null && trigger === 'onClick') {
455
+ if (currentIndex !== null && trigger === "onClick") {
438
456
  const _data = arcs[+currentIndex].data;
439
457
  triggerOnRelative(_data);
440
458
  onEmit(trigger, _data);
@@ -454,21 +472,21 @@ const Component = memo(
454
472
  triggerOnRelative,
455
473
  ]);
456
474
  const aiData = useAiDataOfPie(_arcs, legend);
457
- useEffect(()=>{
458
- if(aiData.length){
459
- if(!window.aiData){
460
- window.aiData={};
475
+ useEffect(() => {
476
+ if (aiData.length) {
477
+ if (!window.aiData) {
478
+ window.aiData = {};
461
479
  }
462
- window.aiData[id]={
463
- getAI:()=>{
480
+ window.aiData[id] = {
481
+ getAI: () => {
464
482
  return aiData;
465
- }
466
- }
483
+ },
484
+ };
467
485
  }
468
- return ()=>{
486
+ return () => {
469
487
  window.aiData && window.aiData[id] && delete window.aiData[id];
470
- }
471
- },[JSON.stringify(aiData),id]);
488
+ };
489
+ }, [JSON.stringify(aiData), id]);
472
490
 
473
491
  const halfChartWidth = chartWidth / 2;
474
492
  const halfChartHeight = chartHeight / 2;
@@ -484,6 +502,9 @@ const Component = memo(
484
502
  maxRadius = Math.max(maxRadius, d.outerRadius);
485
503
  });
486
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);
487
508
  return outerDecorate ? (
488
509
  <>
489
510
  <ChartContainer //用于生成甜甜圈图,判断依据是外环装饰这个配置项(outerDecorate)
@@ -491,18 +512,19 @@ const Component = memo(
491
512
  height={height}
492
513
  marginLeft={marginLeft}
493
514
  marginTop={marginTop}
515
+ ref={pieWarpEl}
494
516
  >
495
517
  <g
496
518
  style={{
497
- transition: 'transform ease-in-out 0.3s',
519
+ transition: "transform ease-in-out 0.3s",
498
520
  transform:
499
- 'translate(' +
521
+ "translate(" +
500
522
  halfChartWidth +
501
- 'px, ' +
523
+ "px, " +
502
524
  halfChartHeight +
503
- 'px) rotate(' +
525
+ "px) rotate(" +
504
526
  rotate_ +
505
- 'deg)',
527
+ "deg)",
506
528
  }}
507
529
  >
508
530
  {
@@ -511,10 +533,10 @@ const Component = memo(
511
533
  getCircleScale(outerDecorate.tick, maxRadius)
512
534
  }
513
535
  <circle //外环装饰
514
- cx='0'
515
- cy='0'
536
+ cx="0"
537
+ cy="0"
516
538
  r={maxRadius + 2}
517
- fill='none'
539
+ fill="none"
518
540
  stroke={outerDecorate.color}
519
541
  strokeWidth={outerDecorate.width}
520
542
  />
@@ -531,7 +553,7 @@ const Component = memo(
531
553
  return (
532
554
  <Fragment key={index}>
533
555
  <path
534
- className={ringCss['inner-arc']}
556
+ className={ringCss["inner-arc"]}
535
557
  style={{
536
558
  strokeDasharray: `${dashLength},${2 * dashLength}`,
537
559
  strokeDashoffset: dashLength,
@@ -541,10 +563,22 @@ const Component = memo(
541
563
  onClick={onClick}
542
564
  onMouseEnter={onMouseEnter}
543
565
  onMouseLeave={onMouseLeave}
544
- d={path.split('L')[0]}
545
- 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 + ")"}
546
580
  strokeWidth={arcWidth}
547
- fill='none'
581
+ fill="none"
548
582
  />
549
583
  <defs>
550
584
  <LinearGradient
@@ -567,7 +601,28 @@ const Component = memo(
567
601
  )}
568
602
  </g>
569
603
  </ChartContainer>
570
- <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
+ />
571
626
  </>
572
627
  ) : (
573
628
  <>
@@ -576,20 +631,25 @@ const Component = memo(
576
631
  height={height}
577
632
  marginLeft={marginLeft}
578
633
  marginTop={marginTop}
579
- onMouseEnter={()=>{hoverEvent(true)}}
580
- onMouseLeave={()=>{hoverEvent(false)}}
634
+ onMouseEnter={() => {
635
+ hoverEvent(true);
636
+ }}
637
+ onMouseLeave={() => {
638
+ hoverEvent(false);
639
+ }}
640
+ ref={pieWarpEl}
581
641
  >
582
642
  <g
583
643
  style={{
584
- transition: 'transform ease-in-out 0.3s',
644
+ transition: "transform ease-in-out 0.3s",
585
645
  transform:
586
- 'translate(' +
646
+ "translate(" +
587
647
  halfChartWidth +
588
- 'px, ' +
648
+ "px, " +
589
649
  halfChartHeight +
590
- 'px) rotate(' +
650
+ "px) rotate(" +
591
651
  rotate_ +
592
- 'deg)',
652
+ "deg)",
593
653
  }}
594
654
  >
595
655
  {_arcs.map(
@@ -622,7 +682,7 @@ const Component = memo(
622
682
  const currentPie = animateColor
623
683
  ? getColorList(animateColor)
624
684
  : getColorList(series.color);
625
- let textPath = '',
685
+ let textPath = "",
626
686
  categoryTextStyle = {};
627
687
  if (categoryText && categoryText.show) {
628
688
  //如果有类目文本,则需要计算文字路径
@@ -634,7 +694,7 @@ const Component = memo(
634
694
  .outerRadius(
635
695
  outerRadius + (current ? gap : categoryText.gap)
636
696
  )(value);
637
- let lastA = textArc.lastIndexOf('A');
697
+ let lastA = textArc.lastIndexOf("A");
638
698
  textPath = textArc.slice(
639
699
  0,
640
700
  lastA > 0 ? lastA : textArc.length
@@ -651,10 +711,22 @@ const Component = memo(
651
711
  onClick={onClick}
652
712
  onMouseEnter={onMouseEnter}
653
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
+ }}
654
726
  d={path}
655
- stroke={show ? color : 'none'}
656
- strokeWidth={show ? strokeWidth : '0'}
657
- fill={'url(#' + id + ')'}
727
+ stroke={show ? color : "none"}
728
+ strokeWidth={show ? strokeWidth : "0"}
729
+ fill={"url(#" + id + ")"}
658
730
  fillOpacity={fillOpacity}
659
731
  />
660
732
  {
@@ -672,43 +744,43 @@ const Component = memo(
672
744
  decorate2.radiusWidth +
673
745
  (current ? radiusWidthAdd : 0)
674
746
  )(value)}
675
- stroke={show ? color : 'none'}
676
- strokeWidth={show ? strokeWidth : '0'}
677
- fill={'url(#' + id + ')'}
747
+ stroke={show ? color : "none"}
748
+ strokeWidth={show ? strokeWidth : "0"}
749
+ fill={"url(#" + id + ")"}
678
750
  fillOpacity={decorate2.opacity / 100}
679
751
  />
680
752
  )
681
753
  }
682
754
  {
683
755
  //类目文本
684
- value && categoryText && categoryText.show && (
756
+ value && categoryText && categoryText.show && (
685
757
  <g>
686
758
  <path
687
759
  onClick={onClick}
688
760
  onMouseEnter={onMouseEnter}
689
761
  onMouseLeave={onMouseLeave}
690
- id={id + '_text_' + index}
762
+ id={id + "_text_" + index}
691
763
  d={textPath}
692
- fill='none'
693
- stroke='none'
764
+ fill="none"
765
+ stroke="none"
694
766
  />
695
767
  <text
696
- textAnchor='middle'
768
+ textAnchor="middle"
697
769
  style={{
698
770
  ...categoryTextStyle,
699
771
  fontWeight: categoryTextStyle.bold
700
- ? 'bold'
701
- : 'normal',
772
+ ? "bold"
773
+ : "normal",
702
774
  fontStyle: categoryTextStyle.italic
703
- ? 'italic'
704
- : 'normal',
705
- pointerEvents: 'none',
775
+ ? "italic"
776
+ : "normal",
777
+ pointerEvents: "none",
706
778
  }}
707
779
  fill={categoryTextStyle.color}
708
780
  >
709
781
  <textPath
710
- startOffset='50%'
711
- href={'#' + id + '_text_' + index}
782
+ startOffset="50%"
783
+ href={"#" + id + "_text_" + index}
712
784
  >
713
785
  {_arcs[index].displayName ||
714
786
  _arcs[index].fieldName}
@@ -736,18 +808,18 @@ const Component = memo(
736
808
  );
737
809
  }
738
810
  )}
739
- {label && <Label config={label} arcs={_arcs} judge = {judgeData} />}
811
+ {label && <Label config={label} arcs={_arcs} judge={judgeData} />}
740
812
  {current && (
741
813
  <g
742
814
  fillOpacity={y}
743
- style={{ transform: 'rotate(' + -rotate_ + 'deg)' }}
815
+ style={{ transform: "rotate(" + -rotate_ + "deg)" }}
744
816
  >
745
817
  <Current
746
818
  config={current}
747
819
  width={width}
748
820
  height={height}
749
821
  data={_arcs}
750
- judge = {judgeData}
822
+ judge={judgeData}
751
823
  currentIndex={+currentIndex}
752
824
  />
753
825
  </g>
@@ -765,7 +837,28 @@ const Component = memo(
765
837
  radius={radius}
766
838
  />
767
839
  )}
768
- <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
+ />
769
862
  </>
770
863
  );
771
864
  }
@@ -775,7 +868,14 @@ const Current = ({
775
868
  config: {
776
869
  show,
777
870
  gap,
778
- 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
+ },
779
879
  percent: {
780
880
  show: showPercent,
781
881
  sameColor: percentColor,
@@ -793,8 +893,8 @@ const Current = ({
793
893
  fontSize,
794
894
  text,
795
895
  translate: { x: translateSuffixX, y: translateSuffixY },
796
- }
797
- }
896
+ },
897
+ },
798
898
  },
799
899
  width,
800
900
  height,
@@ -804,13 +904,13 @@ const Current = ({
804
904
  }) => {
805
905
  const _data = useMemo(() => {
806
906
  const legendDataWithPercent = getDataWithPercent(data, precision);
807
- return sortPie(legendDataWithPercent, '');
907
+ return sortPie(legendDataWithPercent, "");
808
908
  }, [data, precision]);
809
-
909
+
810
910
  //数据容错,当data都为零那么需要进行以下容错
811
911
  if (judge == 0) {
812
912
  _data.forEach((d) => {
813
- d.percent = 0, d.value = 0;
913
+ (d.percent = 0), (d.value = 0);
814
914
  });
815
915
  }
816
916
 
@@ -826,34 +926,41 @@ const Current = ({
826
926
  width,
827
927
  height,
828
928
  transform: `translate(-${width / 2}px,-${height / 2}px)`,
829
- pointerEvents: 'none',
929
+ pointerEvents: "none",
830
930
  },
831
931
  boxStyle = {
832
932
  //弹性盒子样式,用于当前值的上下居中对齐等
833
933
  width,
834
934
  height,
835
- display: 'flex',
836
- flexDirection: 'column',
837
- justifyContent: 'center',
838
- alignItems: 'center',
935
+ display: "flex",
936
+ flexDirection: "column",
937
+ justifyContent: "center",
938
+ alignItems: "center",
839
939
  };
840
940
  let seriesColor = currentData.series.color;
841
941
  seriesColor =
842
- seriesColor.type == 'pure'
942
+ seriesColor.type == "pure"
843
943
  ? seriesColor.pure
844
944
  : seriesColor.linear.stops[0].color;
845
945
  return (
846
946
  show && (
847
947
  <foreignObject style={foreignStyle}>
848
948
  <div style={boxStyle}>
849
- {showName &&<TextOverflow type={textOverflow} value={nameTemp} speed={speed} style={{
850
- maxWidth,
851
- display:textOverflow=="marquee"?"flex":"bolck",
852
- justifyContent:"center",
853
- ...getFontStyle(nameFont),
854
- margin: gap / 2 + 'px 0',
855
- color: nameColor ? seriesColor : nameFont.color,
856
- }}></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
+ )}
857
964
  {
858
965
  //真实值
859
966
  showValue && (
@@ -861,12 +968,12 @@ const Current = ({
861
968
  style={{
862
969
  ...getFontStyle(valueFont),
863
970
  transform:
864
- 'translate(' +
971
+ "translate(" +
865
972
  translateValueX +
866
- 'px,' +
973
+ "px," +
867
974
  translateValueY +
868
- 'px)',
869
- margin: gap / 2 + 'px 0',
975
+ "px)",
976
+ margin: gap / 2 + "px 0",
870
977
  color: valueColor ? seriesColor : valueFont.color,
871
978
  }}
872
979
  >
@@ -874,13 +981,13 @@ const Current = ({
874
981
  {showSuffix && text && (
875
982
  <span
876
983
  style={{
877
- display:"inline-block",
984
+ display: "inline-block",
878
985
  transform:
879
- 'translate(' +
986
+ "translate(" +
880
987
  translateSuffixX +
881
- 'px,' +
988
+ "px," +
882
989
  translateSuffixY +
883
- 'px)',
990
+ "px)",
884
991
  fontSize: fontSize,
885
992
  }}
886
993
  >
@@ -896,17 +1003,17 @@ const Current = ({
896
1003
  <span
897
1004
  style={{
898
1005
  transform:
899
- 'translate(' +
1006
+ "translate(" +
900
1007
  translatePercentX +
901
- 'px,' +
1008
+ "px," +
902
1009
  translatePercentY +
903
- 'px)',
1010
+ "px)",
904
1011
  ...getFontStyle(percentFont),
905
- margin: gap / 2 + 'px 0',
1012
+ margin: gap / 2 + "px 0",
906
1013
  color: percentColor ? seriesColor : percentFont.color,
907
1014
  }}
908
1015
  >
909
- {percent + '%'}
1016
+ {percent + "%"}
910
1017
  </span>
911
1018
  )
912
1019
  }
@@ -934,13 +1041,9 @@ const Label = ({
934
1041
  text,
935
1042
  fontSize: suffixFontSize,
936
1043
  translate: { x: suffixTranslateX, y: suffixTranslateY },
937
- }
938
- },
939
- percent: {
940
- show: showPercent,
941
- font: percentFont,
942
- precision
1044
+ },
943
1045
  },
1046
+ percent: { show: showPercent, font: percentFont, precision },
944
1047
  },
945
1048
  arcs,
946
1049
  judge,
@@ -950,12 +1053,12 @@ const Label = ({
950
1053
  () => getDataWithPercent(arcs, precision),
951
1054
  [arcs, precision]
952
1055
  );
953
- //数据做出容错
1056
+ //数据做出容错
954
1057
  if (judge == 0) {
955
1058
  _arcs.forEach((d) => {
956
- d.percent=0
957
- })
958
- }
1059
+ d.percent = 0;
1060
+ });
1061
+ }
959
1062
  return (
960
1063
  <g>
961
1064
  {_arcs.map(
@@ -1003,70 +1106,90 @@ const Label = ({
1003
1106
  (_showName || showPercent || showValue) && (
1004
1107
  <g key={index}>
1005
1108
  <path
1006
- className={animation ? ringCss['label-line'] : ''}
1109
+ className={animation ? ringCss["label-line"] : ""}
1007
1110
  style={{
1008
1111
  animationDelay: `${
1009
1112
  animation ? (actualIndex + 1) * 2000 - 800 : 0
1010
1113
  }ms`,
1011
1114
  }}
1012
1115
  d={
1013
- 'M' +
1116
+ "M" +
1014
1117
  x1 +
1015
- ', ' +
1118
+ ", " +
1016
1119
  y1 +
1017
- 'L' +
1120
+ "L" +
1018
1121
  x2 +
1019
- ', ' +
1122
+ ", " +
1020
1123
  y2 +
1021
- 'L' +
1124
+ "L" +
1022
1125
  x3 +
1023
- ', ' +
1126
+ ", " +
1024
1127
  y2
1025
1128
  }
1026
1129
  stroke={
1027
1130
  lineColor
1028
1131
  ? lineColor
1029
- : type == 'pure'
1132
+ : type == "pure"
1030
1133
  ? pure
1031
1134
  : stops[0].color
1032
1135
  }
1033
- fill='none'
1136
+ fill="none"
1034
1137
  />
1035
- <foreignObject width="1" height="1" x={_x} y={y2+translateY} style={{overflow:"visible"}}>
1036
- <div className={animation? ringCss['label-text']:""} style={{
1037
- transform:"translate(0,-50%)",
1038
- whiteSpace:"nowrap",
1039
- float:x3>=0?"left":"right",
1040
- width:"max-content"
1041
- }}>
1042
- {_showName &&<TextOverflow type={textOverflow} value={displayName+((showValue || showPercent)?":":"")} speed={speed} style={{
1043
- maxWidth,
1044
- ...nameStyle,
1045
- float:mode=="horizontal"?"left":"none"
1046
- }}></TextOverflow>}
1047
- {
1048
- 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)}>
1049
1170
  {data.y}
1050
- {showSuffix && <span style={{
1051
- position:"relative",
1052
- fontSize:suffixFontSize,
1053
- marginLeft:suffixTranslateX,
1054
- top:suffixTranslateY
1055
- }}>
1056
- { text }
1057
- </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
+ )}
1058
1183
  </span>
1059
- }
1060
- {
1061
- showPercent && <span style={getFontStyle(percentFont)}>
1062
- {
1063
- (_showValue ? '(' : '') +
1184
+ )}
1185
+ {showPercent && (
1186
+ <span style={getFontStyle(percentFont)}>
1187
+ {(_showValue ? "(" : "") +
1064
1188
  percent +
1065
- '%' +
1066
- (_showValue ? '' : '')
1067
- }
1189
+ "%" +
1190
+ (_showValue ? "" : "")}
1068
1191
  </span>
1069
- }
1192
+ )}
1070
1193
  </div>
1071
1194
  </foreignObject>
1072
1195
  </g>
@@ -1096,13 +1219,9 @@ const RingLabel = ({
1096
1219
  text,
1097
1220
  fontSize: suffixFontSize,
1098
1221
  translate: { x: suffixTranslateX, y: suffixTranslateY },
1099
- }
1100
- },
1101
- percent: {
1102
- show: showPercent,
1103
- font: percentFont,
1104
- precision
1222
+ },
1105
1223
  },
1224
+ percent: { show: showPercent, font: percentFont, precision },
1106
1225
  },
1107
1226
  judge,
1108
1227
  arcs,
@@ -1111,13 +1230,13 @@ const RingLabel = ({
1111
1230
  () => getDataWithPercent(arcs, precision),
1112
1231
  [arcs, precision]
1113
1232
  );
1114
-
1115
- //数据做出容错
1116
- if (judge == 0) {
1117
- _arcs.forEach((d) => {
1118
- d.percent=0
1119
- })
1120
- }
1233
+
1234
+ //数据做出容错
1235
+ if (judge == 0) {
1236
+ _arcs.forEach((d) => {
1237
+ d.percent = 0;
1238
+ });
1239
+ }
1121
1240
 
1122
1241
  return (
1123
1242
  <g>
@@ -1166,69 +1285,89 @@ const RingLabel = ({
1166
1285
  (_showName || showPercent || _showValue) && (
1167
1286
  <g key={index}>
1168
1287
  <path
1169
- className={ringCss['label-line']}
1288
+ className={ringCss["label-line"]}
1170
1289
  style={{
1171
1290
  animationDelay: `${(actualIndex + 1) * 2000 - 800}ms`,
1172
1291
  }}
1173
1292
  d={
1174
- 'M' +
1293
+ "M" +
1175
1294
  x1 +
1176
- ', ' +
1295
+ ", " +
1177
1296
  y1 +
1178
- 'L' +
1297
+ "L" +
1179
1298
  x2 +
1180
- ', ' +
1299
+ ", " +
1181
1300
  y2 +
1182
- 'L' +
1301
+ "L" +
1183
1302
  x3 +
1184
- ', ' +
1303
+ ", " +
1185
1304
  y2
1186
1305
  }
1187
1306
  stroke={
1188
1307
  lineColor
1189
1308
  ? lineColor
1190
- : type == 'pure'
1309
+ : type == "pure"
1191
1310
  ? pure
1192
1311
  : stops[0].color
1193
1312
  }
1194
- fill='none'
1313
+ fill="none"
1195
1314
  />
1196
- <foreignObject width="1" height="1" x={_x} y={y2+translateY} style={{overflow:"visible"}}>
1197
- <div className={ringCss['label-text']} style={{
1198
- transform:"translate(0,-50%)",
1199
- whiteSpace:"nowrap",
1200
- float:x3>=0?"left":"right",
1201
- width:"max-content",
1202
- animationDelay: `${(actualIndex + 1) * 2000 - 800}ms`,
1203
- }}>
1204
- {_showName &&<TextOverflow type={textOverflow} value={displayName+((showValue || showPercent)?":":"")} speed={speed} style={{
1205
- maxWidth,
1206
- ...getFontStyle(nameFont),
1207
- float:mode=="horizontal"?"left":"none"
1208
- }}></TextOverflow>}
1209
- {
1210
- 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)}>
1211
1348
  {realData.y}
1212
- {showSuffix && <span style={{
1213
- position:"relative",
1214
- fontSize:suffixFontSize,
1215
- marginLeft:suffixTranslateX,
1216
- top:suffixTranslateY
1217
- }}>
1218
- { text }
1219
- </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
+ )}
1220
1361
  </span>
1221
- }
1222
- {
1223
- showPercent && <span style={getFontStyle(percentFont)}>
1224
- {
1225
- (_showValue ? '(' : '') +
1362
+ )}
1363
+ {showPercent && (
1364
+ <span style={getFontStyle(percentFont)}>
1365
+ {(_showValue ? "(" : "") +
1226
1366
  percent +
1227
- '%' +
1228
- (_showValue ? '' : '')
1229
- }
1367
+ "%" +
1368
+ (_showValue ? "" : "")}
1230
1369
  </span>
1231
- }
1370
+ )}
1232
1371
  </div>
1233
1372
  </foreignObject>
1234
1373
  </g>