@easyv/charts 1.7.35 → 1.7.37

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 (61) hide show
  1. package/.babelrc +8 -8
  2. package/CHANGELOG.md +18 -18
  3. package/commitlint.config.js +1 -1
  4. package/lib/components/Background.js +2 -2
  5. package/lib/components/Band.js +2 -2
  6. package/lib/components/Brush.js +2 -2
  7. package/lib/components/Chart.js +2 -2
  8. package/lib/components/ChartContainer.js +2 -2
  9. package/lib/components/ConicalGradient.js +21 -21
  10. package/lib/components/Control.js +5 -1
  11. package/lib/components/ExtentData.js +2 -2
  12. package/lib/components/Indicator.js +2 -2
  13. package/lib/components/Label.js +2 -2
  14. package/lib/components/Legend.js +38 -6
  15. package/lib/components/Lighter.js +2 -2
  16. package/lib/components/Line.js +2 -2
  17. package/lib/components/LinearGradient.js +2 -2
  18. package/lib/components/StereoBar.js +2 -2
  19. package/lib/css/index.module.css +39 -42
  20. package/lib/css/piechart.module.css +26 -26
  21. package/lib/formatter/legend.js +55 -50
  22. package/lib/hooks/useAnimateData.js +6 -6
  23. package/lib/hooks/useFilterData.js +5 -5
  24. package/lib/hooks/useStackData.js +5 -5
  25. package/lib/hooks/useTooltip.js +11 -11
  26. package/package.json +54 -54
  27. package/src/components/Background.tsx +61 -61
  28. package/src/components/Band.tsx +334 -334
  29. package/src/components/Brush.js +159 -159
  30. package/src/components/Chart.js +157 -157
  31. package/src/components/ChartContainer.tsx +71 -71
  32. package/src/components/ConicalGradient.js +258 -258
  33. package/src/components/Control.jsx +242 -242
  34. package/src/components/ExtentData.js +18 -18
  35. package/src/components/Indicator.js +61 -61
  36. package/src/components/Label.js +262 -262
  37. package/src/components/Legend.js +289 -267
  38. package/src/components/Lighter.jsx +173 -173
  39. package/src/components/Line.js +153 -153
  40. package/src/components/LinearGradient.js +29 -29
  41. package/src/components/PieTooltip.jsx +160 -160
  42. package/src/components/SplitText.tsx +70 -70
  43. package/src/components/StereoBar.tsx +307 -307
  44. package/src/components/index.js +61 -61
  45. package/src/context/index.js +2 -2
  46. package/src/css/index.module.css +39 -42
  47. package/src/css/piechart.module.css +26 -26
  48. package/src/element/ConicGradient.jsx +55 -55
  49. package/src/element/Line.tsx +33 -33
  50. package/src/element/index.ts +3 -3
  51. package/src/formatter/index.js +1 -1
  52. package/src/formatter/legend.js +122 -115
  53. package/src/hooks/index.js +20 -20
  54. package/src/hooks/useAnimateData.ts +68 -68
  55. package/src/hooks/useFilterData.js +77 -77
  56. package/src/hooks/useStackData.js +140 -140
  57. package/src/hooks/useTooltip.ts +103 -103
  58. package/src/index.js +6 -6
  59. package/src/types/index.d.ts +68 -68
  60. package/src/utils/index.js +812 -812
  61. package/tsconfig.json +23 -23
