@easyv/charts 1.6.18 → 1.6.20

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