@easyv/charts 1.10.9 → 1.10.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/components/Legend.js +51 -5
- package/lib/components/PieChart.js +5 -0
- package/lib/formatter/legend.js +111 -6
- package/lib/utils/index.js +116 -105
- package/package.json +2 -2
- package/src/components/Legend.js +63 -1
- package/src/components/PieChart.js +37 -32
- package/src/formatter/legend.js +134 -24
- package/src/utils/index.js +171 -155
package/src/utils/index.js
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
import { getColor } from
|
|
2
|
-
import { toFixed } from
|
|
1
|
+
import { getColor } from "@easyv/utils";
|
|
2
|
+
import { toFixed } from "@easyv/utils/lib/common/utils";
|
|
3
3
|
import {
|
|
4
4
|
scaleOrdinal as ordinal,
|
|
5
5
|
range as sequence,
|
|
6
6
|
ascending,
|
|
7
7
|
descending,
|
|
8
8
|
sum,
|
|
9
|
-
} from
|
|
10
|
-
import { renderToStaticMarkup } from
|
|
11
|
-
import { toPath } from
|
|
9
|
+
} from "d3v7";
|
|
10
|
+
import { renderToStaticMarkup } from "react-dom/server";
|
|
11
|
+
import { toPath } from "svg-points";
|
|
12
12
|
|
|
13
|
-
const defaultBackground =
|
|
13
|
+
const defaultBackground = "#000000";
|
|
14
14
|
const defaultIcon = {
|
|
15
15
|
background: defaultBackground,
|
|
16
16
|
};
|
|
@@ -25,20 +25,20 @@ const renderCanvasBackground = ({
|
|
|
25
25
|
linear: { angle, opacity, stops },
|
|
26
26
|
},
|
|
27
27
|
pattern: {
|
|
28
|
-
path =
|
|
29
|
-
width =
|
|
30
|
-
height =
|
|
31
|
-
boderColor: stroke =
|
|
28
|
+
path = "",
|
|
29
|
+
width = "100%",
|
|
30
|
+
height = "100%",
|
|
31
|
+
boderColor: stroke = "transparent",
|
|
32
32
|
boderWidth = 0,
|
|
33
33
|
},
|
|
34
34
|
}) => {
|
|
35
35
|
// 处理宽高(支持百分比/数字)
|
|
36
|
-
const canvasWidth = width ===
|
|
37
|
-
const canvasHeight = height ===
|
|
36
|
+
const canvasWidth = width === "100%" ? 200 : Number(width) || 200; // 百分比默认200,可根据实际场景调整
|
|
37
|
+
const canvasHeight = height === "100%" ? 200 : Number(height) || 200;
|
|
38
38
|
|
|
39
39
|
// 创建离屏 Canvas
|
|
40
|
-
const canvas = document.createElement(
|
|
41
|
-
const ctx = canvas.getContext(
|
|
40
|
+
const canvas = document.createElement("canvas");
|
|
41
|
+
const ctx = canvas.getContext("2d");
|
|
42
42
|
canvas.width = canvasWidth;
|
|
43
43
|
canvas.height = canvasHeight;
|
|
44
44
|
|
|
@@ -49,13 +49,13 @@ const renderCanvasBackground = ({
|
|
|
49
49
|
const path2D = new Path2D(path);
|
|
50
50
|
|
|
51
51
|
// 2. 处理填充(纯色/渐变)
|
|
52
|
-
if (type ===
|
|
52
|
+
if (type === "pure") {
|
|
53
53
|
ctx.fillStyle = pure;
|
|
54
54
|
} else {
|
|
55
55
|
// 线性渐变(对应原 SVG linearGradient)
|
|
56
56
|
const centerX = canvasWidth / 2;
|
|
57
57
|
const centerY = canvasHeight / 2;
|
|
58
|
-
const rad = (angle + 180) * Math.PI / 180; // 旋转角度转弧度
|
|
58
|
+
const rad = ((angle + 180) * Math.PI) / 180; // 旋转角度转弧度
|
|
59
59
|
const gradientLength = Math.hypot(canvasWidth, canvasHeight); // 渐变长度取对角线
|
|
60
60
|
|
|
61
61
|
// 计算渐变起点/终点(匹配 SVG rotate 效果)
|
|
@@ -84,7 +84,7 @@ const renderCanvasBackground = ({
|
|
|
84
84
|
}
|
|
85
85
|
|
|
86
86
|
// 5. 转换为 DataURL(替代 SVG DataURL)
|
|
87
|
-
return canvas.toDataURL(
|
|
87
|
+
return canvas.toDataURL("image/png");
|
|
88
88
|
};
|
|
89
89
|
const SvgBackground = ({
|
|
90
90
|
fill: {
|
|
@@ -93,33 +93,33 @@ const SvgBackground = ({
|
|
|
93
93
|
linear: { angle, opacity, stops },
|
|
94
94
|
},
|
|
95
95
|
pattern: {
|
|
96
|
-
path =
|
|
97
|
-
width =
|
|
98
|
-
height =
|
|
99
|
-
boderColor: stroke =
|
|
96
|
+
path = "",
|
|
97
|
+
width = "100%",
|
|
98
|
+
height = "100%",
|
|
99
|
+
boderColor: stroke = "transparent",
|
|
100
100
|
boderWidth = 0,
|
|
101
101
|
},
|
|
102
102
|
}) => {
|
|
103
103
|
return (
|
|
104
104
|
<svg
|
|
105
|
-
preserveAspectRatio=
|
|
106
|
-
xmlns=
|
|
105
|
+
preserveAspectRatio="none"
|
|
106
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
107
107
|
width={width}
|
|
108
108
|
height={height}
|
|
109
109
|
>
|
|
110
110
|
<defs>
|
|
111
111
|
<linearGradient
|
|
112
|
-
id=
|
|
113
|
-
x1=
|
|
114
|
-
y1=
|
|
115
|
-
x2=
|
|
116
|
-
y2=
|
|
117
|
-
gradientTransform={
|
|
112
|
+
id="linearGradient"
|
|
113
|
+
x1="0%"
|
|
114
|
+
y1="0%"
|
|
115
|
+
x2="0%"
|
|
116
|
+
y2="100%"
|
|
117
|
+
gradientTransform={"rotate(" + (angle + 180) + ", 0.5, 0.5)"}
|
|
118
118
|
>
|
|
119
119
|
{stops.map(({ offset, color }, index) => (
|
|
120
120
|
<stop
|
|
121
121
|
key={index}
|
|
122
|
-
offset={offset +
|
|
122
|
+
offset={offset + "%"}
|
|
123
123
|
stopColor={color}
|
|
124
124
|
stopOpacity={opacity}
|
|
125
125
|
/>
|
|
@@ -128,7 +128,7 @@ const SvgBackground = ({
|
|
|
128
128
|
</defs>
|
|
129
129
|
<path
|
|
130
130
|
d={path}
|
|
131
|
-
fill={type ===
|
|
131
|
+
fill={type === "pure" ? pure : "url(#linearGradient)"}
|
|
132
132
|
stroke={stroke}
|
|
133
133
|
strokeWidth={boderWidth}
|
|
134
134
|
/>
|
|
@@ -136,7 +136,7 @@ const SvgBackground = ({
|
|
|
136
136
|
);
|
|
137
137
|
};
|
|
138
138
|
const getColorList = ({ type, pure, linear: { stops, angle, opacity } }) => {
|
|
139
|
-
if (type ==
|
|
139
|
+
if (type == "pure") {
|
|
140
140
|
return [
|
|
141
141
|
{ color: pure, offset: 1 },
|
|
142
142
|
{ color: pure, offset: 0 },
|
|
@@ -147,28 +147,31 @@ const getColorList = ({ type, pure, linear: { stops, angle, opacity } }) => {
|
|
|
147
147
|
const getMultiColorStr = (colors) => {
|
|
148
148
|
if (colors) {
|
|
149
149
|
const { stops, angle } = colors;
|
|
150
|
-
let result =
|
|
150
|
+
let result = "linear-gradient(" + angle + "deg, ";
|
|
151
151
|
const stops_ = JSON.parse(JSON.stringify(stops));
|
|
152
152
|
stops_.sort((a, b) => a.offset - b.offset);
|
|
153
153
|
for (let i = 0; i < stops_.length; i++) {
|
|
154
154
|
const { color, offset } = stops_[i];
|
|
155
155
|
result += `${color} ${offset}%,`;
|
|
156
156
|
}
|
|
157
|
-
return result.slice(0, -1) +
|
|
157
|
+
return result.slice(0, -1) + ")";
|
|
158
158
|
}
|
|
159
159
|
};
|
|
160
160
|
|
|
161
161
|
const getIcon = (type, icon, lineType = "solid") => {
|
|
162
162
|
switch (type) {
|
|
163
|
-
case
|
|
164
|
-
case
|
|
163
|
+
case "area":
|
|
164
|
+
case "line":
|
|
165
165
|
let color = icon.background;
|
|
166
166
|
return icon
|
|
167
167
|
? {
|
|
168
168
|
...defaultLineIcon,
|
|
169
169
|
...icon,
|
|
170
170
|
minWidth: icon.width,
|
|
171
|
-
background:
|
|
171
|
+
background:
|
|
172
|
+
lineType == "solid"
|
|
173
|
+
? color
|
|
174
|
+
: `linear-gradient(90deg, ${color}, ${color} 66%, transparent 66%) 0 0/33% 100% repeat`,
|
|
172
175
|
}
|
|
173
176
|
: defaultLineIcon;
|
|
174
177
|
default:
|
|
@@ -185,43 +188,43 @@ const getIcon = (type, icon, lineType = "solid") => {
|
|
|
185
188
|
const dateFormat = (date, fmt) => {
|
|
186
189
|
date = new Date(date);
|
|
187
190
|
const o = {
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
191
|
+
"M+": date.getMonth() + 1, //月份
|
|
192
|
+
"D+": date.getDate(), //日
|
|
193
|
+
"H+": date.getHours(), //小时
|
|
194
|
+
"h+": date.getHours() % 12 == 0 ? 12 : date.getHours() % 12, //小时
|
|
195
|
+
"m+": date.getMinutes(), //分
|
|
196
|
+
"s+": date.getSeconds(), //秒
|
|
194
197
|
S: date.getMilliseconds(), //毫秒
|
|
195
|
-
X:
|
|
198
|
+
X: "星期" + "日一二三四五六".charAt(date.getDay()),
|
|
196
199
|
W: new Array(
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
200
|
+
"Sunday",
|
|
201
|
+
"Monday",
|
|
202
|
+
"Tuesday",
|
|
203
|
+
"Wednesday",
|
|
204
|
+
"Thursday",
|
|
205
|
+
"Friday",
|
|
206
|
+
"Saturday",
|
|
204
207
|
)[date.getDay()],
|
|
205
|
-
w: new Array(
|
|
208
|
+
w: new Array("Sun.", "Mon.", " Tues.", "Wed.", " Thur.", "Fri.", "Sat.")[
|
|
206
209
|
date.getDay()
|
|
207
210
|
],
|
|
208
211
|
};
|
|
209
212
|
if (/(Y+)/.test(fmt))
|
|
210
213
|
fmt = fmt.replace(
|
|
211
214
|
RegExp.$1,
|
|
212
|
-
(date.getFullYear() +
|
|
215
|
+
(date.getFullYear() + "").substr(4 - RegExp.$1.length),
|
|
213
216
|
);
|
|
214
217
|
for (var k in o)
|
|
215
|
-
if (new RegExp(
|
|
218
|
+
if (new RegExp("(" + k + ")").test(fmt))
|
|
216
219
|
fmt = fmt.replace(
|
|
217
220
|
RegExp.$1,
|
|
218
|
-
RegExp.$1.length == 1 ? o[k] : (
|
|
221
|
+
RegExp.$1.length == 1 ? o[k] : ("00" + o[k]).substr(("" + o[k]).length),
|
|
219
222
|
);
|
|
220
223
|
return fmt;
|
|
221
224
|
};
|
|
222
225
|
|
|
223
226
|
const getBreakWord = (str, breakNumber) => {
|
|
224
|
-
const re = new RegExp(
|
|
227
|
+
const re = new RegExp("([^]){1," + breakNumber + "}", "g");
|
|
225
228
|
return str.match(re);
|
|
226
229
|
};
|
|
227
230
|
|
|
@@ -232,14 +235,16 @@ const getTicksOfAxis = (domain, ticksCount, showLast) => {
|
|
|
232
235
|
let step = Math.floor((len - ticksCount) / (ticksCount - 1));
|
|
233
236
|
let ticksArr = [];
|
|
234
237
|
if (showLast) {
|
|
235
|
-
let count = ticksCount,
|
|
238
|
+
let count = ticksCount,
|
|
239
|
+
gap = 0;
|
|
236
240
|
step = (len - 1) / (count - 1);
|
|
237
241
|
const maxGap = Math.max(count - 2, len - count);
|
|
238
242
|
//循环计算出最接近count值且能让step为整数的值
|
|
239
243
|
if (!Number.isInteger(step)) {
|
|
240
244
|
while (gap <= maxGap) {
|
|
241
245
|
gap++;
|
|
242
|
-
const left = (len - 1) / (count - gap - 1),
|
|
246
|
+
const left = (len - 1) / (count - gap - 1),
|
|
247
|
+
right = (len - 1) / (count + gap - 1);
|
|
243
248
|
if (Number.isInteger(left)) {
|
|
244
249
|
step = left;
|
|
245
250
|
break;
|
|
@@ -271,17 +276,17 @@ const getTickCoord = ({
|
|
|
271
276
|
}) => {
|
|
272
277
|
let x1, x2, y1, y2;
|
|
273
278
|
switch (orientation) {
|
|
274
|
-
case
|
|
279
|
+
case "top":
|
|
275
280
|
x1 = x2 = coordinate;
|
|
276
281
|
y2 = y;
|
|
277
282
|
y1 = y2 - tickSize;
|
|
278
283
|
break;
|
|
279
|
-
case
|
|
284
|
+
case "left":
|
|
280
285
|
y1 = y2 = coordinate;
|
|
281
286
|
x2 = x;
|
|
282
287
|
x1 = x2 - tickSize;
|
|
283
288
|
break;
|
|
284
|
-
case
|
|
289
|
+
case "right":
|
|
285
290
|
y1 = y2 = coordinate;
|
|
286
291
|
x2 = x;
|
|
287
292
|
x1 = x2 + tickSize;
|
|
@@ -297,22 +302,22 @@ const getTickCoord = ({
|
|
|
297
302
|
const getGridCoord = ({ orientation, coordinate, end }) => {
|
|
298
303
|
let x1, x2, y1, y2;
|
|
299
304
|
switch (orientation) {
|
|
300
|
-
case
|
|
305
|
+
case "top":
|
|
301
306
|
x1 = x2 = coordinate;
|
|
302
307
|
y1 = 0;
|
|
303
308
|
y2 = end;
|
|
304
309
|
break;
|
|
305
|
-
case
|
|
310
|
+
case "bottom":
|
|
306
311
|
x1 = x2 = coordinate;
|
|
307
312
|
y1 = 0;
|
|
308
313
|
y2 = end * -1;
|
|
309
314
|
break;
|
|
310
|
-
case
|
|
315
|
+
case "left":
|
|
311
316
|
y1 = y2 = coordinate;
|
|
312
317
|
x1 = 0;
|
|
313
318
|
x2 = end;
|
|
314
319
|
break;
|
|
315
|
-
case
|
|
320
|
+
case "right":
|
|
316
321
|
y1 = y2 = coordinate;
|
|
317
322
|
x1 = 0;
|
|
318
323
|
x2 = end * -1;
|
|
@@ -336,17 +341,17 @@ const getMousePos = (evt, dom) => {
|
|
|
336
341
|
|
|
337
342
|
const getFontStyle = (
|
|
338
343
|
{ color, bold, italic, fontSize, fontFamily, letterSpacing, lineHeight },
|
|
339
|
-
type
|
|
344
|
+
type,
|
|
340
345
|
) => {
|
|
341
|
-
if (type ==
|
|
346
|
+
if (type == "svg") {
|
|
342
347
|
return {
|
|
343
348
|
fontSize,
|
|
344
349
|
fontFamily,
|
|
345
350
|
letterSpacing,
|
|
346
351
|
fill: color,
|
|
347
|
-
fontWeight: bold ?
|
|
348
|
-
fontStyle: italic ?
|
|
349
|
-
lineHeight: lineHeight + "px"
|
|
352
|
+
fontWeight: bold ? "bold" : "normal",
|
|
353
|
+
fontStyle: italic ? "italic" : "normal",
|
|
354
|
+
lineHeight: lineHeight + "px",
|
|
350
355
|
};
|
|
351
356
|
}
|
|
352
357
|
return {
|
|
@@ -354,43 +359,45 @@ const getFontStyle = (
|
|
|
354
359
|
fontFamily,
|
|
355
360
|
letterSpacing,
|
|
356
361
|
color,
|
|
357
|
-
fontWeight: bold ?
|
|
358
|
-
fontStyle: italic ?
|
|
359
|
-
lineHeight: lineHeight + "px"//不加px默认是倍数关系
|
|
362
|
+
fontWeight: bold ? "bold" : "normal",
|
|
363
|
+
fontStyle: italic ? "italic" : "normal",
|
|
364
|
+
lineHeight: lineHeight + "px", //不加px默认是倍数关系
|
|
360
365
|
};
|
|
361
366
|
};
|
|
362
367
|
|
|
363
368
|
const formatFont = ({ color, fill, bold, italic, ...rest }, type) => {
|
|
364
|
-
if (type ==
|
|
369
|
+
if (type == "svg") {
|
|
365
370
|
return {
|
|
366
371
|
fill: fill || color,
|
|
367
|
-
fontWeight: typeof bold == "string" ? bold :
|
|
368
|
-
fontStyle:
|
|
369
|
-
|
|
372
|
+
fontWeight: typeof bold == "string" ? bold : bold ? "bold" : "normal",
|
|
373
|
+
fontStyle:
|
|
374
|
+
typeof italic == "string" ? italic : italic ? "italic" : "normal",
|
|
375
|
+
...rest,
|
|
370
376
|
};
|
|
371
377
|
}
|
|
372
378
|
return {
|
|
373
379
|
color: color || fill,
|
|
374
|
-
fontWeight: typeof bold == "string" ? bold :
|
|
375
|
-
fontStyle:
|
|
376
|
-
|
|
380
|
+
fontWeight: typeof bold == "string" ? bold : bold ? "bold" : "normal",
|
|
381
|
+
fontStyle:
|
|
382
|
+
typeof italic == "string" ? italic : italic ? "italic" : "normal",
|
|
383
|
+
...rest,
|
|
377
384
|
};
|
|
378
385
|
};
|
|
379
386
|
|
|
380
387
|
const getMargin = ({ marginTop, marginRight, marginBottom, marginLeft }) =>
|
|
381
388
|
marginTop +
|
|
382
|
-
|
|
389
|
+
"px " +
|
|
383
390
|
marginRight +
|
|
384
|
-
|
|
391
|
+
"px " +
|
|
385
392
|
marginBottom +
|
|
386
|
-
|
|
393
|
+
"px " +
|
|
387
394
|
marginLeft +
|
|
388
|
-
|
|
395
|
+
"px";
|
|
389
396
|
|
|
390
397
|
const getTranslate3d = ({ x = 0, y = 0, z = 0 }) =>
|
|
391
|
-
|
|
398
|
+
"translate3d(" + x + "px, " + y + "px, " + z + "px)";
|
|
392
399
|
|
|
393
|
-
const getTranslate2d = ({ x = 0, y = 0 }) =>
|
|
400
|
+
const getTranslate2d = ({ x = 0, y = 0 }) => "translate(" + x + ", " + y + ")";
|
|
394
401
|
|
|
395
402
|
function band() {
|
|
396
403
|
var scale = ordinal().unknown(undefined),
|
|
@@ -416,7 +423,8 @@ function band() {
|
|
|
416
423
|
if (round) step = Math.floor(step);
|
|
417
424
|
start += (stop - start - step * n) * align;
|
|
418
425
|
bandwidth = step;
|
|
419
|
-
if (round)
|
|
426
|
+
if (round)
|
|
427
|
+
((start = Math.round(start)), (bandwidth = Math.round(bandwidth)));
|
|
420
428
|
var values = sequence(n).map(function (i) {
|
|
421
429
|
return start + step * i + step / 2;
|
|
422
430
|
});
|
|
@@ -434,7 +442,7 @@ function band() {
|
|
|
434
442
|
};
|
|
435
443
|
|
|
436
444
|
scale.rangeRound = function (_) {
|
|
437
|
-
return ([r0, r1] = _), (r0 = +r0), (r1 = +r1), (round = true), rescale();
|
|
445
|
+
return (([r0, r1] = _), (r0 = +r0), (r1 = +r1), (round = true), rescale());
|
|
438
446
|
};
|
|
439
447
|
|
|
440
448
|
scale.bandwidth = function () {
|
|
@@ -509,7 +517,7 @@ const getStacks = (series) => {
|
|
|
509
517
|
series.forEach(({ type, stack, yOrZ }, name) => {
|
|
510
518
|
const current = tmp.find(
|
|
511
519
|
({ type: _type, stack: _stack, yOrZ: _yOrZ }) =>
|
|
512
|
-
_type == type && stack && _stack == stack && yOrZ == _yOrZ
|
|
520
|
+
_type == type && stack && _stack == stack && yOrZ == _yOrZ,
|
|
513
521
|
);
|
|
514
522
|
if (!current) {
|
|
515
523
|
const common = {
|
|
@@ -520,8 +528,8 @@ const getStacks = (series) => {
|
|
|
520
528
|
yOrZ,
|
|
521
529
|
s: [name],
|
|
522
530
|
};
|
|
523
|
-
if (type ===
|
|
524
|
-
const index = tmp.filter((item) => item.type ===
|
|
531
|
+
if (type === "band") {
|
|
532
|
+
const index = tmp.filter((item) => item.type === "band").length;
|
|
525
533
|
tmp.push({
|
|
526
534
|
...common,
|
|
527
535
|
index,
|
|
@@ -561,7 +569,7 @@ const seriesYOrZ = (series) => {
|
|
|
561
569
|
const y = new Map();
|
|
562
570
|
const z = new Map();
|
|
563
571
|
series.forEach((value, key) => {
|
|
564
|
-
if (value.yOrZ ===
|
|
572
|
+
if (value.yOrZ === "y") {
|
|
565
573
|
y.set(key, value);
|
|
566
574
|
} else {
|
|
567
575
|
z.set(key, value);
|
|
@@ -583,11 +591,11 @@ const getCurrentStack = (stack, stackMap) =>
|
|
|
583
591
|
_type == stack.type &&
|
|
584
592
|
_stack == stack.stack &&
|
|
585
593
|
_yOrZ == stack.yOrZ &&
|
|
586
|
-
_s.includes(stack.name)
|
|
594
|
+
_s.includes(stack.name),
|
|
587
595
|
);
|
|
588
596
|
|
|
589
597
|
const reverseGradientStops = (gradient) => {
|
|
590
|
-
if (gradient.type !==
|
|
598
|
+
if (gradient.type !== "linear" || !gradient.linear?.stops) {
|
|
591
599
|
return gradient;
|
|
592
600
|
}
|
|
593
601
|
const stops = gradient.linear.stops;
|
|
@@ -596,9 +604,9 @@ const reverseGradientStops = (gradient) => {
|
|
|
596
604
|
|
|
597
605
|
// 反转每个 stop 的 offset: newOffset = 100 - oldOffset
|
|
598
606
|
// 颜色保持不变,只是位置镜像翻转
|
|
599
|
-
const reversedStops = sortedStops.map(stop => ({
|
|
607
|
+
const reversedStops = sortedStops.map((stop) => ({
|
|
600
608
|
...stop,
|
|
601
|
-
offset: 100 - stop.offset
|
|
609
|
+
offset: 100 - stop.offset,
|
|
602
610
|
}));
|
|
603
611
|
//再按新的 offset 升序排序,确保输出结构正确
|
|
604
612
|
const finalStops = reversedStops.sort((a, b) => a.offset - b.offset);
|
|
@@ -607,25 +615,21 @@ const reverseGradientStops = (gradient) => {
|
|
|
607
615
|
...gradient,
|
|
608
616
|
linear: {
|
|
609
617
|
...gradient.linear,
|
|
610
|
-
stops: finalStops
|
|
611
|
-
}
|
|
618
|
+
stops: finalStops,
|
|
619
|
+
},
|
|
612
620
|
};
|
|
613
621
|
};
|
|
614
622
|
const getBandBackground = (pattern, fill, y) => {
|
|
615
623
|
if (!(pattern && pattern.path)) {
|
|
616
|
-
return getColor(y < 0 ? reverseGradientStops(fill) : fill)
|
|
624
|
+
return getColor(y < 0 ? reverseGradientStops(fill) : fill); //小于0颜色翻转
|
|
617
625
|
}
|
|
618
626
|
try {
|
|
619
|
-
const { backgroundSize =
|
|
627
|
+
const { backgroundSize = "100% 100%", ..._pattern } = pattern;
|
|
620
628
|
// 替换原 SVG DataURL 为 Canvas DataURL
|
|
621
629
|
const canvasDataUrl = renderCanvasBackground({ fill, pattern: _pattern });
|
|
622
|
-
return (
|
|
623
|
-
'center top / ' +
|
|
624
|
-
backgroundSize +
|
|
625
|
-
' url("' + canvasDataUrl + '")'
|
|
626
|
-
);
|
|
630
|
+
return "center top / " + backgroundSize + ' url("' + canvasDataUrl + '")';
|
|
627
631
|
} catch (e) {
|
|
628
|
-
console.error(
|
|
632
|
+
console.error("Canvas 绘制背景失败:", e);
|
|
629
633
|
}
|
|
630
634
|
return "";
|
|
631
635
|
};
|
|
@@ -673,14 +677,14 @@ const isValidHttpUrl = (string) => {
|
|
|
673
677
|
return false;
|
|
674
678
|
}
|
|
675
679
|
|
|
676
|
-
return url.protocol ===
|
|
680
|
+
return url.protocol === "http:" || url.protocol === "https:";
|
|
677
681
|
};
|
|
678
682
|
|
|
679
683
|
const getChildren = (svgStr) => {
|
|
680
|
-
const wrapper = document.createElement(
|
|
684
|
+
const wrapper = document.createElement("div");
|
|
681
685
|
wrapper.innerHTML = svgStr;
|
|
682
686
|
const { childNodes } = wrapper;
|
|
683
|
-
const svgDom = [...childNodes].find((item) => item.tagName ===
|
|
687
|
+
const svgDom = [...childNodes].find((item) => item.tagName === "svg");
|
|
684
688
|
|
|
685
689
|
if (!!svgDom) {
|
|
686
690
|
return [...svgDom.childNodes];
|
|
@@ -694,7 +698,7 @@ const filterChildren = (children, tagNames) => {
|
|
|
694
698
|
let { nodeName } = node;
|
|
695
699
|
|
|
696
700
|
if (tagNames.indexOf(nodeName) > -1) {
|
|
697
|
-
if (nodeName ===
|
|
701
|
+
if (nodeName === "g") {
|
|
698
702
|
return filterChildren([...node.childNodes], tagNames);
|
|
699
703
|
} else {
|
|
700
704
|
prev.push(node);
|
|
@@ -707,76 +711,88 @@ const filterChildren = (children, tagNames) => {
|
|
|
707
711
|
|
|
708
712
|
const getDomPath = (node) => {
|
|
709
713
|
switch (node.nodeName) {
|
|
710
|
-
case
|
|
714
|
+
case "circle":
|
|
711
715
|
return toPath({
|
|
712
|
-
type:
|
|
713
|
-
cx: +node.getAttribute(
|
|
714
|
-
cy: +node.getAttribute(
|
|
715
|
-
r: +node.getAttribute(
|
|
716
|
+
type: "circle",
|
|
717
|
+
cx: +node.getAttribute("cx") || 0,
|
|
718
|
+
cy: +node.getAttribute("cy") || 0,
|
|
719
|
+
r: +node.getAttribute("r") || 0,
|
|
716
720
|
});
|
|
717
721
|
|
|
718
|
-
case
|
|
722
|
+
case "ellipse":
|
|
719
723
|
return toPath({
|
|
720
|
-
type:
|
|
721
|
-
cx: +node.getAttribute(
|
|
722
|
-
cy: +node.getAttribute(
|
|
723
|
-
rx: +node.getAttribute(
|
|
724
|
-
ry: +node.getAttribute(
|
|
724
|
+
type: "ellipse",
|
|
725
|
+
cx: +node.getAttribute("cx") || 0,
|
|
726
|
+
cy: +node.getAttribute("cy") || 0,
|
|
727
|
+
rx: +node.getAttribute("rx") || 0,
|
|
728
|
+
ry: +node.getAttribute("ry") || 0,
|
|
725
729
|
});
|
|
726
730
|
|
|
727
|
-
case
|
|
731
|
+
case "line":
|
|
728
732
|
return toPath({
|
|
729
|
-
type:
|
|
730
|
-
x1: +node.getAttribute(
|
|
731
|
-
x2: +node.getAttribute(
|
|
732
|
-
y1: +node.getAttribute(
|
|
733
|
-
y2: +node.getAttribute(
|
|
733
|
+
type: "line",
|
|
734
|
+
x1: +node.getAttribute("x1") || 0,
|
|
735
|
+
x2: +node.getAttribute("x2") || 0,
|
|
736
|
+
y1: +node.getAttribute("y1") || 0,
|
|
737
|
+
y2: +node.getAttribute("y2") || 0,
|
|
734
738
|
});
|
|
735
739
|
|
|
736
|
-
case
|
|
740
|
+
case "path":
|
|
737
741
|
return toPath({
|
|
738
|
-
type:
|
|
739
|
-
d: node.getAttribute(
|
|
742
|
+
type: "path",
|
|
743
|
+
d: node.getAttribute("d") || "",
|
|
740
744
|
});
|
|
741
745
|
|
|
742
|
-
case
|
|
746
|
+
case "polygon":
|
|
743
747
|
return toPath({
|
|
744
|
-
type:
|
|
745
|
-
points: node.getAttribute(
|
|
748
|
+
type: "polyline",
|
|
749
|
+
points: node.getAttribute("points") || "",
|
|
746
750
|
});
|
|
747
751
|
|
|
748
|
-
case
|
|
752
|
+
case "polyline":
|
|
749
753
|
return toPath({
|
|
750
|
-
type:
|
|
751
|
-
points: node.getAttribute(
|
|
754
|
+
type: "polyline",
|
|
755
|
+
points: node.getAttribute("points") || "",
|
|
752
756
|
});
|
|
753
757
|
|
|
754
|
-
case
|
|
758
|
+
case "rect":
|
|
755
759
|
return toPath({
|
|
756
|
-
type:
|
|
757
|
-
height: +node.getAttribute(
|
|
758
|
-
width: +node.getAttribute(
|
|
759
|
-
x: +node.getAttribute(
|
|
760
|
-
y: +node.getAttribute(
|
|
761
|
-
rx: +node.getAttribute(
|
|
762
|
-
ry: +node.getAttribute(
|
|
760
|
+
type: "rect",
|
|
761
|
+
height: +node.getAttribute("height") || 0,
|
|
762
|
+
width: +node.getAttribute("width") || 0,
|
|
763
|
+
x: +node.getAttribute("x") || 0,
|
|
764
|
+
y: +node.getAttribute("y") || 0,
|
|
765
|
+
rx: +node.getAttribute("rx") || 0,
|
|
766
|
+
ry: +node.getAttribute("ry") || 0,
|
|
763
767
|
});
|
|
764
768
|
}
|
|
765
769
|
};
|
|
766
770
|
|
|
767
|
-
const sortPie = (data, order) => {
|
|
771
|
+
const sortPie = (data, order, acc) => {
|
|
768
772
|
const _data = data.map((item) => ({ ...item }));
|
|
769
773
|
switch (order) {
|
|
770
|
-
case
|
|
774
|
+
case "":
|
|
771
775
|
_data.sort(({ index: a }, { index: b }) => ascending(a, b));
|
|
772
776
|
break;
|
|
773
|
-
case
|
|
777
|
+
case "desc":
|
|
774
778
|
_data.sort(({ value: a }, { value: b }) => descending(a, b));
|
|
775
779
|
break;
|
|
776
|
-
case
|
|
780
|
+
case "asc":
|
|
777
781
|
_data.sort(({ value: a }, { value: b }) => ascending(a, b));
|
|
778
782
|
break;
|
|
779
783
|
}
|
|
784
|
+
if (acc && acc.columns) {
|
|
785
|
+
_data.forEach((item) => {
|
|
786
|
+
item.fields = {};
|
|
787
|
+
Object.values(acc.columns).forEach((columnConfig) => {
|
|
788
|
+
const fieldName = columnConfig.field;
|
|
789
|
+
if (fieldName) {
|
|
790
|
+
item.fields[fieldName] = columnConfig;
|
|
791
|
+
}
|
|
792
|
+
});
|
|
793
|
+
});
|
|
794
|
+
}
|
|
795
|
+
|
|
780
796
|
return _data;
|
|
781
797
|
};
|
|
782
798
|
|
|
@@ -794,7 +810,7 @@ const getDataWithPercent = (data = [], precision = 0) => {
|
|
|
794
810
|
}
|
|
795
811
|
const digits = Math.pow(10, precision);
|
|
796
812
|
const votesPerQuota = valueList.map(function (val) {
|
|
797
|
-
return val.value / sum * digits * 100;
|
|
813
|
+
return (val.value / sum) * digits * 100;
|
|
798
814
|
});
|
|
799
815
|
const targetSeats = digits * 100;
|
|
800
816
|
const seats = votesPerQuota.map(function (votes) {
|
|
@@ -824,13 +840,13 @@ const getDataWithPercent = (data = [], precision = 0) => {
|
|
|
824
840
|
data.forEach((d, i) => {
|
|
825
841
|
objData.push({
|
|
826
842
|
...d,
|
|
827
|
-
percent: getPercentWithPrecision(data, i, precision)
|
|
828
|
-
})
|
|
843
|
+
percent: getPercentWithPrecision(data, i, precision),
|
|
844
|
+
});
|
|
829
845
|
});
|
|
830
|
-
return objData
|
|
846
|
+
return objData;
|
|
831
847
|
};
|
|
832
848
|
|
|
833
|
-
const excludeTypes = [
|
|
849
|
+
const excludeTypes = ["array", "object", "group", "modal", "colors"];
|
|
834
850
|
const reduceConfig = (config = []) => {
|
|
835
851
|
if (!Array.isArray(config)) {
|
|
836
852
|
return config;
|
|
@@ -888,5 +904,5 @@ export {
|
|
|
888
904
|
getSeriesInfo,
|
|
889
905
|
mathR,
|
|
890
906
|
renderCanvasBackground, // 导出 Canvas 绘制方法
|
|
891
|
-
SvgBackground
|
|
892
|
-
};
|
|
907
|
+
SvgBackground,
|
|
908
|
+
};
|