@@ -1,812 +1,812 @@
1
- import { getColor } from '@easyv/utils';
2
- import { toFixed } from '@easyv/utils/lib/common/utils';
3
- import {
4
- scaleOrdinal as ordinal,
5
- range as sequence,
6
- ascending,
7
- descending,
8
- sum,
9
- } from 'd3v7';
10
- import { renderToStaticMarkup } from 'react-dom/server';
11
- import { toPath } from 'svg-points';
12
-
13
- const defaultBackground = '#000000';
14
- const defaultIcon = {
15
- background: defaultBackground,
16
- };
17
- const defaultLineIcon = {
18
- height: 2,
19
- background: defaultBackground,
20
- };
21
- const SvgBackground = ({
22
- fill: {
23
- type,
24
- pure,
25
- linear: { angle, opacity, stops },
26
- },
27
- pattern: {
28
- path = '',
29
- width = '100%',
30
- height = '100%',
31
- boderColor: stroke = 'transparent',
32
- boderWidth = 0,
33
- },
34
- }) => {
35
- return (
36
- <svg
37
- preserveAspectRatio='none'
38
- xmlns='http://www.w3.org/2000/svg'
39
- width={width}
40
- height={height}
41
- >
42
- <defs>
43
- <linearGradient
44
- id='linearGradient'
45
- x1='0%'
46
- y1='0%'
47
- x2='0%'
48
- y2='100%'
49
- gradientTransform={'rotate(' + (angle + 180) + ', 0.5, 0.5)'}
50
- >
51
- {stops.map(({ offset, color }, index) => (
52
- <stop
53
- key={index}
54
- offset={offset + '%'}
55
- stopColor={color}
56
- stopOpacity={opacity}
57
- />
58
- ))}
59
- </linearGradient>
60
- </defs>
61
- <path
62
- d={path}
63
- fill={type === 'pure' ? pure : 'url(#linearGradient)'}
64
- stroke={stroke}
65
- strokeWidth={boderWidth}
66
- />
67
- </svg>
68
- );
69
- };
70
- const getColorList = ({ type, pure, linear: { stops, angle, opacity } }) => {
71
- if (type == 'pure') {
72
- return [
73
- { color: pure, offset: 1 },
74
- { color: pure, offset: 0 },
75
- ];
76
- }
77
- return stops.map(({ color, offset }) => ({ color, offset: offset / 100 }));
78
- };
79
- const getMultiColorStr = (colors)=>{
80
- const { stops, angle } = colors;
81
- let result = 'linear-gradient(' + angle + 'deg, ';
82
- const stops_ = JSON.parse(JSON.stringify(stops));
83
- stops_.sort((a,b)=>a.offset-b.offset);
84
- for(let i=0;i<stops_.length;i++){
85
- const { color, offset } = stops_[i];
86
- result += `${color} ${offset}%,`;
87
- }
88
- return result.slice(0,-1)+")";
89
- }
90
- const getIcon = (type, icon, lineType="solid") => {
91
- switch (type) {
92
- case 'area':
93
- case 'line':
94
- let color = icon.background;
95
- return icon
96
- ? {
97
- ...defaultLineIcon,
98
- ...icon,
99
- minWidth: icon.width,
100
- background:lineType=="solid"?color:`linear-gradient(90deg, ${color}, ${color} 66%, transparent 66%) 0 0/33% 100% repeat`
101
- }
102
- : defaultLineIcon;
103
- default:
104
- return icon
105
- ? {
106
- ...defaultIcon,
107
- ...icon,
108
- minWidth: icon.width,
109
- }
110
- : defaultIcon;
111
- }
112
- };
113
-
114
- const dateFormat = (date, fmt) => {
115
- date = new Date(date);
116
- const o = {
117
- 'M+': date.getMonth() + 1, //月份
118
- 'D+': date.getDate(), //日
119
- 'H+': date.getHours(), //小时
120
- 'h+': date.getHours() % 12 == 0 ? 12 : date.getHours() % 12, //小时
121
- 'm+': date.getMinutes(), //分
122
- 's+': date.getSeconds(), //秒
123
- S: date.getMilliseconds(), //毫秒
124
- X: '星期' + '日一二三四五六'.charAt(date.getDay()),
125
- W: new Array(
126
- 'Sunday',
127
- 'Monday',
128
- 'Tuesday',
129
- 'Wednesday',
130
- 'Thursday',
131
- 'Friday',
132
- 'Saturday'
133
- )[date.getDay()],
134
- w: new Array('Sun.', 'Mon.', ' Tues.', 'Wed.', ' Thur.', 'Fri.', 'Sat.')[
135
- date.getDay()
136
- ],
137
- };
138
- if (/(Y+)/.test(fmt))
139
- fmt = fmt.replace(
140
- RegExp.$1,
141
- (date.getFullYear() + '').substr(4 - RegExp.$1.length)
142
- );
143
- for (var k in o)
144
- if (new RegExp('(' + k + ')').test(fmt))
145
- fmt = fmt.replace(
146
- RegExp.$1,
147
- RegExp.$1.length == 1 ? o[k] : ('00' + o[k]).substr(('' + o[k]).length)
148
- );
149
- return fmt;
150
- };
151
- const getBreakWord = (str, breakNumber) => {
152
- const re = new RegExp('([^]){1,' + breakNumber + '}', 'g');
153
- return str.match(re);
154
- };
155
-
156
- //x轴标签逻辑
157
- const getTicksOfAxis = (domain, ticksCount, showLast) => {
158
- let len = domain.length;
159
- if (ticksCount < 2 || ticksCount > len) return domain;
160
- let step = Math.floor((len - ticksCount) / (ticksCount - 1));
161
- let ticksArr = [];
162
- if (showLast) {
163
- let count = ticksCount, gap = 0;
164
- step = (len - 1) / (count - 1);
165
- const maxGap = Math.max(count-2,len-count);
166
- //循环计算出最接近count值且能让step为整数的值
167
- if(!Number.isInteger(step)){
168
- while(gap<=maxGap){
169
- gap++;
170
- const left = (len-1)/(count-gap-1), right = (len-1)/(count+gap-1);
171
- if(Number.isInteger(left)){
172
- step = left;
173
- break;
174
- }
175
- if(Number.isInteger(right)){
176
- step = right;
177
- break;
178
- }
179
- }
180
- }
181
- if(!Number.isInteger(step)) step = 1; //如果找不到整数的step,直接取1,返回所有刻度
182
- ticksArr = domain.filter(function (d, i) {
183
- return i % step === 0;
184
- });
185
- }else{
186
- ticksArr = domain.filter(function (d, i) {
187
- return i % (step + 1) === 0;
188
- });
189
- }
190
- return ticksArr;
191
- };
192
-
193
- const getTickCoord = ({
194
- orientation,
195
- coordinate,
196
- tickSize = 6,
197
- x = 0,
198
- y = 0,
199
- }) => {
200
- let x1, x2, y1, y2;
201
- switch (orientation) {
202
- case 'top':
203
- x1 = x2 = coordinate;
204
- y2 = y;
205
- y1 = y2 - tickSize;
206
- break;
207
- case 'left':
208
- y1 = y2 = coordinate;
209
- x2 = x;
210
- x1 = x2 - tickSize;
211
- break;
212
- case 'right':
213
- y1 = y2 = coordinate;
214
- x2 = x;
215
- x1 = x2 + tickSize;
216
- break;
217
- default:
218
- x1 = x2 = coordinate;
219
- y2 = y;
220
- y1 = y2 + tickSize;
221
- break;
222
- }
223
- return { x1, x2, y1, y2 };
224
- };
225
- const getGridCoord = ({ orientation, coordinate, end }) => {
226
- let x1, x2, y1, y2;
227
- switch (orientation) {
228
- case 'top':
229
- x1 = x2 = coordinate;
230
- y1 = 0;
231
- y2 = end;
232
- break;
233
- case 'bottom':
234
- x1 = x2 = coordinate;
235
- y1 = 0;
236
- y2 = end * -1;
237
- break;
238
- case 'left':
239
- y1 = y2 = coordinate;
240
- x1 = 0;
241
- x2 = end;
242
- break;
243
- case 'right':
244
- y1 = y2 = coordinate;
245
- x1 = 0;
246
- x2 = end * -1;
247
- break;
248
- }
249
- return { x1, x2, y1, y2 };
250
- };
251
-
252
- const identity = (d) => d;
253
-
254
- //获取鼠标指针坐标
255
- const getMousePos = (evt, dom) => {
256
- var rect = dom.getBoundingClientRect();
257
- return {
258
- x: evt.clientX - rect.left,
259
- y: evt.clientY - rect.top,
260
- w: rect.width,
261
- h: rect.height,
262
- };
263
- };
264
-
265
- const getFontStyle = (
266
- { color, bold, italic, fontSize, fontFamily, letterSpacing },
267
- type
268
- ) => {
269
- if (type == 'svg') {
270
- return {
271
- fontSize,
272
- fontFamily,
273
- letterSpacing,
274
- fill: color,
275
- fontWeight: bold ? 'bold' : 'normal',
276
- fontStyle: italic ? 'italic' : 'normal',
277
- };
278
- }
279
- return {
280
- fontSize,
281
- fontFamily,
282
- letterSpacing,
283
- color,
284
- fontWeight: bold ? 'bold' : 'normal',
285
- fontStyle: italic ? 'italic' : 'normal',
286
- };
287
- };
288
- const formatFont=({ color, fill, bold, italic, ...rest },
289
- type)=>{
290
- if (type == 'svg') {
291
- return {
292
- fill: fill || color,
293
- fontWeight: typeof bold=="string" ? bold : ( bold ? 'bold' : 'normal'),
294
- fontStyle: typeof italic=="string"? italic : (italic ? 'italic' : 'normal'),
295
- ...rest
296
- };
297
- }
298
- return {
299
- color:color|| fill,
300
- fontWeight: typeof bold=="string" ? bold : ( bold ? 'bold' : 'normal'),
301
- fontStyle: typeof italic=="string"? italic : (italic ? 'italic' : 'normal'),
302
- ...rest
303
- };
304
- }
305
-
306
- const getMargin = ({ marginTop, marginRight, marginBottom, marginLeft }) =>
307
- marginTop +
308
- 'px ' +
309
- marginRight +
310
- 'px ' +
311
- marginBottom +
312
- 'px ' +
313
- marginLeft +
314
- 'px';
315
- const getTranslate3d = ({ x = 0, y = 0, z = 0 }) =>
316
- 'translate3d(' + x + 'px, ' + y + 'px, ' + z + 'px)';
317
- const getTranslate2d = ({ x = 0, y = 0 }) => 'translate(' + x + ', ' + y + ')';
318
- function band() {
319
- var scale = ordinal().unknown(undefined),
320
- domain = scale.domain,
321
- ordinalRange = scale.range,
322
- r0 = 0,
323
- r1 = 1,
324
- step,
325
- bandwidth,
326
- round = false,
327
- paddingInner = 0,
328
- paddingOuter = 0,
329
- // seriesPaddingInner = 0,
330
- // seriesPaddingOuter = 0,
331
- // seriesLength = 0,
332
- align = 0.5;
333
-
334
- delete scale.unknown;
335
-
336
- function rescale() {
337
- var n = domain().length,
338
- reverse = r1 < r0,
339
- start = reverse ? r1 : r0,
340
- stop = reverse ? r0 : r1;
341
- step = (stop - start) / Math.max(1, n - paddingOuter * 2);
342
- if (round) step = Math.floor(step);
343
- start += (stop - start - step * n) * align;
344
- bandwidth = step;
345
- if (round) (start = Math.round(start)), (bandwidth = Math.round(bandwidth));
346
- var values = sequence(n).map(function (i) {
347
- return start + step * i + step / 2;
348
- });
349
- return ordinalRange(reverse ? values.reverse() : values);
350
- }
351
-
352
- scale.domain = function (_) {
353
- return arguments.length ? (domain(_), rescale()) : domain();
354
- };
355
-
356
- scale.range = function (_) {
357
- return arguments.length
358
- ? (([r0, r1] = _), (r0 = +r0), (r1 = +r1), rescale())
359
- : [r0, r1];
360
- };
361
-
362
- scale.rangeRound = function (_) {
363
- return ([r0, r1] = _), (r0 = +r0), (r1 = +r1), (round = true), rescale();
364
- };
365
-
366
- scale.bandwidth = function () {
367
- return bandwidth;
368
- };
369
-
370
- scale.step = function () {
371
- return step;
372
- };
373
-
374
- scale.seriesBandwidth = function () {
375
- return seriesBandwidth;
376
- };
377
-
378
- scale.seriesStep = function () {
379
- return seriesStep;
380
- };
381
-
382
- scale.round = function (_) {
383
- return arguments.length ? ((round = !!_), rescale()) : round;
384
- };
385
-
386
- scale.padding = function (_) {
387
- return arguments.length
388
- ? ((paddingInner = Math.min(1, (paddingOuter = +_))), rescale())
389
- : paddingInner;
390
- };
391
-
392
- scale.paddingInner = function (_) {
393
- return arguments.length
394
- ? ((paddingInner = Math.min(1, _)), rescale())
395
- : paddingInner;
396
- };
397
-
398
- scale.paddingOuter = function (_) {
399
- return arguments.length ? ((paddingOuter = +_), rescale()) : paddingOuter;
400
- };
401
-
402
- scale.align = function (_) {
403
- return arguments.length
404
- ? ((align = Math.max(0, Math.min(1, _))), rescale())
405
- : align;
406
- };
407
-
408
- scale.copy = function () {
409
- return band(domain(), [r0, r1])
410
- .round(round)
411
- .paddingInner(paddingInner)
412
- .paddingOuter(paddingOuter)
413
- .align(align);
414
- };
415
-
416
- return initRange.apply(rescale(), arguments);
417
- }
418
-
419
- function initRange(domain, range) {
420
- switch (arguments.length) {
421
- case 0:
422
- break;
423
- case 1:
424
- this.range(domain);
425
- break;
426
- default:
427
- this.range(range).domain(domain);
428
- break;
429
- }
430
- return this;
431
- }
432
-
433
- const getStacks = (series) => {
434
- const tmp = [];
435
- series.forEach(({ type, stack, yOrZ }, name) => {
436
- const current = tmp.find(
437
- ({ type: _type, stack: _stack, yOrZ: _yOrZ }) =>
438
- _type == type && stack && _stack == stack && yOrZ == _yOrZ
439
- );
440
- if (!current) {
441
- const common = {
442
- type,
443
- stack,
444
- positive: 0,
445
- negative: 0,
446
- yOrZ,
447
- s: [name],
448
- };
449
- if (type === 'band') {
450
- const index = tmp.filter((item) => item.type === 'band').length;
451
- tmp.push({
452
- ...common,
453
- index,
454
- });
455
- } else {
456
- tmp.push({
457
- ...common,
458
- index: 0,
459
- });
460
- }
461
- } else {
462
- current.s.push(name);
463
- }
464
- });
465
- return tmp;
466
- };
467
-
468
- const dataYOrZ = (data, { y: seriesY, z: seriesZ }) => {
469
- const tmp = {
470
- y: [],
471
- z: [],
472
- };
473
- for (let i = 0, j = data.length; i < j; i++) {
474
- const d = data[i];
475
- if (seriesY.get(d.s)) {
476
- tmp.y.push(d);
477
- continue;
478
- }
479
- if (seriesZ.get(d.s)) {
480
- tmp.z.push(d);
481
- }
482
- }
483
- return tmp;
484
- };
485
-
486
- const seriesYOrZ = (series) => {
487
- const y = new Map();
488
- const z = new Map();
489
- series.forEach((value, key) => {
490
- if (value.yOrZ === 'y') {
491
- y.set(key, value);
492
- } else {
493
- z.set(key, value);
494
- }
495
- });
496
- return { y, z };
497
- };
498
-
499
- const resetStacks = (stacks) => {
500
- stacks.forEach((stack) => {
501
- stack.positive = 0;
502
- stack.negative = 0;
503
- });
504
- };
505
-
506
- const getCurrentStack = (stack, stackMap) =>
507
- stackMap.find(
508
- ({ stack: _stack, type: _type, yOrZ: _yOrZ, s: _s }) =>
509
- _type == stack.type &&
510
- _stack == stack.stack &&
511
- _yOrZ == stack.yOrZ &&
512
- _s.includes(stack.name)
513
- );
514
-
515
- const getBandBackground = (pattern, fill) => {
516
- if (!(pattern && pattern.path)) return getColor(fill);
517
- try{
518
- const { backgroundSize = '100% 100%', ..._pattern } = pattern;
519
- return (
520
- 'center top / ' +
521
- backgroundSize +
522
- ' url("data:image/svg+xml,' +
523
- encodeURIComponent(
524
- renderToStaticMarkup(<SvgBackground fill={fill} pattern={_pattern} />)
525
- ) +
526
- '")'
527
- );
528
- }catch(e){}
529
- return "";
530
- };
531
- const getBandwidth = (step, paddingOuter) => step * (1 - paddingOuter);
532
-
533
- const getBandSeriesStepAndWidth = ({ width, paddingInner, bandLength }) => {
534
- const seriesStep = width / (bandLength == 0 ? 1 : bandLength);
535
- const seriesWidth = seriesStep * (1 - paddingInner);
536
- return {
537
- seriesStep,
538
- seriesWidth,
539
- };
540
- };
541
-
542
- const getSeriesInfo = ({
543
- step,
544
- bandLength = 1,
545
- paddingInner = 0,
546
- paddingOuter = 0,
547
- }) => {
548
- if (bandLength == 0)
549
- return {
550
- seriesWidth: step,
551
- seriesStep: step,
552
- seriesStart: 0,
553
- width: step,
554
- };
555
- const _step =
556
- step / (bandLength + paddingOuter * 2 + paddingInner * (bandLength - 1));
557
- return {
558
- seriesWidth: _step,
559
- seriesStep: (1 + paddingInner) * _step,
560
- seriesStart: paddingOuter * _step,
561
- width: step - paddingOuter * 2 * _step,
562
- };
563
- };
564
-
565
- const isValidHttpUrl = (string) => {
566
- let url;
567
-
568
- try {
569
- url = new URL(string);
570
- } catch (_) {
571
- return false;
572
- }
573
-
574
- return url.protocol === 'http:' || url.protocol === 'https:';
575
- };
576
-
577
- const getChildren = (svgStr) => {
578
- const wrapper = document.createElement('div');
579
- wrapper.innerHTML = svgStr;
580
- const { childNodes } = wrapper;
581
- const svgDom = [...childNodes].find((item) => item.tagName === 'svg');
582
-
583
- if (!!svgDom) {
584
- return [...svgDom.childNodes];
585
- }
586
-
587
- return null;
588
- };
589
-
590
- const filterChildren = (children, tagNames) => {
591
- return children.reduce((prev, node) => {
592
- let { nodeName } = node;
593
-
594
- if (tagNames.indexOf(nodeName) > -1) {
595
- if (nodeName === 'g') {
596
- return filterChildren([...node.childNodes], tagNames);
597
- } else {
598
- prev.push(node);
599
- }
600
- }
601
-
602
- return prev;
603
- }, []);
604
- };
605
-
606
- const getDomPath = (node) => {
607
- switch (node.nodeName) {
608
- case 'circle':
609
- return toPath({
610
- type: 'circle',
611
- cx: +node.getAttribute('cx') || 0,
612
- cy: +node.getAttribute('cy') || 0,
613
- r: +node.getAttribute('r') || 0,
614
- });
615
-
616
- case 'ellipse':
617
- return toPath({
618
- type: 'ellipse',
619
- cx: +node.getAttribute('cx') || 0,
620
- cy: +node.getAttribute('cy') || 0,
621
- rx: +node.getAttribute('rx') || 0,
622
- ry: +node.getAttribute('ry') || 0,
623
- });
624
-
625
- case 'line':
626
- return toPath({
627
- type: 'line',
628
- x1: +node.getAttribute('x1') || 0,
629
- x2: +node.getAttribute('x2') || 0,
630
- y1: +node.getAttribute('y1') || 0,
631
- y2: +node.getAttribute('y2') || 0,
632
- });
633
-
634
- case 'path':
635
- return toPath({
636
- type: 'path',
637
- d: node.getAttribute('d') || '',
638
- });
639
-
640
- case 'polygon':
641
- return toPath({
642
- type: 'polyline',
643
- points: node.getAttribute('points') || '',
644
- });
645
-
646
- case 'polyline':
647
- return toPath({
648
- type: 'polyline',
649
- points: node.getAttribute('points') || '',
650
- });
651
-
652
- case 'rect':
653
- return toPath({
654
- type: 'rect',
655
- height: +node.getAttribute('height') || 0,
656
- width: +node.getAttribute('width') || 0,
657
- x: +node.getAttribute('x') || 0,
658
- y: +node.getAttribute('y') || 0,
659
- rx: +node.getAttribute('rx') || 0,
660
- ry: +node.getAttribute('ry') || 0,
661
- });
662
- }
663
- };
664
-
665
- const sortPie = (data, order) => {
666
- const _data = data.map((item) => ({ ...item }));
667
- switch (order) {
668
- case '':
669
- _data.sort(({ index: a }, { index: b }) => ascending(a, b));
670
- break;
671
- case 'desc':
672
- _data.sort(({ value: a }, { value: b }) => descending(a, b));
673
- break;
674
- case 'asc':
675
- _data.sort(({ value: a }, { value: b }) => ascending(a, b));
676
- break;
677
- }
678
- return _data;
679
- };
680
-
681
- // const getDataWithPercent = (data = [], precision = 0, type) => {
682
- // const digits = Math.pow(10, precision);
683
- // const targetSeats = digits * 100;
684
-
685
- // const total = sum(data, (d) => d.value);
686
-
687
- // const votesPerQuota = data.map((d, index) => ({
688
- // ...d,
689
- // vote: Math.round((d.value / total) * digits * 100),
690
- // index,
691
- // }));
692
- // const currentSum = sum(votesPerQuota, (d) => d.vote);
693
- // const remainder = targetSeats - currentSum;
694
- // console.log(type+":",votesPerQuota, toFixed);
695
- // votesPerQuota.sort(({ value: a }, { value: b }) => (a % total) - (b % total));
696
-
697
- // const tmp = votesPerQuota.map(({ vote, ...data }, index) => ({
698
- // ...data,
699
- // percent: toFixed((vote + (index < remainder ? 1 : 0)) / digits, precision),
700
- // }));
701
-
702
- // return tmp;
703
- // };
704
-
705
- const getDataWithPercent = (data = [], precision = 0) => {
706
- let objData = [];
707
- function getPercentWithPrecision(valueList, idx, precision) {
708
- if (!valueList[idx]) {
709
- return 0;
710
- }
711
- const sum = valueList.reduce( function (acc, val) {
712
- return acc + val.value;
713
- }, 0);
714
- if (sum === 0) {
715
- return 0;
716
- }
717
- const digits = Math.pow(10, precision);
718
- const votesPerQuota = valueList.map(function (val) {
719
- return val.value / sum * digits * 100;
720
- });
721
- const targetSeats = digits * 100;
722
- const seats = votesPerQuota.map(function (votes) {
723
- return Math.floor(votes);
724
- });
725
- let currentSum = seats.reduce( function (acc, val) {
726
- return acc + val;
727
- }, 0);
728
- const remainder = votesPerQuota.map(function (votes, idx) {
729
- return votes - seats[idx];
730
- });
731
- while (currentSum < targetSeats) {
732
- let max = Number.NEGATIVE_INFINITY;
733
- let maxId = null;
734
- for (let i = 0, len = remainder.length; i < len; ++i) {
735
- if (remainder[i] > max) {
736
- max = remainder[i];
737
- maxId = i;
738
- }
739
- }
740
- ++seats[maxId];
741
- remainder[maxId] = 0;
742
- ++currentSum;
743
- }
744
- return seats[idx] / digits;
745
- }
746
- data.forEach((d, i) => {
747
- objData.push({
748
- ...d,
749
- percent: getPercentWithPrecision(data, i, precision)
750
- })
751
- });
752
- return objData
753
- };
754
-
755
- const excludeTypes = ['array', 'object', 'group', 'modal', 'colors'];
756
- const reduceConfig = (config = []) => {
757
- if (!Array.isArray(config)) {
758
- return config;
759
- }
760
- let output = {};
761
- for (let i = 0, len = config.length; i < len; i++) {
762
- let type = config[i]._type;
763
-
764
- output[config[i]._name] =
765
- type && !excludeTypes.includes(type)
766
- ? config[i]._value
767
- : reduceConfig(config[i]._value);
768
- }
769
- return output;
770
- };
771
-
772
- //限制value的值在min和max之间
773
- const mathR=(value, range)=>{
774
- const [min,max] = range;
775
- return Math.max(min,Math.min(value,max));
776
- }
777
-
778
- export {
779
- dateFormat,
780
- getBreakWord,
781
- getTicksOfAxis,
782
- getTickCoord,
783
- getGridCoord,
784
- identity,
785
- getMousePos,
786
- getFontStyle,
787
- formatFont,
788
- getMargin,
789
- getTranslate3d,
790
- getTranslate2d,
791
- band,
792
- getIcon,
793
- getColorList,
794
- getMultiColorStr,
795
- getStacks,
796
- dataYOrZ,
797
- seriesYOrZ,
798
- resetStacks,
799
- getCurrentStack,
800
- getBandBackground,
801
- getBandwidth,
802
- getBandSeriesStepAndWidth,
803
- isValidHttpUrl,
804
- getChildren,
805
- filterChildren,
806
- getDomPath,
807
- sortPie,
808
- getDataWithPercent,
809
- reduceConfig,
810
- getSeriesInfo,
811
- mathR
812
- };
1
+ import { getColor } from '@easyv/utils';
2
+ import { toFixed } from '@easyv/utils/lib/common/utils';
3
+ import {
4
+ scaleOrdinal as ordinal,
5
+ range as sequence,
6
+ ascending,
7
+ descending,
8
+ sum,
9
+ } from 'd3v7';
10
+ import { renderToStaticMarkup } from 'react-dom/server';
11
+ import { toPath } from 'svg-points';
12
+
13
+ const defaultBackground = '#000000';
14
+ const defaultIcon = {
15
+ background: defaultBackground,
16
+ };
17
+ const defaultLineIcon = {
18
+ height: 2,
19
+ background: defaultBackground,
20
+ };
21
+ const SvgBackground = ({
22
+ fill: {
23
+ type,
24
+ pure,
25
+ linear: { angle, opacity, stops },
26
+ },
27
+ pattern: {
28
+ path = '',
29
+ width = '100%',
30
+ height = '100%',
31
+ boderColor: stroke = 'transparent',
32
+ boderWidth = 0,
33
+ },
34
+ }) => {
35
+ return (
36
+ <svg
37
+ preserveAspectRatio='none'
38
+ xmlns='http://www.w3.org/2000/svg'
39
+ width={width}
40
+ height={height}
41
+ >
42
+ <defs>
43
+ <linearGradient
44
+ id='linearGradient'
45
+ x1='0%'
46
+ y1='0%'
47
+ x2='0%'
48
+ y2='100%'
49
+ gradientTransform={'rotate(' + (angle + 180) + ', 0.5, 0.5)'}
50
+ >
51
+ {stops.map(({ offset, color }, index) => (
52
+ <stop
53
+ key={index}
54
+ offset={offset + '%'}
55
+ stopColor={color}
56
+ stopOpacity={opacity}
57
+ />
58
+ ))}
59
+ </linearGradient>
60
+ </defs>
61
+ <path
62
+ d={path}
63
+ fill={type === 'pure' ? pure : 'url(#linearGradient)'}
64
+ stroke={stroke}
65
+ strokeWidth={boderWidth}
66
+ />
67
+ </svg>
68
+ );
69
+ };
70
+ const getColorList = ({ type, pure, linear: { stops, angle, opacity } }) => {
71
+ if (type == 'pure') {
72
+ return [
73
+ { color: pure, offset: 1 },
74
+ { color: pure, offset: 0 },
75
+ ];
76
+ }
77
+ return stops.map(({ color, offset }) => ({ color, offset: offset / 100 }));
78
+ };
79
+ const getMultiColorStr = (colors)=>{
80
+ const { stops, angle } = colors;
81
+ let result = 'linear-gradient(' + angle + 'deg, ';
82
+ const stops_ = JSON.parse(JSON.stringify(stops));
83
+ stops_.sort((a,b)=>a.offset-b.offset);
84
+ for(let i=0;i<stops_.length;i++){
85
+ const { color, offset } = stops_[i];
86
+ result += `${color} ${offset}%,`;
87
+ }
88
+ return result.slice(0,-1)+")";
89
+ }
90
+ const getIcon = (type, icon, lineType="solid") => {
91
+ switch (type) {
92
+ case 'area':
93
+ case 'line':
94
+ let color = icon.background;
95
+ return icon
96
+ ? {
97
+ ...defaultLineIcon,
98
+ ...icon,
99
+ minWidth: icon.width,
100
+ background:lineType=="solid"?color:`linear-gradient(90deg, ${color}, ${color} 66%, transparent 66%) 0 0/33% 100% repeat`
101
+ }
102
+ : defaultLineIcon;
103
+ default:
104
+ return icon
105
+ ? {
106
+ ...defaultIcon,
107
+ ...icon,
108
+ minWidth: icon.width,
109
+ }
110
+ : defaultIcon;
111
+ }
112
+ };
113
+
114
+ const dateFormat = (date, fmt) => {
115
+ date = new Date(date);
116
+ const o = {
117
+ 'M+': date.getMonth() + 1, //月份
118
+ 'D+': date.getDate(), //日
119
+ 'H+': date.getHours(), //小时
120
+ 'h+': date.getHours() % 12 == 0 ? 12 : date.getHours() % 12, //小时
121
+ 'm+': date.getMinutes(), //分
122
+ 's+': date.getSeconds(), //秒
123
+ S: date.getMilliseconds(), //毫秒
124
+ X: '星期' + '日一二三四五六'.charAt(date.getDay()),
125
+ W: new Array(
126
+ 'Sunday',
127
+ 'Monday',
128
+ 'Tuesday',
129
+ 'Wednesday',
130
+ 'Thursday',
131
+ 'Friday',
132
+ 'Saturday'
133
+ )[date.getDay()],
134
+ w: new Array('Sun.', 'Mon.', ' Tues.', 'Wed.', ' Thur.', 'Fri.', 'Sat.')[
135
+ date.getDay()
136
+ ],
137
+ };
138
+ if (/(Y+)/.test(fmt))
139
+ fmt = fmt.replace(
140
+ RegExp.$1,
141
+ (date.getFullYear() + '').substr(4 - RegExp.$1.length)
142
+ );
143
+ for (var k in o)
144
+ if (new RegExp('(' + k + ')').test(fmt))
145
+ fmt = fmt.replace(
146
+ RegExp.$1,
147
+ RegExp.$1.length == 1 ? o[k] : ('00' + o[k]).substr(('' + o[k]).length)
148
+ );
149
+ return fmt;
150
+ };
151
+ const getBreakWord = (str, breakNumber) => {
152
+ const re = new RegExp('([^]){1,' + breakNumber + '}', 'g');
153
+ return str.match(re);
154
+ };
155
+
156
+ //x轴标签逻辑
157
+ const getTicksOfAxis = (domain, ticksCount, showLast) => {
158
+ let len = domain.length;
159
+ if (ticksCount < 2 || ticksCount > len) return domain;
160
+ let step = Math.floor((len - ticksCount) / (ticksCount - 1));
161
+ let ticksArr = [];
162
+ if (showLast) {
163
+ let count = ticksCount, gap = 0;
164
+ step = (len - 1) / (count - 1);
165
+ const maxGap = Math.max(count-2,len-count);
166
+ //循环计算出最接近count值且能让step为整数的值
167
+ if(!Number.isInteger(step)){
168
+ while(gap<=maxGap){
169
+ gap++;
170
+ const left = (len-1)/(count-gap-1), right = (len-1)/(count+gap-1);
171
+ if(Number.isInteger(left)){
172
+ step = left;
173
+ break;
174
+ }
175
+ if(Number.isInteger(right)){
176
+ step = right;
177
+ break;
178
+ }
179
+ }
180
+ }
181
+ if(!Number.isInteger(step)) step = 1; //如果找不到整数的step,直接取1,返回所有刻度
182
+ ticksArr = domain.filter(function (d, i) {
183
+ return i % step === 0;
184
+ });
185
+ }else{
186
+ ticksArr = domain.filter(function (d, i) {
187
+ return i % (step + 1) === 0;
188
+ });
189
+ }
190
+ return ticksArr;
191
+ };
192
+
193
+ const getTickCoord = ({
194
+ orientation,
195
+ coordinate,
196
+ tickSize = 6,
197
+ x = 0,
198
+ y = 0,
199
+ }) => {
200
+ let x1, x2, y1, y2;
201
+ switch (orientation) {
202
+ case 'top':
203
+ x1 = x2 = coordinate;
204
+ y2 = y;
205
+ y1 = y2 - tickSize;
206
+ break;
207
+ case 'left':
208
+ y1 = y2 = coordinate;
209
+ x2 = x;
210
+ x1 = x2 - tickSize;
211
+ break;
212
+ case 'right':
213
+ y1 = y2 = coordinate;
214
+ x2 = x;
215
+ x1 = x2 + tickSize;
216
+ break;
217
+ default:
218
+ x1 = x2 = coordinate;
219
+ y2 = y;
220
+ y1 = y2 + tickSize;
221
+ break;
222
+ }
223
+ return { x1, x2, y1, y2 };
224
+ };
225
+ const getGridCoord = ({ orientation, coordinate, end }) => {
226
+ let x1, x2, y1, y2;
227
+ switch (orientation) {
228
+ case 'top':
229
+ x1 = x2 = coordinate;
230
+ y1 = 0;
231
+ y2 = end;
232
+ break;
233
+ case 'bottom':
234
+ x1 = x2 = coordinate;
235
+ y1 = 0;
236
+ y2 = end * -1;
237
+ break;
238
+ case 'left':
239
+ y1 = y2 = coordinate;
240
+ x1 = 0;
241
+ x2 = end;
242
+ break;
243
+ case 'right':
244
+ y1 = y2 = coordinate;
245
+ x1 = 0;
246
+ x2 = end * -1;
247
+ break;
248
+ }
249
+ return { x1, x2, y1, y2 };
250
+ };
251
+
252
+ const identity = (d) => d;
253
+
254
+ //获取鼠标指针坐标
255
+ const getMousePos = (evt, dom) => {
256
+ var rect = dom.getBoundingClientRect();
257
+ return {
258
+ x: evt.clientX - rect.left,
259
+ y: evt.clientY - rect.top,
260
+ w: rect.width,
261
+ h: rect.height,
262
+ };
263
+ };
264
+
265
+ const getFontStyle = (
266
+ { color, bold, italic, fontSize, fontFamily, letterSpacing },
267
+ type
268
+ ) => {
269
+ if (type == 'svg') {
270
+ return {
271
+ fontSize,
272
+ fontFamily,
273
+ letterSpacing,
274
+ fill: color,
275
+ fontWeight: bold ? 'bold' : 'normal',
276
+ fontStyle: italic ? 'italic' : 'normal',
277
+ };
278
+ }
279
+ return {
280
+ fontSize,
281
+ fontFamily,
282
+ letterSpacing,
283
+ color,
284
+ fontWeight: bold ? 'bold' : 'normal',
285
+ fontStyle: italic ? 'italic' : 'normal',
286
+ };
287
+ };
288
+ const formatFont=({ color, fill, bold, italic, ...rest },
289
+ type)=>{
290
+ if (type == 'svg') {
291
+ return {
292
+ fill: fill || color,
293
+ fontWeight: typeof bold=="string" ? bold : ( bold ? 'bold' : 'normal'),
294
+ fontStyle: typeof italic=="string"? italic : (italic ? 'italic' : 'normal'),
295
+ ...rest
296
+ };
297
+ }
298
+ return {
299
+ color:color|| fill,
300
+ fontWeight: typeof bold=="string" ? bold : ( bold ? 'bold' : 'normal'),
301
+ fontStyle: typeof italic=="string"? italic : (italic ? 'italic' : 'normal'),
302
+ ...rest
303
+ };
304
+ }
305
+
306
+ const getMargin = ({ marginTop, marginRight, marginBottom, marginLeft }) =>
307
+ marginTop +
308
+ 'px ' +
309
+ marginRight +
310
+ 'px ' +
311
+ marginBottom +
312
+ 'px ' +
313
+ marginLeft +
314
+ 'px';
315
+ const getTranslate3d = ({ x = 0, y = 0, z = 0 }) =>
316
+ 'translate3d(' + x + 'px, ' + y + 'px, ' + z + 'px)';
317
+ const getTranslate2d = ({ x = 0, y = 0 }) => 'translate(' + x + ', ' + y + ')';
318
+ function band() {
319
+ var scale = ordinal().unknown(undefined),
320
+ domain = scale.domain,
321
+ ordinalRange = scale.range,
322
+ r0 = 0,
323
+ r1 = 1,
324
+ step,
325
+ bandwidth,
326
+ round = false,
327
+ paddingInner = 0,
328
+ paddingOuter = 0,
329
+ // seriesPaddingInner = 0,
330
+ // seriesPaddingOuter = 0,
331
+ // seriesLength = 0,
332
+ align = 0.5;
333
+
334
+ delete scale.unknown;
335
+
336
+ function rescale() {
337
+ var n = domain().length,
338
+ reverse = r1 < r0,
339
+ start = reverse ? r1 : r0,
340
+ stop = reverse ? r0 : r1;
341
+ step = (stop - start) / Math.max(1, n - paddingOuter * 2);
342
+ if (round) step = Math.floor(step);
343
+ start += (stop - start - step * n) * align;
344
+ bandwidth = step;
345
+ if (round) (start = Math.round(start)), (bandwidth = Math.round(bandwidth));
346
+ var values = sequence(n).map(function (i) {
347
+ return start + step * i + step / 2;
348
+ });
349
+ return ordinalRange(reverse ? values.reverse() : values);
350
+ }
351
+
352
+ scale.domain = function (_) {
353
+ return arguments.length ? (domain(_), rescale()) : domain();
354
+ };
355
+
356
+ scale.range = function (_) {
357
+ return arguments.length
358
+ ? (([r0, r1] = _), (r0 = +r0), (r1 = +r1), rescale())
359
+ : [r0, r1];
360
+ };
361
+
362
+ scale.rangeRound = function (_) {
363
+ return ([r0, r1] = _), (r0 = +r0), (r1 = +r1), (round = true), rescale();
364
+ };
365
+
366
+ scale.bandwidth = function () {
367
+ return bandwidth;
368
+ };
369
+
370
+ scale.step = function () {
371
+ return step;
372
+ };
373
+
374
+ scale.seriesBandwidth = function () {
375
+ return seriesBandwidth;
376
+ };
377
+
378
+ scale.seriesStep = function () {
379
+ return seriesStep;
380
+ };
381
+
382
+ scale.round = function (_) {
383
+ return arguments.length ? ((round = !!_), rescale()) : round;
384
+ };
385
+
386
+ scale.padding = function (_) {
387
+ return arguments.length
388
+ ? ((paddingInner = Math.min(1, (paddingOuter = +_))), rescale())
389
+ : paddingInner;
390
+ };
391
+
392
+ scale.paddingInner = function (_) {
393
+ return arguments.length
394
+ ? ((paddingInner = Math.min(1, _)), rescale())
395
+ : paddingInner;
396
+ };
397
+
398
+ scale.paddingOuter = function (_) {
399
+ return arguments.length ? ((paddingOuter = +_), rescale()) : paddingOuter;
400
+ };
401
+
402
+ scale.align = function (_) {
403
+ return arguments.length
404
+ ? ((align = Math.max(0, Math.min(1, _))), rescale())
405
+ : align;
406
+ };
407
+
408
+ scale.copy = function () {
409
+ return band(domain(), [r0, r1])
410
+ .round(round)
411
+ .paddingInner(paddingInner)
412
+ .paddingOuter(paddingOuter)
413
+ .align(align);
414
+ };
415
+
416
+ return initRange.apply(rescale(), arguments);
417
+ }
418
+
419
+ function initRange(domain, range) {
420
+ switch (arguments.length) {
421
+ case 0:
422
+ break;
423
+ case 1:
424
+ this.range(domain);
425
+ break;
426
+ default:
427
+ this.range(range).domain(domain);
428
+ break;
429
+ }
430
+ return this;
431
+ }
432
+
433
+ const getStacks = (series) => {
434
+ const tmp = [];
435
+ series.forEach(({ type, stack, yOrZ }, name) => {
436
+ const current = tmp.find(
437
+ ({ type: _type, stack: _stack, yOrZ: _yOrZ }) =>
438
+ _type == type && stack && _stack == stack && yOrZ == _yOrZ
439
+ );
440
+ if (!current) {
441
+ const common = {
442
+ type,
443
+ stack,
444
+ positive: 0,
445
+ negative: 0,
446
+ yOrZ,
447
+ s: [name],
448
+ };
449
+ if (type === 'band') {
450
+ const index = tmp.filter((item) => item.type === 'band').length;
451
+ tmp.push({
452
+ ...common,
453
+ index,
454
+ });
455
+ } else {
456
+ tmp.push({
457
+ ...common,
458
+ index: 0,
459
+ });
460
+ }
461
+ } else {
462
+ current.s.push(name);
463
+ }
464
+ });
465
+ return tmp;
466
+ };
467
+
468
+ const dataYOrZ = (data, { y: seriesY, z: seriesZ }) => {
469
+ const tmp = {
470
+ y: [],
471
+ z: [],
472
+ };
473
+ for (let i = 0, j = data.length; i < j; i++) {
474
+ const d = data[i];
475
+ if (seriesY.get(d.s)) {
476
+ tmp.y.push(d);
477
+ continue;
478
+ }
479
+ if (seriesZ.get(d.s)) {
480
+ tmp.z.push(d);
481
+ }
482
+ }
483
+ return tmp;
484
+ };
485
+
486
+ const seriesYOrZ = (series) => {
487
+ const y = new Map();
488
+ const z = new Map();
489
+ series.forEach((value, key) => {
490
+ if (value.yOrZ === 'y') {
491
+ y.set(key, value);
492
+ } else {
493
+ z.set(key, value);
494
+ }
495
+ });
496
+ return { y, z };
497
+ };
498
+
499
+ const resetStacks = (stacks) => {
500
+ stacks.forEach((stack) => {
501
+ stack.positive = 0;
502
+ stack.negative = 0;
503
+ });
504
+ };
505
+
506
+ const getCurrentStack = (stack, stackMap) =>
507
+ stackMap.find(
508
+ ({ stack: _stack, type: _type, yOrZ: _yOrZ, s: _s }) =>
509
+ _type == stack.type &&
510
+ _stack == stack.stack &&
511
+ _yOrZ == stack.yOrZ &&
512
+ _s.includes(stack.name)
513
+ );
514
+
515
+ const getBandBackground = (pattern, fill) => {
516
+ if (!(pattern && pattern.path)) return getColor(fill);
517
+ try{
518
+ const { backgroundSize = '100% 100%', ..._pattern } = pattern;
519
+ return (
520
+ 'center top / ' +
521
+ backgroundSize +
522
+ ' url("data:image/svg+xml,' +
523
+ encodeURIComponent(
524
+ renderToStaticMarkup(<SvgBackground fill={fill} pattern={_pattern} />)
525
+ ) +
526
+ '")'
527
+ );
528
+ }catch(e){}
529
+ return "";
530
+ };
531
+ const getBandwidth = (step, paddingOuter) => step * (1 - paddingOuter);
532
+
533
+ const getBandSeriesStepAndWidth = ({ width, paddingInner, bandLength }) => {
534
+ const seriesStep = width / (bandLength == 0 ? 1 : bandLength);
535
+ const seriesWidth = seriesStep * (1 - paddingInner);
536
+ return {
537
+ seriesStep,
538
+ seriesWidth,
539
+ };
540
+ };
541
+
542
+ const getSeriesInfo = ({
543
+ step,
544
+ bandLength = 1,
545
+ paddingInner = 0,
546
+ paddingOuter = 0,
547
+ }) => {
548
+ if (bandLength == 0)
549
+ return {
550
+ seriesWidth: step,
551
+ seriesStep: step,
552
+ seriesStart: 0,
553
+ width: step,
554
+ };
555
+ const _step =
556
+ step / (bandLength + paddingOuter * 2 + paddingInner * (bandLength - 1));
557
+ return {
558
+ seriesWidth: _step,
559
+ seriesStep: (1 + paddingInner) * _step,
560
+ seriesStart: paddingOuter * _step,
561
+ width: step - paddingOuter * 2 * _step,
562
+ };
563
+ };
564
+
565
+ const isValidHttpUrl = (string) => {
566
+ let url;
567
+
568
+ try {
569
+ url = new URL(string);
570
+ } catch (_) {
571
+ return false;
572
+ }
573
+
574
+ return url.protocol === 'http:' || url.protocol === 'https:';
575
+ };
576
+
577
+ const getChildren = (svgStr) => {
578
+ const wrapper = document.createElement('div');
579
+ wrapper.innerHTML = svgStr;
580
+ const { childNodes } = wrapper;
581
+ const svgDom = [...childNodes].find((item) => item.tagName === 'svg');
582
+
583
+ if (!!svgDom) {
584
+ return [...svgDom.childNodes];
585
+ }
586
+
587
+ return null;
588
+ };
589
+
590
+ const filterChildren = (children, tagNames) => {
591
+ return children.reduce((prev, node) => {
592
+ let { nodeName } = node;
593
+
594
+ if (tagNames.indexOf(nodeName) > -1) {
595
+ if (nodeName === 'g') {
596
+ return filterChildren([...node.childNodes], tagNames);
597
+ } else {
598
+ prev.push(node);
599
+ }
600
+ }
601
+
602
+ return prev;
603
+ }, []);
604
+ };
605
+
606
+ const getDomPath = (node) => {
607
+ switch (node.nodeName) {
608
+ case 'circle':
609
+ return toPath({
610
+ type: 'circle',
611
+ cx: +node.getAttribute('cx') || 0,
612
+ cy: +node.getAttribute('cy') || 0,
613
+ r: +node.getAttribute('r') || 0,
614
+ });
615
+
616
+ case 'ellipse':
617
+ return toPath({
618
+ type: 'ellipse',
619
+ cx: +node.getAttribute('cx') || 0,
620
+ cy: +node.getAttribute('cy') || 0,
621
+ rx: +node.getAttribute('rx') || 0,
622
+ ry: +node.getAttribute('ry') || 0,
623
+ });
624
+
625
+ case 'line':
626
+ return toPath({
627
+ type: 'line',
628
+ x1: +node.getAttribute('x1') || 0,
629
+ x2: +node.getAttribute('x2') || 0,
630
+ y1: +node.getAttribute('y1') || 0,
631
+ y2: +node.getAttribute('y2') || 0,
632
+ });
633
+
634
+ case 'path':
635
+ return toPath({
636
+ type: 'path',
637
+ d: node.getAttribute('d') || '',
638
+ });
639
+
640
+ case 'polygon':
641
+ return toPath({
642
+ type: 'polyline',
643
+ points: node.getAttribute('points') || '',
644
+ });
645
+
646
+ case 'polyline':
647
+ return toPath({
648
+ type: 'polyline',
649
+ points: node.getAttribute('points') || '',
650
+ });
651
+
652
+ case 'rect':
653
+ return toPath({
654
+ type: 'rect',
655
+ height: +node.getAttribute('height') || 0,
656
+ width: +node.getAttribute('width') || 0,
657
+ x: +node.getAttribute('x') || 0,
658
+ y: +node.getAttribute('y') || 0,
659
+ rx: +node.getAttribute('rx') || 0,
660
+ ry: +node.getAttribute('ry') || 0,
661
+ });
662
+ }
663
+ };
664
+
665
+ const sortPie = (data, order) => {
666
+ const _data = data.map((item) => ({ ...item }));
667
+ switch (order) {
668
+ case '':
669
+ _data.sort(({ index: a }, { index: b }) => ascending(a, b));
670
+ break;
671
+ case 'desc':
672
+ _data.sort(({ value: a }, { value: b }) => descending(a, b));
673
+ break;
674
+ case 'asc':
675
+ _data.sort(({ value: a }, { value: b }) => ascending(a, b));
676
+ break;
677
+ }
678
+ return _data;
679
+ };
680
+
681
+ // const getDataWithPercent = (data = [], precision = 0, type) => {
682
+ // const digits = Math.pow(10, precision);
683
+ // const targetSeats = digits * 100;
684
+
685
+ // const total = sum(data, (d) => d.value);
686
+
687
+ // const votesPerQuota = data.map((d, index) => ({
688
+ // ...d,
689
+ // vote: Math.round((d.value / total) * digits * 100),
690
+ // index,
691
+ // }));
692
+ // const currentSum = sum(votesPerQuota, (d) => d.vote);
693
+ // const remainder = targetSeats - currentSum;
694
+ // console.log(type+":",votesPerQuota, toFixed);
695
+ // votesPerQuota.sort(({ value: a }, { value: b }) => (a % total) - (b % total));
696
+
697
+ // const tmp = votesPerQuota.map(({ vote, ...data }, index) => ({
698
+ // ...data,
699
+ // percent: toFixed((vote + (index < remainder ? 1 : 0)) / digits, precision),
700
+ // }));
701
+
702
+ // return tmp;
703
+ // };
704
+
705
+ const getDataWithPercent = (data = [], precision = 0) => {
706
+ let objData = [];
707
+ function getPercentWithPrecision(valueList, idx, precision) {
708
+ if (!valueList[idx]) {
709
+ return 0;
710
+ }
711
+ const sum = valueList.reduce( function (acc, val) {
712
+ return acc + val.value;
713
+ }, 0);
714
+ if (sum === 0) {
715
+ return 0;
716
+ }
717
+ const digits = Math.pow(10, precision);
718
+ const votesPerQuota = valueList.map(function (val) {
719
+ return val.value / sum * digits * 100;
720
+ });
721
+ const targetSeats = digits * 100;
722
+ const seats = votesPerQuota.map(function (votes) {
723
+ return Math.floor(votes);
724
+ });
725
+ let currentSum = seats.reduce( function (acc, val) {
726
+ return acc + val;
727
+ }, 0);
728
+ const remainder = votesPerQuota.map(function (votes, idx) {
729
+ return votes - seats[idx];
730
+ });
731
+ while (currentSum < targetSeats) {
732
+ let max = Number.NEGATIVE_INFINITY;
733
+ let maxId = null;
734
+ for (let i = 0, len = remainder.length; i < len; ++i) {
735
+ if (remainder[i] > max) {
736
+ max = remainder[i];
737
+ maxId = i;
738
+ }
739
+ }
740
+ ++seats[maxId];
741
+ remainder[maxId] = 0;
742
+ ++currentSum;
743
+ }
744
+ return seats[idx] / digits;
745
+ }
746
+ data.forEach((d, i) => {
747
+ objData.push({
748
+ ...d,
749
+ percent: getPercentWithPrecision(data, i, precision)
750
+ })
751
+ });
752
+ return objData
753
+ };
754
+
755
+ const excludeTypes = ['array', 'object', 'group', 'modal', 'colors'];
756
+ const reduceConfig = (config = []) => {
757
+ if (!Array.isArray(config)) {
758
+ return config;
759
+ }
760
+ let output = {};
761
+ for (let i = 0, len = config.length; i < len; i++) {
762
+ let type = config[i]._type;
763
+
764
+ output[config[i]._name] =
765
+ type && !excludeTypes.includes(type)
766
+ ? config[i]._value
767
+ : reduceConfig(config[i]._value);
768
+ }
769
+ return output;
770
+ };
771
+
772
+ //限制value的值在min和max之间
773
+ const mathR=(value, range)=>{
774
+ const [min,max] = range;
775
+ return Math.max(min,Math.min(value,max));
776
+ }
777
+
778
+ export {
779
+ dateFormat,
780
+ getBreakWord,
781
+ getTicksOfAxis,
782
+ getTickCoord,
783
+ getGridCoord,
784
+ identity,
785
+ getMousePos,
786
+ getFontStyle,
787
+ formatFont,
788
+ getMargin,
789
+ getTranslate3d,
790
+ getTranslate2d,
791
+ band,
792
+ getIcon,
793
+ getColorList,
794
+ getMultiColorStr,
795
+ getStacks,
796
+ dataYOrZ,
797
+ seriesYOrZ,
798
+ resetStacks,
799
+ getCurrentStack,
800
+ getBandBackground,
801
+ getBandwidth,
802
+ getBandSeriesStepAndWidth,
803
+ isValidHttpUrl,
804
+ getChildren,
805
+ filterChildren,
806
+ getDomPath,
807
+ sortPie,
808
+ getDataWithPercent,
809
+ reduceConfig,
810
+ getSeriesInfo,
811
+ mathR
812
+ };