@easyv/charts 1.2.3 → 1.2.4

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 (89) hide show
  1. package/.babelrc +8 -8
  2. package/.husky/commit-msg +3 -3
  3. package/CHANGELOG.md +18 -18
  4. package/lib/components/AnimateData.js +11 -7
  5. package/lib/components/Axis.js +18 -14
  6. package/lib/components/Background.js +2 -2
  7. package/lib/components/Band.js +8 -4
  8. package/lib/components/Brush.js +2 -2
  9. package/lib/components/Carousel.js +15 -8
  10. package/lib/components/CartesianChart.js +11 -7
  11. package/lib/components/Chart.js +9 -6
  12. package/lib/components/ChartContainer.js +8 -4
  13. package/lib/components/ConicalGradient.js +27 -23
  14. package/lib/components/ExtentData.js +7 -4
  15. package/lib/components/FilterData.js +7 -4
  16. package/lib/components/Indicator.js +2 -2
  17. package/lib/components/Label.js +2 -2
  18. package/lib/components/Legend.js +11 -5
  19. package/lib/components/Lighter.js +179 -179
  20. package/lib/components/Line.js +11 -5
  21. package/lib/components/LinearGradient.js +2 -2
  22. package/lib/components/Mapping.js +8 -5
  23. package/lib/components/Marquee.js +14 -14
  24. package/lib/components/PieChart.js +17 -8
  25. package/lib/components/StackData.js +7 -4
  26. package/lib/components/StereoBar.js +8 -4
  27. package/lib/components/TextOverflow.js +65 -0
  28. package/lib/components/Tooltip.js +2 -2
  29. package/lib/components/index.js +50 -50
  30. package/lib/css/index.module.css +41 -41
  31. package/lib/css/piechart.module.css +26 -26
  32. package/lib/element/ConicGradient.js +72 -72
  33. package/lib/formatter/legend.js +2 -2
  34. package/lib/hooks/index.js +14 -14
  35. package/lib/hooks/useAnimateData.js +7 -7
  36. package/lib/hooks/useAxes.js +7 -7
  37. package/lib/hooks/useCarouselAxisX.js +7 -7
  38. package/lib/hooks/useExtentData.js +8 -8
  39. package/lib/hooks/useFilterData.js +8 -8
  40. package/lib/hooks/useStackData.js +10 -8
  41. package/lib/hooks/useTooltip.js +10 -10
  42. package/lib/index.js +6 -2
  43. package/lib/utils/index.js +8 -5
  44. package/package.json +53 -51
  45. package/src/components/AnimateData.tsx +24 -24
  46. package/src/components/Axis.tsx +354 -354
  47. package/src/components/Background.tsx +45 -45
  48. package/src/components/Band.tsx +173 -173
  49. package/src/components/Brush.js +159 -159
  50. package/src/components/Carousel.tsx +144 -144
  51. package/src/components/Chart.js +99 -99
  52. package/src/components/ChartContainer.tsx +63 -63
  53. package/src/components/ConicalGradient.js +258 -258
  54. package/src/components/ExtentData.js +17 -17
  55. package/src/components/FilterData.js +23 -23
  56. package/src/components/Indicator.js +13 -13
  57. package/src/components/Label.js +206 -206
  58. package/src/components/Legend.js +158 -158
  59. package/src/components/Lighter.jsx +173 -173
  60. package/src/components/Line.js +144 -144
  61. package/src/components/LinearGradient.js +29 -29
  62. package/src/components/Mapping.js +71 -71
  63. package/src/components/Marquee.js +93 -93
  64. package/src/components/PieChart.js +1288 -1288
  65. package/src/components/StackData.js +20 -20
  66. package/src/components/StereoBar.tsx +310 -310
  67. package/src/components/TextOverflow.js +51 -0
  68. package/src/components/Tooltip.js +169 -169
  69. package/src/components/index.js +53 -53
  70. package/src/context/index.js +2 -2
  71. package/src/css/index.module.css +41 -41
  72. package/src/css/piechart.module.css +26 -26
  73. package/src/element/ConicGradient.jsx +55 -55
  74. package/src/element/Line.tsx +33 -33
  75. package/src/element/index.ts +3 -3
  76. package/src/formatter/index.js +1 -1
  77. package/src/formatter/legend.js +90 -90
  78. package/src/hooks/index.js +17 -17
  79. package/src/hooks/useAnimateData.ts +67 -67
  80. package/src/hooks/useAxes.js +144 -144
  81. package/src/hooks/useCarouselAxisX.js +163 -163
  82. package/src/hooks/useExtentData.js +88 -88
  83. package/src/hooks/useFilterData.js +72 -72
  84. package/src/hooks/useStackData.js +100 -100
  85. package/src/hooks/useTooltip.ts +96 -96
  86. package/src/index.js +6 -6
  87. package/src/types/index.d.ts +67 -67
  88. package/src/utils/index.js +696 -696
  89. package/tsconfig.json +22 -22
