@easyv/charts 1.4.22 → 1.4.25

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.
@@ -8,11 +8,13 @@ import React, {
8
8
  useContext,
9
9
  CSSProperties,
10
10
  MouseEventHandler,
11
+ forwardRef,
11
12
  } from "react";
12
13
  import { getTickCoord, getGridCoord, getFontStyle } from "../utils";
13
14
  import { chartContext } from "../context";
14
15
  import { Line } from "../element";
15
16
  import TextOverflow from "./TextOverflow";
17
+ import { path } from "d3";
16
18
  const defaultEvent = () => {};
17
19
  const defaultAppearance = {
18
20
  angle: 0,
@@ -250,201 +252,239 @@ const Label: (
250
252
  };
251
253
 
252
254
  export default memo(
253
- ({
254
- orientation,
255
- scaler,
256
- tickSize = defaultTickSize,
257
- ticks,
258
- formatter,
259
- rotate,
260
- triggerClick,
261
- config: { on, label, axisLine, tickLine, gridLine, unit },
262
- config,
263
- positions,
264
- xLineRange,
265
- //断轴图相关
266
- isClipAxis = false,
267
- yLineRange,
268
- clipAxisRange,
269
- }: any) => {
270
- if (!(on && ticks.length > 0)) return null;
271
- const { width, height } = useContext(chartContext);
272
- const x = orientation == "right" ? width : 0;
273
- const y = orientation == "bottom" ? height : 0;
255
+ forwardRef(
256
+ (
257
+ {
258
+ orientation,
259
+ scaler,
260
+ tickSize = defaultTickSize,
261
+ ticks,
262
+ formatter,
263
+ rotate,
264
+ triggerClick,
265
+ config: { on, label, axisLine, tickLine, gridLine, unit },
266
+ config,
267
+ positions,
268
+ xLineRange,
269
+ range,
270
+ axisType,
271
+ //断轴图相关
272
+ isClipAxis = false,
273
+ yLineRange,
274
+ clipAxisRange,
275
+ //控制图相关
276
+ isControlChart,
277
+ controlConfig,
278
+ controlEnd,
279
+ rawTicks,
280
+ }: any,
281
+ ref
282
+ ) => {
283
+ if (!(on && ticks.length > 0)) return null;
284
+ const { width, height } = useContext(chartContext);
285
+ const x = orientation == "right" ? width : 0;
286
+ const y = orientation == "bottom" ? height : 0;
274
287
 
275
- function drawYAxisTickLine() {
276
- const draw = (ticks: any, scaler: any) => {
277
- return ticks.map((tick: string, index: number) => {
278
- const coordinate = scaler(tick);
279
- if (isNaN(coordinate)) return null;
280
- const _tickSize = tickLine.tickSize || tickSize;
281
- const gridCoord = getGridCoord({
282
- orientation,
283
- coordinate,
284
- end:
285
- orientation == "left" || orientation == "right" ? width : height,
288
+ function drawAxisTickLine() {
289
+ const draw = (ticks: any, scaler: any) => {
290
+ return ticks.map((tick: string, index: number) => {
291
+ const coordinate = scaler(tick);
292
+ if (isNaN(coordinate)) return null;
293
+ const _tickSize = tickLine.tickSize || tickSize;
294
+ const gridCoord = getGridCoord({
295
+ orientation,
296
+ coordinate,
297
+ end:
298
+ orientation == "left" || orientation == "right"
299
+ ? width
300
+ : height,
301
+ });
302
+
303
+ const x1 = gridCoord.x1;
304
+ const y1 = gridCoord.y1;
305
+ return (
306
+ !(
307
+ (orientation == "bottom" && (x1 < 0 || x1 > xLineRange)) ||
308
+ y1 < 0 ||
309
+ y1 > yLineRange
310
+ ) && (
311
+ <Line
312
+ className="__easyv-tickLine"
313
+ key={index}
314
+ config={tickLine}
315
+ {...getTickCoord({
316
+ orientation,
317
+ coordinate,
318
+ tickSize: _tickSize,
319
+ })}
320
+ />
321
+ )
322
+ );
286
323
  });
324
+ };
287
325
 
288
- const x1 = gridCoord.x1;
289
- const y1 = gridCoord.y1;
326
+ if (isClipAxis) {
290
327
  return (
291
- !(
292
- (orientation == "bottom" && (x1 < 0 || x1 > xLineRange)) ||
293
- y1 < 0 ||
294
- y1 > yLineRange
295
- ) && (
296
- <Line
297
- className="__easyv-tickLine"
298
- key={index}
299
- config={tickLine}
300
- {...getTickCoord({
301
- orientation,
302
- coordinate,
303
- tickSize: _tickSize,
304
- })}
305
- />
306
- )
328
+ <>
329
+ {ticks.map((ticks: any, index: number) => {
330
+ return draw(ticks, scaler[index]);
331
+ })}
332
+ </>
307
333
  );
308
- });
309
- };
310
-
311
- if (isClipAxis) {
312
- return (
313
- <>
314
- {ticks.map((ticks: any, index: number) => {
315
- return draw(ticks, scaler[index]);
316
- })}
317
- </>
318
- );
319
- } else {
320
- return <>{draw(ticks, scaler)}</>;
334
+ } else {
335
+ return <>{draw(ticks, scaler)}</>;
336
+ }
321
337
  }
322
- }
323
338
 
324
- function drawLabel() {
325
- const draw = (ticks: any, scaler: any) => {
326
- return ticks.map((tick: string, index: number) => {
327
- const coordinate = scaler(tick);
328
- if (isNaN(coordinate)) return null;
329
- const _tickSize = tickLine.tickSize || tickSize;
330
- const gridCoord = getGridCoord({
331
- orientation,
332
- coordinate,
333
- end:
334
- orientation == 'left' || orientation == 'right'
335
- ? width
336
- : height,
339
+ function drawLabel() {
340
+ const draw = (ticks: any, scaler: any) => {
341
+ return ticks.map((tick: string, index: number) => {
342
+ const coordinate = scaler(tick);
343
+ if (isNaN(coordinate)) return null;
344
+ const _tickSize = tickLine.tickSize || tickSize;
345
+ const gridCoord = getGridCoord({
346
+ orientation,
347
+ coordinate,
348
+ end:
349
+ orientation == "left" || orientation == "right"
350
+ ? width
351
+ : height,
352
+ });
353
+ const x1 = gridCoord.x1;
354
+ const y1 = gridCoord.y1;
355
+ return (
356
+ (!(
357
+ (orientation == "bottom" && (x1 < 0 || x1 > xLineRange)) ||
358
+ y1 < 0 ||
359
+ y1 > yLineRange
360
+ ) ||
361
+ isControlChart) && (
362
+ <g key={index}>
363
+ {label && (
364
+ <Label
365
+ className="__easyv-label"
366
+ orientation={orientation}
367
+ coordinate={coordinate}
368
+ config={label}
369
+ label={tick}
370
+ tickSize={_tickSize}
371
+ formatter={formatter}
372
+ rotate={rotate}
373
+ onClick={triggerClick}
374
+ />
375
+ )}
376
+ {gridLine && (
377
+ <Line
378
+ className="__easyv-gridLine"
379
+ config={gridLine}
380
+ {...gridCoord}
381
+ />
382
+ )}
383
+ </g>
384
+ )
385
+ );
337
386
  });
338
- const x1 = gridCoord.x1;
339
- const y1 = gridCoord.y1;
387
+ };
388
+ if (isClipAxis) {
340
389
  return (
341
- !(orientation=="bottom" && (x1<0 || x1>xLineRange) || (y1<0 || y1>yLineRange)) && <g key={index}>
342
- {label && (
343
- <Label
344
- className='__easyv-label'
345
- orientation={orientation}
346
- coordinate={coordinate}
347
- config={label}
348
- label={tick}
349
- tickSize={_tickSize}
350
- formatter={formatter}
351
- rotate={rotate}
352
- onClick={triggerClick}
353
- />
354
- )}
355
- {gridLine && (
356
- <Line
357
- className='__easyv-gridLine'
358
- config={gridLine}
359
- {...gridCoord}
360
- />
361
- )}
362
- </g>
390
+ <>
391
+ {ticks.map((ticks: any, index: number) => {
392
+ return draw(ticks, scaler[index]);
393
+ })}
394
+ </>
363
395
  );
364
- })
396
+ } else if (isControlChart && orientation == "bottom") {
397
+ return <>{draw(rawTicks, scaler)}</>;
398
+ } else {
399
+ return <>{draw(ticks, scaler)}</>;
400
+ }
365
401
  }
366
- if (isClipAxis) {
367
- return (
368
- <>
369
- {ticks.map((ticks: any, index: number) => {
370
- return draw(ticks, scaler[index]);
371
- })}
372
- </>
373
- );
374
- } else {
375
- return <>{draw(ticks, scaler)}</>;
376
- }
377
- }
378
402
 
379
- return (
380
- <>
381
- {/* 绘制轴线和刻度 */}
382
- {axisLine && tickLine && (
383
- <>
384
- {axisLine &&
385
- // 依据positions来区分x轴y轴,有position为x轴
386
- (positions && positions.length ? (
387
- positions.map(({ x, y }: any, index: number) => (
388
- <g key={index} transform={"translate(" + x + ", " + y + ")"}>
389
- <AxisLine orientation={orientation} config={axisLine} />
390
- {tickLine &&
391
- ticks.map((tick: string, index: number) => {
392
- const coordinate = scaler(tick);
393
- if (isNaN(coordinate)) return null;
394
- const _tickSize = tickLine.tickSize || tickSize;
395
- const gridCoord = getGridCoord({
396
- orientation,
397
- coordinate,
398
- end:
399
- orientation == "left" || orientation == "right"
400
- ? width
401
- : height,
402
- });
403
- const x1 = gridCoord.x1;
404
- const y1 = gridCoord.y1;
405
- return (
406
- !(
407
- (orientation == "bottom" &&
408
- (x1 < 0 || x1 > xLineRange)) ||
409
- y1 < 0 ||
410
- y1 > yLineRange
411
- ) && (
412
- <Line
413
- className="__easyv-tickLine"
414
- key={index}
415
- config={tickLine}
416
- {...getTickCoord({
417
- orientation,
418
- coordinate,
419
- tickSize: _tickSize,
420
- })}
421
- />
422
- )
423
- );
424
- })}
403
+ return (
404
+ <g>
405
+ {/* 绘制轴线和刻度 */}
406
+ {axisLine && tickLine && (
407
+ <g>
408
+ {axisLine &&
409
+ (positions && positions.length ? (
410
+ positions.map(({ x, y }: any, index: number) => (
411
+ <g
412
+ key={index}
413
+ transform={"translate(" + x + ", " + y + ")"}
414
+ >
415
+ <AxisLine
416
+ orientation={orientation}
417
+ config={axisLine}
418
+ range={range}
419
+ />
420
+ {tickLine &&
421
+ ticks.map((tick: string, index: number) => {
422
+ const coordinate = scaler(tick);
423
+ if (isNaN(coordinate)) return null;
424
+ const _tickSize = tickLine.tickSize || tickSize;
425
+ const gridCoord = getGridCoord({
426
+ orientation,
427
+ coordinate,
428
+ end:
429
+ orientation == "left" || orientation == "right"
430
+ ? width
431
+ : height,
432
+ });
433
+ const x1 = gridCoord.x1;
434
+ const y1 = gridCoord.y1;
435
+ return (
436
+ !(
437
+ (orientation == "bottom" &&
438
+ (x1 < 0 || x1 > xLineRange)) ||
439
+ y1 < 0 ||
440
+ y1 > yLineRange
441
+ ) && (
442
+ <Line
443
+ className="__easyv-tickLine"
444
+ key={index}
445
+ config={tickLine}
446
+ {...getTickCoord({
447
+ orientation,
448
+ coordinate,
449
+ tickSize: _tickSize,
450
+ })}
451
+ />
452
+ )
453
+ );
454
+ })}
455
+ </g>
456
+ ))
457
+ ) : (
458
+ <g transform={"translate(" + x + ", " + y + ")"}>
459
+ <AxisLine
460
+ orientation={orientation}
461
+ config={axisLine}
462
+ isClipAxis={isClipAxis}
463
+ clipAxisRange={clipAxisRange}
464
+ />
465
+ {tickLine && drawAxisTickLine()}
425
466
  </g>
426
- ))
427
- ) : (
428
- <g transform={"translate(" + x + ", " + y + ")"}>
429
- <AxisLine
430
- orientation={orientation}
431
- config={axisLine}
432
- isClipAxis={isClipAxis}
433
- clipAxisRange={clipAxisRange}
434
- />
435
- {tickLine && drawYAxisTickLine()}
436
- </g>
437
- ))}
438
- </>
439
- )}
440
- {/* 绘制标签和网格线 */}
441
- <g transform={'translate(' + x + ', ' + y + ')'}>
442
- {label &&
443
- gridLine && drawLabel()
444
- }
445
- {unit && <Unit config={unit} />}
467
+ ))}
468
+ </g>
469
+ )}
470
+ {/* 绘制标签和网格线 */}
471
+ <svg
472
+ width={width}
473
+ style={{
474
+ overflow:
475
+ axisType !== "x" && isControlChart ? "visible" : "hidden",
476
+ }}
477
+ >
478
+ <g transform={"translate(" + x + ", " + y + ")"}>
479
+ {/* 用于控制图 */}
480
+ <g ref={ref as any}>
481
+ {label && gridLine && drawLabel()}
482
+ {unit && <Unit config={unit} />}
483
+ </g>
484
+ </g>
485
+ </svg>
446
486
  </g>
447
- </>
448
- );
449
- }
487
+ );
488
+ }
489
+ )
450
490
  );
@@ -66,7 +66,15 @@ const getBorderRadius = ({
66
66
 
67
67
  export default memo(
68
68
  ({
69
+ //控制图部分,主要是为了控制图的指示器,在悬浮的时候显示
69
70
  triggerClick,
71
+ indicatorWidth,
72
+ setControlChartTooltipShow,
73
+ setControlChartTooltipX,
74
+ setControlChartTooltipXName,
75
+ isControlChart = false,
76
+ setControlChartIndicatorList,
77
+
70
78
  config: {
71
79
  pattern = {},
72
80
  seriesIntervalWidth: paddingInner = 0,
@@ -84,6 +92,7 @@ export default memo(
84
92
  bandLength = 0,
85
93
  data,
86
94
  xAxis: { scaler: xScaler, step, direction },
95
+ xAxis,
87
96
  yAxis: { scaler: yScaler, isClipAxis, clipValue },
88
97
  }: any) => {
89
98
  if (!data.length) return null;
@@ -112,8 +121,7 @@ export default memo(
112
121
  }: DataWithBoundType,
113
122
  i: number
114
123
  ) => {
115
- //todo 柱状中空设置
116
- let y1:number, y2: number;
124
+ let y1: number, y2: number;
117
125
  //断轴图相关,断轴图的scaler是一个数组,内含上断轴下断轴的scaler
118
126
  if (isClipAxis) {
119
127
  if (end > +clipValue) {
@@ -144,9 +152,9 @@ export default memo(
144
152
  if (isClipAxis && end > +clipValue) {
145
153
  let clipValueY2 = yScaler[0](clipValue); //上方
146
154
  let clipValueY1 = yScaler[1](clipValue); //下方
147
- let top = Math.abs((y2-clipValueY2)/(y1-y2))*100;
148
- let bottom = Math.abs((y2-clipValueY1)/(y1-y2))*100;
149
-
155
+ let top = Math.abs((y2 - clipValueY2) / (y1 - y2)) * 100;
156
+ let bottom = Math.abs((y2 - clipValueY1) / (y1 - y2)) * 100;
157
+
150
158
  //clip path属性
151
159
  return `polygon(0% 0%, 0% 100%, 0 100%, 0 ${top}%, 100% ${top}%, 100% ${bottom}%, 0 ${bottom}%, 0 100%, 100% 100%, 100% 0%)`;
152
160
  } else {
@@ -172,6 +180,33 @@ export default memo(
172
180
  }}
173
181
  {...attr}
174
182
  onClick={triggerClick}
183
+ //enter和leave事件,用于控制图的提示框
184
+ onMouseEnter={() => {
185
+ if (isControlChart) {
186
+ setControlChartIndicatorList((v: any) => {
187
+ return v.map((item: any) => {
188
+ if (item.tick === data.x) {
189
+ return { ...item, isShow: true };
190
+ } else {
191
+ return item;
192
+ }
193
+ });
194
+ });
195
+ setControlChartTooltipShow(true);
196
+ setControlChartTooltipX(xScaler(x) - indicatorWidth / 2);
197
+ setControlChartTooltipXName(data.x);
198
+ }
199
+ }}
200
+ onMouseLeave={() => {
201
+ if (isControlChart) {
202
+ setControlChartIndicatorList((v: any) =>
203
+ v.map((item: any) => ({ ...item, isShow: false }))
204
+ );
205
+ setControlChartTooltipShow(false);
206
+ setControlChartTooltipXName(undefined);
207
+ setControlChartTooltipX(undefined);
208
+ }
209
+ }}
175
210
  data-data={JSON.stringify(data)}
176
211
  >
177
212
  {headUrl && showHead && (