@fc-plot/ts-graph 0.16.5 → 0.17.2

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/src/index.ts CHANGED
@@ -1,18 +1,36 @@
1
- import * as d3 from 'd3';
2
- import { assign, merge, debounce, throttle, uniqueId, isEmpty, find, sortBy } from 'lodash';
3
- import { addListener, removeListener } from 'resize-detector';
4
- import EventEmitter from 'events';
5
- import XAxis from './xAxis';
6
- import YAxis from './yAxis';
7
- import Tooltip from './tooltip';
8
- import Line from './line';
9
- import Bar from './bar';
10
- import Zoom from './zoom';
11
- import Legend from './legend';
12
- import Shapes from './shapes';
13
- import { TsGraphType, Options, EventPosition, Transform, Serie, SerieDataItem, XScales, YScales } from './interface';
14
- import { getTouchPosition, getYkeyValue } from './utils';
15
- import '../assets/style.less';
1
+ import * as d3 from "d3";
2
+ import {
3
+ assign,
4
+ merge,
5
+ debounce,
6
+ throttle,
7
+ uniqueId,
8
+ isEmpty,
9
+ find,
10
+ sortBy,
11
+ } from "lodash";
12
+ import { addListener, removeListener } from "resize-detector";
13
+ import EventEmitter from "events";
14
+ import XAxis from "./xAxis";
15
+ import YAxis from "./yAxis";
16
+ import Tooltip from "./tooltip";
17
+ import Line from "./line";
18
+ import Bar from "./bar";
19
+ import Zoom from "./zoom";
20
+ import Legend from "./legend";
21
+ import Shapes from "./shapes";
22
+ import {
23
+ TsGraphType,
24
+ Options,
25
+ EventPosition,
26
+ Transform,
27
+ Serie,
28
+ SerieDataItem,
29
+ XScales,
30
+ YScales,
31
+ } from "./interface";
32
+ import { getTouchPosition, getYkeyValue } from "./utils";
33
+ import "../assets/style.less";
16
34
 
17
35
  const eventEmitter = new EventEmitter();