@@ -1,20 +1,20 @@
1
- /**
2
- * 堆叠类,具体逻辑在useStackData(HOC)
3
- */
4
- import { memo } from 'react';
5
- import { useStackData } from '../hooks';
6
- export default (Component) => {
7
- return memo(({ config: { series, ...config }, data, ...props }) => {
8
- const _series = useStackData({
9
- series,
10
- data,
11
- });
12
- return (
13
- <Component
14
- {...props}
15
- config={{ ...config, series: _series }}
16
- data={data}
17
- />
18
- );
19
- });
20
- };
1
+ /**
2
+ * 堆叠类,具体逻辑在useStackData(HOC)
3
+ */
4
+ import { memo } from 'react';
5
+ import { useStackData } from '../hooks';
6
+ export default (Component) => {
7
+ return memo(({ config: { series, ...config }, data, ...props }) => {
8
+ const _series = useStackData({
9
+ series,
10
+ data,
11
+ });
12
+ return (
13
+ <Component
14
+ {...props}
15
+ config={{ ...config, series: _series }}
16
+ data={data}
17
+ />
18
+ );
19
+ });
20
+ };
@@ -1,311 +1,311 @@
1
- /**
2
- * 立体柱状图的柱子
3
- */
4
- import React, { memo } from 'react';
5
- import { min, max } from 'd3v7';
6
- import {
7
- getBandBackground,
8
- getBandwidth,
9
- getBandSeriesStepAndWidth,
10
- } from '../utils';
11
-
12
- const getHighlightData = (data: Array<DataWithBoundType>, extent: string) => {
13
- switch (extent) {
14
- case 'min':
15
- const minData = min(data, (d: DataWithBoundType) => d.data.y);
16
- return data.map((item) => ({
17
- ...item,
18
- flag: minData == item.data.y ? 'min' : '',
19
- }));
20
- case 'max':
21
- const maxData = max(data, (d: DataWithBoundType) => d.data.y);
22
- return data.map((item) => ({
23
- ...item,
24
- flag: maxData == item.data.y ? 'max' : '',
25
- }));
26
- default:
27
- return data;
28
- }
29
- };
30
-
31
- const getAttr = ({
32
- isVertical,
33
- seriesWidth,
34
- length,
35
- x,
36
- y,
37
- }: {
38
- isVertical: boolean;
39
- seriesWidth: number;
40
- length: number;
41
- x: number;
42
- y: number;
43
- }) => {
44
- if (isVertical) return { width: length, height: seriesWidth, x: y, y: x };
45
- return {
46
- x,
47
- y,
48
- width: seriesWidth,
49
- height: length,
50
- };
51
- };
52
-
53
- const getBorderRadius = ({
54
- isVertical,
55
- positive,
56
- seriesWidth,
57
- }: {
58
- isVertical: boolean;
59
- positive: boolean;
60
- seriesWidth: number;
61
- }) => {
62
- return isVertical
63
- ? positive
64
- ? '0px ' + seriesWidth + 'px ' + seriesWidth + 'px 0'
65
- : seriesWidth + 'px 0 0 ' + seriesWidth + 'px'
66
- : positive
67
- ? seriesWidth / 2 + 'px ' + seriesWidth / 2 + 'px 0 0'
68
- : '0 0 ' + seriesWidth / 2 + 'px ' + seriesWidth / 2 + 'px';
69
- };
70
-
71
- export default memo(
72
- ({
73
- triggerClick,
74
- config: {
75
- pattern = {},
76
- seriesIntervalWidth: paddingInner = 0,
77
- paddingInner: paddingOuter = 0,
78
- style,
79
- fill,
80
- highlight: { show: showHighlight, extent, fill: highlightFill },
81
- id
82
- },
83
- bandLength = 0,
84
- data,
85
- xAxis: { scaler: xScaler, step, direction },
86
- yAxis: { scaler: yScaler },
87
- fieldName
88
- }: any) => {
89
- if (!data.length) return null;
90
- const bandwidth = getBandwidth(step, paddingOuter);
91
- const { seriesStep, seriesWidth } = getBandSeriesStepAndWidth({
92
- width: bandwidth,
93
- paddingInner,
94
- bandLength,
95
- });
96
-
97
- const _data = showHighlight ? getHighlightData(data, extent) : data;
98
-
99
- const offset =
100
- (seriesWidth + paddingInner * seriesStep) * bandLength -
101
- paddingInner * seriesStep;
102
-
103
- const isVertical = direction === 'vertical';
104
-
105
- const highlightColor = parseMultiColorToSVG(highlightFill, "highlight_gradient_" + id + "_" + fieldName);
106
- const color = parseMultiColorToSVG(fill, "gradient_" + id + "_" + fieldName);
107
- return (
108
- <g className='__easyv-band'>
109
- <defs>
110
- <filter id={`filter_front`}>
111
- <feComponentTransfer>
112
- <feFuncR type='linear' slope='0.5' />
113
- <feFuncG type='linear' slope='0.5' />
114
- <feFuncB type='linear' slope='0.5' />
115
- </feComponentTransfer>
116
- </filter>
117
- <filter id={`filter_side`}>
118
- <feComponentTransfer>
119
- <feFuncR type='linear' slope='0.7' />
120
- <feFuncG type='linear' slope='0.7' />
121
- <feFuncB type='linear' slope='0.7' />
122
- </feComponentTransfer>
123
- </filter>
124
- {highlightColor.def}
125
- {color.def}
126
- </defs>
127
- {_data.map(
128
- (
129
- {
130
- flag,
131
- index,
132
- bound: [start, end],
133
- data,
134
- data: { x, y, s },
135
- }: DataWithBoundType,
136
- i: number
137
- ) => {
138
- const y1 = yScaler(isVertical ? end : start);
139
- const y2 = yScaler(isVertical ? start : end);
140
- const positionX = xScaler(x) + seriesStep * index - offset / 2;
141
- if (isNaN(positionX)) return null;
142
- const positionY = y < 0 ? y1 : y2;
143
- const attr = getAttr({
144
- isVertical,
145
- x: positionX,
146
- y: positionY,
147
- length: Math.abs(y1 - y2),
148
- seriesWidth,
149
- });
150
-
151
- return (
152
- <g
153
- key={i}
154
- onClick={triggerClick}
155
- data-data={JSON.stringify(data)}
156
- >
157
- <Column3DSkin
158
- {...attr}
159
- color={extent === flag ? highlightColor : color}
160
- />
161
- </g>
162
- );
163
- }
164
- )}
165
- </g>
166
- );
167
- }
168
- );
169
-
170
-
171
- const Column3DSkin = function (props: any) {
172
- const {
173
- width,
174
- height,
175
- x,
176
- y,
177
- color,
178
- opacity = 1,
179
- } = props;
180
- return (
181
- <g
182
- style={{
183
- transform: `skew(0deg, 23deg)`,
184
- transformOrigin: `${x + width / 2}px ${y + height / 2}px`,
185
- opacity: opacity,
186
- }}
187
- >
188
- {color.defs}
189
- {/* 正面 */}
190
- <rect
191
- width={width / 2}
192
- height={height}
193
- x={x}
194
- y={y}
195
- fill={color.fill}
196
- style={{ filter: `url(#filter_front)` }}
197
- ></rect>
198
- {/* 侧面 */}
199
- <rect
200
- width={width / 2}
201
- height={height}
202
- x={x + width / 2}
203
- y={y}
204
- fill={color.fill}
205
- style={{
206
- transformOrigin: `${x + width / 2}px ${y + height / 2}px`,
207
- transform: 'skew(0deg, -45deg)',
208
- }}
209
- ></rect>
210
- {/* 顶部 */}
211
- <rect
212
- width={width / 2}
213
- height={width / 2}
214
- x={x}
215
- y={y}
216
- fill={color.firstColor ? color.firstColor : color}
217
- style={{
218
- transformOrigin: `${x + (width / 4) * 3}px ${y}px`,
219
- transform: `skew(-45deg) translate(0, -${width / 2}px)`,
220
- }}
221
- ></rect>
222
- </g>
223
- );
224
- };
225
-
226
-
227
- //以下都是为了解析multicolor
228
- function pointRotate(point: any, center: any, angle: any) {
229
- const
230
- x = point[0],
231
- y = point[1],
232
- rx = center[0],
233
- ry = center[1],
234
- cos = Math.cos(angle),
235
- sin = Math.sin(angle);
236
- const x0 = (x - rx) * cos - (y - ry) * sin + rx;
237
- const y0 = (x - rx) * sin + (y - ry) * cos + ry;
238
- return [x0, y0];
239
- }
240
- const AngleTransfromRatio = 180 / Math.PI;
241
- function deg2rad(deg: any) {
242
- return deg / AngleTransfromRatio;
243
- }
244
- function deepCopy(obj: any): any {
245
- if (typeof obj == "object") {
246
- let o: any;
247
- if (Array.isArray(obj)) {
248
- o = [];
249
- for (let i = 0; i < obj.length; i++) {
250
- o.push(deepCopy(obj[i]));
251
- }
252
- } else {
253
- o = {};
254
- for (const k of Object.keys(obj)) {
255
- o[k] = deepCopy(obj[k]);
256
- }
257
- }
258
- return o;
259
- } else {
260
- return obj;
261
- }
262
- }
263
- function parseMultiColorToSVG(config: any, id: any) {
264
- if (config.type == "linear") {
265
- const { stops, opacity } = config.linear;
266
- let start = [0, 0.5], end = [1, 0.5];
267
- const angle = config.linear.angle + 90;
268
- if (angle) {
269
- const center = [0.5, 0.5];
270
- start = pointRotate(start, center, deg2rad(angle));
271
- end = pointRotate(end, center, deg2rad(angle));
272
- }
273
- const _stops = deepCopy(stops); //深度复制再排序防止修改props
274
- _stops.sort((a: any, b: any) => a.offset - b.offset); //必须排序才能渲染出来
275
- return {
276
- fill: `url(#${id})`,
277
- def: React.createElement("linearGradient", {
278
- id,
279
- x2: start[0],
280
- y2: start[1],
281
- x1: end[0],
282
- y1: end[1],
283
- }, _stops.map((e: any) => {
284
- return React.createElement("stop", {
285
- key: e.offset,
286
- offset: e.offset / 100,
287
- stopColor: e.color,
288
- stopOpacity: opacity
289
- });
290
- })),
291
- firstColor: getTopColor(_stops,angle)
292
- }
293
- } else {
294
- return {
295
- fill: config.pure,
296
- firstColor: config.pure
297
- };
298
- }
299
- }
300
-
301
- function getTopColor(stops: any[], angle: number) {
302
- let a = angle % 360;
303
- if (a < 0) {
304
- a = 360 + a;
305
- }
306
- if (a >= 90 && a < 270) {
307
- return stops[stops.length - 1].color;
308
- } else {
309
- return stops[0].color;
310
- }
1
+ /**
2
+ * 立体柱状图的柱子
3
+ */
4
+ import React, { memo } from 'react';
5
+ import { min, max } from 'd3v7';
6
+ import {
7
+ getBandBackground,
8
+ getBandwidth,
9
+ getBandSeriesStepAndWidth,
10
+ } from '../utils';
11
+
12
+ const getHighlightData = (data: Array<DataWithBoundType>, extent: string) => {
13
+ switch (extent) {
14
+ case 'min':
15
+ const minData = min(data, (d: DataWithBoundType) => d.data.y);
16
+ return data.map((item) => ({
17
+ ...item,
18
+ flag: minData == item.data.y ? 'min' : '',
19
+ }));
20
+ case 'max':
21
+ const maxData = max(data, (d: DataWithBoundType) => d.data.y);
22
+ return data.map((item) => ({
23
+ ...item,
24
+ flag: maxData == item.data.y ? 'max' : '',
25
+ }));
26
+ default:
27
+ return data;
28
+ }
29
+ };
30
+
31
+ const getAttr = ({
32
+ isVertical,
33
+ seriesWidth,
34
+ length,
35
+ x,
36
+ y,
37
+ }: {
38
+ isVertical: boolean;
39
+ seriesWidth: number;
40
+ length: number;
41
+ x: number;
42
+ y: number;
43
+ }) => {
44
+ if (isVertical) return { width: length, height: seriesWidth, x: y, y: x };
45
+ return {
46
+ x,
47
+ y,
48
+ width: seriesWidth,
49
+ height: length,
50
+ };
51
+ };
52
+
53
+ const getBorderRadius = ({
54
+ isVertical,
55
+ positive,
56
+ seriesWidth,
57
+ }: {
58
+ isVertical: boolean;
59
+ positive: boolean;
60
+ seriesWidth: number;
61
+ }) => {
62
+ return isVertical
63
+ ? positive
64
+ ? '0px ' + seriesWidth + 'px ' + seriesWidth + 'px 0'
65
+ : seriesWidth + 'px 0 0 ' + seriesWidth + 'px'
66
+ : positive
67
+ ? seriesWidth / 2 + 'px ' + seriesWidth / 2 + 'px 0 0'
68
+ : '0 0 ' + seriesWidth / 2 + 'px ' + seriesWidth / 2 + 'px';
69
+ };
70
+
71
+ export default memo(
72
+ ({
73
+ triggerClick,
74
+ config: {
75
+ pattern = {},
76
+ seriesIntervalWidth: paddingInner = 0,
77
+ paddingInner: paddingOuter = 0,
78
+ style,
79
+ fill,
80
+ highlight: { show: showHighlight, extent, fill: highlightFill },
81
+ id
82
+ },
83
+ bandLength = 0,
84
+ data,
85
+ xAxis: { scaler: xScaler, step, direction },
86
+ yAxis: { scaler: yScaler },
87
+ fieldName
88
+ }: any) => {
89
+ if (!data.length) return null;
90
+ const bandwidth = getBandwidth(step, paddingOuter);
91
+ const { seriesStep, seriesWidth } = getBandSeriesStepAndWidth({
92
+ width: bandwidth,
93
+ paddingInner,
94
+ bandLength,
95
+ });
96
+
97
+ const _data = showHighlight ? getHighlightData(data, extent) : data;
98
+
99
+ const offset =
100
+ (seriesWidth + paddingInner * seriesStep) * bandLength -
101
+ paddingInner * seriesStep;
102
+
103
+ const isVertical = direction === 'vertical';
104
+
105
+ const highlightColor = parseMultiColorToSVG(highlightFill, "highlight_gradient_" + id + "_" + fieldName);
106
+ const color = parseMultiColorToSVG(fill, "gradient_" + id + "_" + fieldName);
107
+ return (
108
+ <g className='__easyv-band'>
109
+ <defs>
110
+ <filter id={`filter_front`}>
111
+ <feComponentTransfer>
112
+ <feFuncR type='linear' slope='0.5' />
113
+ <feFuncG type='linear' slope='0.5' />
114
+ <feFuncB type='linear' slope='0.5' />
115
+ </feComponentTransfer>
116
+ </filter>
117
+ <filter id={`filter_side`}>
118
+ <feComponentTransfer>
119
+ <feFuncR type='linear' slope='0.7' />
120
+ <feFuncG type='linear' slope='0.7' />
121
+ <feFuncB type='linear' slope='0.7' />
122
+ </feComponentTransfer>
123
+ </filter>
124
+ {highlightColor.def}
125
+ {color.def}
126
+ </defs>
127
+ {_data.map(
128
+ (
129
+ {
130
+ flag,
131
+ index,
132
+ bound: [start, end],
133
+ data,
134
+ data: { x, y, s },
135
+ }: DataWithBoundType,
136
+ i: number
137
+ ) => {
138
+ const y1 = yScaler(isVertical ? end : start);
139
+ const y2 = yScaler(isVertical ? start : end);
140
+ const positionX = xScaler(x) + seriesStep * index - offset / 2;
141
+ if (isNaN(positionX)) return null;
142
+ const positionY = y < 0 ? y1 : y2;
143
+ const attr = getAttr({
144
+ isVertical,
145
+ x: positionX,
146
+ y: positionY,
147
+ length: Math.abs(y1 - y2),
148
+ seriesWidth,
149
+ });
150
+
151
+ return (
152
+ <g
153
+ key={i}
154
+ onClick={triggerClick}
155
+ data-data={JSON.stringify(data)}
156
+ >
157
+ <Column3DSkin
158
+ {...attr}
159
+ color={extent === flag ? highlightColor : color}
160
+ />
161
+ </g>
162
+ );
163
+ }
164
+ )}
165
+ </g>
166
+ );
167
+ }
168
+ );
169
+
170
+
171
+ const Column3DSkin = function (props: any) {
172
+ const {
173
+ width,
174
+ height,
175
+ x,
176
+ y,
177
+ color,
178
+ opacity = 1,
179
+ } = props;
180
+ return (
181
+ <g
182
+ style={{
183
+ transform: `skew(0deg, 23deg)`,
184
+ transformOrigin: `${x + width / 2}px ${y + height / 2}px`,
185
+ opacity: opacity,
186
+ }}
187
+ >
188
+ {color.defs}
189
+ {/* 正面 */}
190
+ <rect
191
+ width={width / 2}
192
+ height={height}
193
+ x={x}
194
+ y={y}
195
+ fill={color.fill}
196
+ style={{ filter: `url(#filter_front)` }}
197
+ ></rect>
198
+ {/* 侧面 */}
199
+ <rect
200
+ width={width / 2}
201
+ height={height}
202
+ x={x + width / 2}
203
+ y={y}
204
+ fill={color.fill}
205
+ style={{
206
+ transformOrigin: `${x + width / 2}px ${y + height / 2}px`,
207
+ transform: 'skew(0deg, -45deg)',
208
+ }}
209
+ ></rect>
210
+ {/* 顶部 */}
211
+ <rect
212
+ width={width / 2}
213
+ height={width / 2}
214
+ x={x}
215
+ y={y}
216
+ fill={color.firstColor ? color.firstColor : color}
217
+ style={{
218
+ transformOrigin: `${x + (width / 4) * 3}px ${y}px`,
219
+ transform: `skew(-45deg) translate(0, -${width / 2}px)`,
220
+ }}
221
+ ></rect>
222
+ </g>
223
+ );
224
+ };
225
+
226
+
227
+ //以下都是为了解析multicolor
228
+ function pointRotate(point: any, center: any, angle: any) {
229
+ const
230
+ x = point[0],
231
+ y = point[1],
232
+ rx = center[0],
233
+ ry = center[1],
234
+ cos = Math.cos(angle),
235
+ sin = Math.sin(angle);
236
+ const x0 = (x - rx) * cos - (y - ry) * sin + rx;
237
+ const y0 = (x - rx) * sin + (y - ry) * cos + ry;
238
+ return [x0, y0];
239
+ }
240
+ const AngleTransfromRatio = 180 / Math.PI;
241
+ function deg2rad(deg: any) {
242
+ return deg / AngleTransfromRatio;
243
+ }
244
+ function deepCopy(obj: any): any {
245
+ if (typeof obj == "object") {
246
+ let o: any;
247
+ if (Array.isArray(obj)) {
248
+ o = [];
249
+ for (let i = 0; i < obj.length; i++) {
250
+ o.push(deepCopy(obj[i]));
251
+ }
252
+ } else {
253
+ o = {};
254
+ for (const k of Object.keys(obj)) {
255
+ o[k] = deepCopy(obj[k]);
256
+ }
257
+ }
258
+ return o;
259
+ } else {
260
+ return obj;
261
+ }
262
+ }
263
+ function parseMultiColorToSVG(config: any, id: any) {
264
+ if (config.type == "linear") {
265
+ const { stops, opacity } = config.linear;
266
+ let start = [0, 0.5], end = [1, 0.5];
267
+ const angle = config.linear.angle + 90;
268
+ if (angle) {
269
+ const center = [0.5, 0.5];
270
+ start = pointRotate(start, center, deg2rad(angle));
271
+ end = pointRotate(end, center, deg2rad(angle));
272
+ }
273
+ const _stops = deepCopy(stops); //深度复制再排序防止修改props
274
+ _stops.sort((a: any, b: any) => a.offset - b.offset); //必须排序才能渲染出来
275
+ return {
276
+ fill: `url(#${id})`,
277
+ def: React.createElement("linearGradient", {
278
+ id,
279
+ x2: start[0],
280
+ y2: start[1],
281
+ x1: end[0],
282
+ y1: end[1],
283
+ }, _stops.map((e: any) => {
284
+ return React.createElement("stop", {
285
+ key: e.offset,
286
+ offset: e.offset / 100,
287
+ stopColor: e.color,
288
+ stopOpacity: opacity
289
+ });
290
+ })),
291
+ firstColor: getTopColor(_stops,angle)
292
+ }
293
+ } else {
294
+ return {
295
+ fill: config.pure,
296
+ firstColor: config.pure
297
+ };
298
+ }
299
+ }
300
+
301
+ function getTopColor(stops: any[], angle: number) {
302
+ let a = angle % 360;
303
+ if (a < 0) {
304
+ a = 360 + a;
305
+ }
306
+ if (a >= 90 && a < 270) {
307
+ return stops[stops.length - 1].color;
308
+ } else {
309
+ return stops[0].color;
310
+ }
311
311
  }