18
36
  export default class TsGraph {
@@ -39,11 +57,28 @@ export default class TsGraph {
39
57
  ratio: window.devicePixelRatio || 1,
40
58
  xkey: 0,
41
59
  ykey: 1,
42
- oykey: '__originValue', // stack area 用于缓存原始值
43
- timestamp: 'x',
60
+ ykey2: 2,
61
+ oykey: "__originValue", // stack area 用于缓存原始值
62
+ timestamp: "x",
44
63
  chart: {
45
- id: uniqueId('ts-graph-'),
46
- colors: ['#3399CC', '#CC9933', '#9966CC', '#66CC66', '#CC3333', '#99CCCC', '#CCCC66', '#CC99CC', '#99CC99', '#CC6666', '#336699', '#996633', '#993399', '#339966', '#993333'],
64
+ id: uniqueId("ts-graph-"),
65
+ colors: [
66
+ "#3399CC",
67
+ "#CC9933",
68
+ "#9966CC",
69
+ "#66CC66",
70
+ "#CC3333",
71
+ "#99CCCC",
72
+ "#CCCC66",
73
+ "#CC99CC",
74
+ "#99CC99",
75
+ "#CC6666",
76
+ "#336699",
77
+ "#996633",
78
+ "#993399",
79
+ "#339966",
80
+ "#993333",
81
+ ],
47
82
  width: userOptions.chart.renderTo.offsetWidth,
48
83
  height: userOptions.chart.renderTo.offsetHeight || 350,
49
84
  marginTop: 10,
@@ -53,13 +88,13 @@ export default class TsGraph {
53
88
  },
54
89
  xAxis: {
55
90
  visible: true,
56
- lineColor: '#ccc',
91
+ lineColor: "#ccc",
57
92
  lineWidth: 1,
58
93
  tickLength: 5,
59
94
  tickpadding: 5,
60
- tickColor: '#ccc',
95
+ tickColor: "#ccc",
61
96
  labels: {
62
- color: '#999',
97
+ color: "#999",
63
98
  fontSize: 11,
64
99
  },
65
100
  },
@@ -67,18 +102,18 @@ export default class TsGraph {
67
102
  // min: -Infinity,
68
103
  // max: Infinity,
69
104
  visible: true,
70
- lineColor: '#ccc',
105
+ lineColor: "#ccc",
71
106
  lineWidth: 1,
72
107
  tickLength: 5,
73
108
  tickpadding: 5,
74
- tickColor: '#ccc',
75
- gridLineColor: '#efefef',
109
+ tickColor: "#ccc",
110
+ gridLineColor: "#efefef",
76
111
  labels: {
77
- color: '#999',
112
+ color: "#999",
78
113
  fontSize: 11,
79
114
  },
80
115
  },
81
- type: 'line',
116
+ type: "line",
82
117
  line: {
83
118
  enable: true,
84
119
  width: 2,
@@ -99,12 +134,12 @@ export default class TsGraph {
99
134
  shared: true,
100
135
  cascade: false, // tooltip 联动
101
136
  cascadeScope: undefined, // tooltip 联动的范围
102
- timeFormat: '%Y-%m-%d %H:%M:%S',
137
+ timeFormat: "%Y-%m-%d %H:%M:%S",
103
138
  },
104
139
  series: [],
105
140
  legend: {
106
- align: 'center',
107
- verticalAlign: 'top',
141
+ align: "center",
142
+ verticalAlign: "top",
108
143
  enabled: false,
109
144
  },
110
145
  fillNull: undefined,
@@ -130,17 +165,19 @@ export default class TsGraph {
130
165
  this.options.notDisplayedSeries = [];
131
166
  this.options.chart.containerWidth = chart.width;
132
167
  this.options.chart.containerHeight = chart.height;
133
- this.options.chart.width = chart.width - chart.marginLeft - chart.marginRight;
134
- this.options.chart.height = chart.height - chart.marginTop - chart.marginBottom;
168
+ this.options.chart.width =
169
+ chart.width - chart.marginLeft - chart.marginRight;
170
+ this.options.chart.height =
171
+ chart.height - chart.marginTop - chart.marginBottom;
135
172
  this.createContainer();
136
173
  this.createCanvas();
137
174
  this.initSeries();
138
175
  this.initScales();
139
176
  this.initEvent();
140
- if (this.options.type === 'line') {
177
+ if (this.options.type === "line") {
141
178
  this.initLine();
142
179
  }
143
- if (this.options.type === 'bar') {
180
+ if (this.options.type === "bar") {
144
181
  this.initBar();
145
182
  }
146
183
  this.initLegend();
@@ -151,7 +188,9 @@ export default class TsGraph {
151
188
  }
152
189
 
153
190
  clearRect(ctx: CanvasRenderingContext2D) {
154
- const { chart: { containerWidth, containerHeight } } = this.options;
191
+ const {
192
+ chart: { containerWidth, containerHeight },
193
+ } = this.options;
155
194
 
156
195
  ctx.clearRect(0, 0, containerWidth, containerHeight);
157
196
  }
@@ -161,10 +200,10 @@ export default class TsGraph {
161
200
  if (this.options.xAxis.visible) {
162
201
  this.yAxis.drawGridLine(this.yScales);
163
202
  }
164
- if (this.options.type === 'line') {
203
+ if (this.options.type === "line") {
165
204
  this.line.draw(this.xScales, this.yScales);
166
205
  }
167
- if (this.options.type === 'bar') {
206
+ if (this.options.type === "bar") {
168
207
  this.bar.draw(this.xScales, this.yScales, transform);
169
208
  }
170
209
  if (this.options.xAxis.visible) {
@@ -195,10 +234,10 @@ export default class TsGraph {
195
234
  this.initSeries();
196
235
  this.initScales();
197
236
  this.initEvent();
198
- if (this.options.type === 'line') {
237
+ if (this.options.type === "line") {
199
238
  this.initLine();
200
239
  }
201
- if (this.options.type === 'bar') {
240
+ if (this.options.type === "bar") {
202
241
  this.initBar();
203
242
  }
204
243
  this.initTooltip();
@@ -213,16 +252,18 @@ export default class TsGraph {
213
252
 
214
253
  showTooltip = (eventPosition: EventPosition) => {
215
254
  this.tooltip.draw(eventPosition, this);
216
- }
255
+ };
217
256
 
218
257
  hideTooltip = () => {
219
258
  this.tooltip.clear();
220
- }
259
+ };
221
260
 
222
261
  initEvent() {
223
262
  const { cascade, cascadeScope } = this.options.tooltip;
224
- const plotmoveType = cascadeScope ? `plotmove:${cascadeScope}` : 'plotmove';
225
- const plotleaveType = cascadeScope ? `plotleave:${cascadeScope}` : 'plotleave';
263
+ const plotmoveType = cascadeScope ? `plotmove:${cascadeScope}` : "plotmove";
264
+ const plotleaveType = cascadeScope
265
+ ? `plotleave:${cascadeScope}`
266
+ : "plotleave";
226
267
  let mousedownStatus = false;
227
268
  let mousedownPos: EventPosition = {} as EventPosition;
228
269
  let mouseupPos: EventPosition = {} as EventPosition;
@@ -241,72 +282,107 @@ export default class TsGraph {
241
282
  const handleMouseLeave = throttle(() => {
242
283
  _this.tooltip.clear();
243
284
  }, 5);
244
- d3.select(this.eventCanvas).on('mousemove', function mousemove(this: HTMLCanvasElement) {
245
- isMouserover = true;
246
- handleMouseover(d3.event);
247
- if (cascade) eventEmitter.emit(plotmoveType, d3.event);
248
- }).on('mouseleave', function mouseleave(this: HTMLCanvasElement) {
249
- mouseleavePos = d3.event;
250
- isMouserover = false;
251
- handleMouseLeave();
252
- if (cascade) eventEmitter.emit(plotleaveType);
253
- }).on('mousedown', function mousedown(this: HTMLCanvasElement) {
254
- if (d3.event.which === 1) {
255
- mousedownStatus = true;
256
- mousedownPos = d3.event;
257
- }
258
- }).on('mouseup', function mouseup(this: HTMLCanvasElement) {
259
- d3.event.stopPropagation();
260
- const eventPosition = d3.event as EventPosition;
261
- if (mousedownPos && (mousedownPos.offsetX !== eventPosition.offsetX)) {
262
- _this.zoom.clearMarker();
263
- _this.zoom.onZoom(mousedownPos, eventPosition, (transform: Transform) => {
264
- _this.handleZoom(transform, [mousedownPos, eventPosition]);
265
- });
266
- } else {
267
- _this.options.onClick(d3.event, _this.xScales.invert(d3.event.offsetX), _this.yScales.invert(d3.event.offsetY));
268
- }
269
- mousedownStatus = false;
270
- mousedownPos = {} as EventPosition;
271
- }).on('contextmenu', function contextmenu() {
272
- _this.options.onRightClick(d3.event, _this.xScales.invert(d3.event.offsetX), _this.yScales.invert(d3.event.offsetY));
273
- d3.event.preventDefault();
274
- }).on('touchstart', function touchmove(this: HTMLCanvasElement) {
275
- // 模拟 mousedown
276
- if (d3.event.touches.length > 1) {
277
- mousedownStatus = true;
278
- // mousedownPos = getTouchPosition(_this.eventCanvas, d3.event);
279
- }
280
- }).on('touchmove', function touchmove(this: HTMLCanvasElement) {
281
- const eventPosition = getTouchPosition(_this.eventCanvas, d3.event) as EventPosition;
282
-
283
- if (d3.event.touches.length === 1) {
284
- _this.tooltip.draw(eventPosition, _this);
285
- }
286
-
287
- // 触发 zoom marker
288
- if (mousedownStatus) {
289
- mousedownPos = eventPosition;
290
- mouseupPos = getTouchPosition(_this.eventCanvas, d3.event, 1) as EventPosition;
291
- _this.zoom.drawMarker(mousedownPos, mouseupPos);
292
- }
293
- }).on('touchend', function mouseleave(this: HTMLCanvasElement) {
294
- isMouserover = false;
295
- handleMouseLeave();
285
+ d3.select(this.eventCanvas)
286
+ .on("mousemove", function mousemove(this: HTMLCanvasElement) {
287
+ isMouserover = true;
288
+ handleMouseover(d3.event);
289
+ if (cascade) eventEmitter.emit(plotmoveType, d3.event);
290
+ })
291
+ .on("mouseleave", function mouseleave(this: HTMLCanvasElement) {
292
+ mouseleavePos = d3.event;
293
+ isMouserover = false;
294
+ handleMouseLeave();
295
+ if (cascade) eventEmitter.emit(plotleaveType);
296
+ })
297
+ .on("mousedown", function mousedown(this: HTMLCanvasElement) {
298
+ if (d3.event.which === 1) {
299
+ mousedownStatus = true;
300
+ mousedownPos = d3.event;
301
+ }
302
+ })
303
+ .on("mouseup", function mouseup(this: HTMLCanvasElement) {
304
+ d3.event.stopPropagation();
305
+ const eventPosition = d3.event as EventPosition;
306
+ if (mousedownPos && mousedownPos.offsetX !== eventPosition.offsetX) {
307
+ _this.zoom.clearMarker();
308
+ _this.zoom.onZoom(
309
+ mousedownPos,
310
+ eventPosition,
311
+ (transform: Transform) => {
312
+ _this.handleZoom(transform, [mousedownPos, eventPosition]);
313
+ }
314
+ );
315
+ } else {
316
+ _this.options.onClick(
317
+ d3.event,
318
+ _this.xScales.invert(d3.event.offsetX),
319
+ _this.yScales.invert(d3.event.offsetY)
320
+ );
321
+ }
322
+ mousedownStatus = false;
323
+ mousedownPos = {} as EventPosition;
324
+ })
325
+ .on("contextmenu", function contextmenu() {
326
+ _this.options.onRightClick(
327
+ d3.event,
328
+ _this.xScales.invert(d3.event.offsetX),
329
+ _this.yScales.invert(d3.event.offsetY)
330
+ );
331
+ d3.event.preventDefault();
332
+ })
333
+ .on("touchstart", function touchmove(this: HTMLCanvasElement) {
334
+ // 模拟 mousedown
335
+ if (d3.event.touches.length > 1) {
336
+ mousedownStatus = true;
337
+ // mousedownPos = getTouchPosition(_this.eventCanvas, d3.event);
338
+ }
339
+ })
340
+ .on("touchmove", function touchmove(this: HTMLCanvasElement) {
341
+ const eventPosition = getTouchPosition(
342
+ _this.eventCanvas,
343
+ d3.event
344
+ ) as EventPosition;
345
+
346
+ if (d3.event.touches.length === 1) {
347
+ _this.tooltip.draw(eventPosition, _this);
348
+ }
296
349
 
297
- // 触发 zoom
298
- if (mousedownPos && (mousedownPos.offsetX !== mouseupPos.offsetX)) {
299
- _this.zoom.clearMarker();
300
- _this.zoom.onZoom(mousedownPos, mouseupPos, (transform: Transform) => {
301
- _this.handleZoom(transform, [mousedownPos, mouseupPos]);
302
- });
303
- } else {
304
- _this.options.onClick(d3.event, _this.xScales.invert(d3.event.offsetX), _this.yScales.invert(d3.event.offsetY));
305
- }
306
- mousedownStatus = false;
307
- mousedownPos = {} as EventPosition;
308
- mouseupPos = {} as EventPosition;
309
- });
350
+ // 触发 zoom marker
351
+ if (mousedownStatus) {
352
+ mousedownPos = eventPosition;
353
+ mouseupPos = getTouchPosition(
354
+ _this.eventCanvas,
355
+ d3.event,
356
+ 1
357
+ ) as EventPosition;
358
+ _this.zoom.drawMarker(mousedownPos, mouseupPos);
359
+ }
360
+ })
361
+ .on("touchend", function mouseleave(this: HTMLCanvasElement) {
362
+ isMouserover = false;
363
+ handleMouseLeave();
364
+
365
+ // 触发 zoom
366
+ if (mousedownPos && mousedownPos.offsetX !== mouseupPos.offsetX) {
367
+ _this.zoom.clearMarker();
368
+ _this.zoom.onZoom(
369
+ mousedownPos,
370
+ mouseupPos,
371
+ (transform: Transform) => {
372
+ _this.handleZoom(transform, [mousedownPos, mouseupPos]);
373
+ }
374
+ );
375
+ } else {
376
+ _this.options.onClick(
377
+ d3.event,
378
+ _this.xScales.invert(d3.event.offsetX),
379
+ _this.yScales.invert(d3.event.offsetY)
380
+ );
381
+ }
382
+ mousedownStatus = false;
383
+ mousedownPos = {} as EventPosition;
384
+ mouseupPos = {} as EventPosition;
385
+ });
310
386
 
311
387
  if (cascade) {
312
388
  eventEmitter.on(plotmoveType, this.showTooltip);
@@ -314,14 +390,18 @@ export default class TsGraph {
314
390
  }
315
391
 
316
392
  // TODO: removeListener
317
- window.addEventListener('mouseup', () => {
393
+ window.addEventListener("mouseup", () => {
318
394
  if (!isEmpty(mousedownPos)) {
319
395
  const eventPosition = mouseleavePos;
320
396
  mousedownStatus = false;
321
397
  _this.zoom.clearMarker();
322
- _this.zoom.onZoom(mousedownPos, eventPosition, (transform: Transform) => {
323
- _this.handleZoom(transform, [mousedownPos, eventPosition]);
324
- });
398
+ _this.zoom.onZoom(
399
+ mousedownPos,
400
+ eventPosition,
401
+ (transform: Transform) => {
402
+ _this.handleZoom(transform, [mousedownPos, eventPosition]);
403
+ }
404
+ );
325
405
  mousedownPos = {} as EventPosition;
326
406
  }
327
407
  });
@@ -330,12 +410,17 @@ export default class TsGraph {
330
410
  }
331
411
 
332
412
  getZoomedSeries = () => {
333
- const { chart: { renderTo }, series, timestamp, xkey } = this.options;
413
+ const {
414
+ chart: { renderTo },
415
+ series,
416
+ timestamp,
417
+ xkey,
418
+ } = this.options;
334
419
  const renderToWidth = renderTo.offsetWidth;
335
420
  return series.map((serie) => {
336
- if (Object.prototype.toString.call(serie.data) === '[object Array]') {
421
+ if (Object.prototype.toString.call(serie.data) === "[object Array]") {
337
422
  const data = serie.data.filter((point) => {
338
- const xVal = timestamp === 'X' ? point[xkey] * 1000 : point[xkey];
423
+ const xVal = timestamp === "X" ? point[xkey] * 1000 : point[xkey];
339
424
  const x = this.xScales(new Date(xVal));
340
425
  return x >= 0 && x <= renderToWidth;
341
426
  });
@@ -346,7 +431,7 @@ export default class TsGraph {
346
431
  }
347
432
  return serie;
348
433
  });
349
- }
434
+ };
350
435
 
351
436
  handleResize = () => {
352
437
  const { chart } = this.options;
@@ -359,23 +444,25 @@ export default class TsGraph {
359
444
  this.options.chart.containerHeight = height;
360
445
  this.container.style.width = `${width}px`;
361
446
  this.container.style.height = `${height}px`;
362
- this.retinaScaled(this.backCanvas, 'back');
363
- this.retinaScaled(this.frontCanvas, 'front');
364
- this.retinaScaled(this.eventCanvas, 'event');
447
+ this.retinaScaled(this.backCanvas, "back");
448
+ this.retinaScaled(this.frontCanvas, "front");
449
+ this.retinaScaled(this.eventCanvas, "event");
365
450
  this.initScales();
366
451
  this.initZoom();
367
452
  this.draw(false);
368
- }
453
+ };
369
454
 
370
455
  handleZoom = (transform?: Transform, eventPositions?: EventPosition[]) => {
371
456
  if (this.options.onZoomWithoutDefult) {
372
457
  let times;
373
458
  if (eventPositions) {
374
- times = sortBy(eventPositions, 'offsetX').map((pos: EventPosition) => this.xScales.invert(pos.offsetX));
459
+ times = sortBy(eventPositions, "offsetX").map((pos: EventPosition) =>
460
+ this.xScales.invert(pos.offsetX)
461
+ );
375
462
  }
376
463
  this.options.onZoomWithoutDefult(times);
377
464
  } else {
378
- const { ykey, yAxis, ykeyFormatter } = this.options
465
+ const { ykey, yAxis, ykeyFormatter } = this.options;
379
466
  let { series } = this.options;
380
467
  if (transform) {
381
468
  this.transform = transform;
@@ -410,7 +497,7 @@ export default class TsGraph {
410
497
  this.options.onZoom(this.getZoomedSeries);
411
498
  }
412
499
  this.draw(false);
413
- }
500
+ };
414
501
 
415
502
  handleLegendItemClick = (serieName: string) => {
416
503
  const { notDisplayedSeries } = this.options;
@@ -423,24 +510,24 @@ export default class TsGraph {
423
510
  });
424
511
  }
425
512
  this.draw(false);
426
- }
513
+ };
427
514
 
428
515
  retinaScaled(canvas: HTMLCanvasElement, name: string) {
429
516
  const { chart, ratio } = this.options;
430
- const ctx = canvas.getContext('2d')!;
431
- const width = name === 'front' ? chart.containerWidth : chart.width;
432
- const height = name === 'front' ? chart.containerHeight : chart.height;
433
- const left = name === 'front' ? '0px' : `${chart.marginLeft}px`;
434
- const top = name === 'front' ? '0px' : `${chart.marginTop}px`;
517
+ const ctx = canvas.getContext("2d")!;
518
+ const width = name === "front" ? chart.containerWidth : chart.width;
519
+ const height = name === "front" ? chart.containerHeight : chart.height;
520
+ const left = name === "front" ? "0px" : `${chart.marginLeft}px`;
521
+ const top = name === "front" ? "0px" : `${chart.marginTop}px`;
435
522
 
436
523
  canvas.width = width * ratio;
437
524
  canvas.height = height * ratio;
438
525
  canvas.style.width = `${width}px`;
439
526
  canvas.style.height = `${height}px`;
440
- canvas.style.position = 'absolute';
527
+ canvas.style.position = "absolute";
441
528
  canvas.style.left = left;
442
529
  canvas.style.top = top;
443
- if (name === 'front') {
530
+ if (name === "front") {
444
531
  ctx.translate(chart.marginLeft * ratio, chart.marginTop * ratio);
445
532
  }
446
533
  ctx.scale(ratio, ratio);
@@ -448,44 +535,54 @@ export default class TsGraph {
448
535
 
449
536
  createContainer() {
450
537
  const { chart } = this.options;
451
- const container = document.createElement('div');
538
+ const container = document.createElement("div");
452
539
 
453
- container.style.position = 'relative';
540
+ container.style.position = "relative";
454
541
  container.style.width = `${chart.containerWidth}px`;
455
542
  container.style.height = `${chart.containerHeight}px`;
456
- container.style.overflow = 'hidden';
457
- container.className = 'd3-graph-container';
543
+ container.style.overflow = "hidden";
544
+ container.className = "d3-graph-container";
458
545
  chart.renderTo.appendChild(container);
459
546
  this.container = container;
460
547
  }
461
548
 
462
549
  createCanvas() {
463
- const { chart: { id } } = this.options;
550
+ const {
551
+ chart: { id },
552
+ } = this.options;
464
553
 
465
554
  function create(this: TsGraphType, name: string) {
466
- const canvas = document.createElement('canvas');
467
- const context = canvas.getContext('2d');
555
+ const canvas = document.createElement("canvas");
556
+ const context = canvas.getContext("2d");
468
557
 
469
- canvas.setAttribute('id', `${id}-${name}Canvas`);
558
+ canvas.setAttribute("id", `${id}-${name}Canvas`);
470
559
  this.container.appendChild(canvas);
471
560
  this[`${name}Canvas`] = canvas;
472
561
  this[`${name}Context`] = context;
473
562
  this.retinaScaled(canvas, name);
474
563
  }
475
- create.call(this, 'back');
476
- create.call(this, 'front');
477
- create.call(this, 'event');
564
+ create.call(this, "back");
565
+ create.call(this, "front");
566
+ create.call(this, "event");
478
567
  }
479
568
 
480
569
  initSeries() {
481
- const { fillNull, series, xkey, ykey, ykeyFormatter, oykey, yAxis, stack } = this.options;
570
+ const {
571
+ fillNull,
572
+ series,
573
+ xkey,
574
+ ykey,
575
+ ykey2,
576
+ ykeyFormatter,
577
+ oykey,
578
+ yAxis,
579
+ stack,
580
+ } = this.options;
482
581
  let xmin = -Infinity;
483
582
  let xmax = Infinity;
484
583
  let ymin = yAxis.min;
485
584
  let ymax = yAxis.max;
486
585
 
487
-
488
-
489
586
  if (Array.isArray(series)) {
490
587
  const newSeries: Serie[] = [];
491
588
  series.forEach((serie, idx) => {
@@ -494,13 +591,19 @@ export default class TsGraph {
494
591
  let flag = false; // 起始标记,后面有连续空值即丢掉
495
592
  let dataIdx;
496
593
  for (dataIdx = 0; dataIdx < data.length; dataIdx++) {
497
- const ykeyVal = data[dataIdx][oykey] ? data[dataIdx][oykey]: getYkeyValue(data[dataIdx][ykey], ykeyFormatter);
594
+ const ykeyVal = data[dataIdx][oykey]
595
+ ? data[dataIdx][oykey]
596
+ : getYkeyValue(data[dataIdx][ykey], ykeyFormatter);
498
597
  const item = {
499
598
  [xkey]: data[dataIdx][xkey],
500
599
  [ykey]: ykeyVal,
501
600
  [oykey]: ykeyVal,
502
601
  };
503
602
 
603
+ if (ykey2 && ykey2 in data[dataIdx]) {
604
+ item[ykey2] = getYkeyValue(data[dataIdx][ykey2], ykeyFormatter);
605
+ }
606
+
504
607
  if (stack.enabled) {
505
608
  if (item[oykey] === undefined) {
506
609
  item[oykey] = getYkeyValue(item[ykey], ykeyFormatter);
@@ -508,7 +611,9 @@ export default class TsGraph {
508
611
  let preIdx = idx;
509
612
  if (preIdx > 0) {
510
613
  while (preIdx > 0) {
511
- const preData = Array.isArray(series[preIdx - 1].data) ? series[preIdx - 1].data : [];
614
+ const preData = Array.isArray(series[preIdx - 1].data)
615
+ ? series[preIdx - 1].data
616
+ : [];
512
617
  const preItem = find(preData, (pItem: SerieDataItem) => {
513
618
  return pItem[xkey] === item[xkey];
514
619
  });
@@ -530,18 +635,19 @@ export default class TsGraph {
530
635
  }
531
636
 
532
637
  data[dataIdx] = item;
533
-
638
+
534
639
  const x = item[xkey];
535
640
  const y = item[ykey];
536
-
641
+
537
642
  // filter is invalid points
538
643
  if (fillNull === undefined) {
539
644
  if (
540
- !isNaN(y) && (
541
- dataIdx === 0
542
- || dataIdx === data.length - 1
543
- || (dataIdx > 0 && dataIdx < data.length -1 && typeof y === 'number')
544
- )
645
+ !isNaN(y) &&
646
+ (dataIdx === 0 ||
647
+ dataIdx === data.length - 1 ||
648
+ (dataIdx > 0 &&
649
+ dataIdx < data.length - 1 &&
650
+ typeof y === "number"))
545
651
  ) {
546
652
  newData.push(item);
547
653
  flag = true;
@@ -560,14 +666,14 @@ export default class TsGraph {
560
666
  if (xmax > x) {
561
667
  xmax = x;
562
668
  }
563
- if (typeof y === 'number' && !isNaN(y)) {
564
- if (typeof ymin !== 'number' || y < ymin) {
669
+ if (typeof y === "number" && !isNaN(y)) {
670
+ if (typeof ymin !== "number" || y < ymin) {
565
671
  ymin = y;
566
672
  }
567
- if (typeof ymax !== 'number' || y > ymax) {
673
+ if (typeof ymax !== "number" || y > ymax) {
568
674
  ymax = y;
569
675
  }
570
- } else if (typeof fillNull === 'number') {
676
+ } else if (typeof fillNull === "number") {
571
677
  if (fillNull < ymin) {
572
678
  ymin = fillNull;
573
679
  }
@@ -576,7 +682,7 @@ export default class TsGraph {
576
682
  }
577
683
  }
578
684
  }
579
-
685
+
580
686
  newSeries.push({
581
687
  ...serie,
582
688
  data: newData,
@@ -601,15 +707,30 @@ export default class TsGraph {
601
707
  }
602
708
 
603
709
  initTooltip() {
604
- this.tooltip = new Tooltip(this.options, this.frontContext, this.container, this.eventCanvas);
710
+ this.tooltip = new Tooltip(
711
+ this.options,
712
+ this.frontContext,
713
+ this.container,
714
+ this.eventCanvas
715
+ );
605
716
  }
606
717
 
607
718
  initZoom() {
608
- this.zoom = new Zoom(this.options, this.handleZoom, this.container, this.eventCanvas);
719
+ this.zoom = new Zoom(
720
+ this.options,
721
+ this.handleZoom,
722
+ this.container,
723
+ this.eventCanvas
724
+ );
609
725
  }
610
726
 
611
727
  initLegend() {
612
- this.legend = new Legend(this.options, this.handleLegendItemClick, this.container, this.eventCanvas);
728
+ this.legend = new Legend(
729
+ this.options,
730
+ this.handleLegendItemClick,
731
+ this.container,
732
+ this.eventCanvas
733
+ );
613
734
  }
614
735
 
615
736
  initScales() {
@@ -633,14 +754,17 @@ export default class TsGraph {
633
754
 
634
755
  offEvents() {
635
756
  const { cascade, cascadeScope } = this.options.tooltip;
636
- const plotmoveType = cascadeScope ? `plotmove:${cascadeScope}` : 'plotmove';
637
- const plotleaveType = cascadeScope ? `plotleave:${cascadeScope}` : 'plotleave';
638
-
639
- d3.select(this.eventCanvas).on('mousemove', null)
640
- .on('mouseleave', null)
641
- .on('mousedown', null)
642
- .on('mouseup', null)
643
- .on('touchmove', null);
757
+ const plotmoveType = cascadeScope ? `plotmove:${cascadeScope}` : "plotmove";
758
+ const plotleaveType = cascadeScope
759
+ ? `plotleave:${cascadeScope}`
760
+ : "plotleave";
761
+
762
+ d3.select(this.eventCanvas)
763
+ .on("mousemove", null)
764
+ .on("mouseleave", null)
765
+ .on("mousedown", null)
766
+ .on("mouseup", null)
767
+ .on("touchmove", null);
644
768
  removeListener(this.options.chart.renderTo, this.handleResize);
645
769
 
646
770
  if (cascade) {