@fc-plot/ts-graph 0.23.2 → 0.24.0
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/examples/index.js +11 -8
- package/package.json +1 -1
- package/src/index.ts +119 -24
- package/src/interface.ts +4 -0
- package/src/line.ts +13 -8
- package/src/tooltip.ts +32 -11
- package/src/utils.ts +4 -1
- package/src/xAxis.ts +11 -3
- package/src/yAxis.ts +1 -37
- package/src/yAxis2.ts +154 -0
- package/dist/BundleReport.html +0 -53
- package/dist/index.css +0 -104
- package/dist/index.css.map +0 -1
- package/dist/index.js +0 -2
- package/dist/index.js.map +0 -1
package/examples/index.js
CHANGED
|
@@ -39,13 +39,12 @@ newSeries.push({
|
|
|
39
39
|
});
|
|
40
40
|
|
|
41
41
|
newSeries.push(origin);
|
|
42
|
-
console.log(newSeries);
|
|
43
42
|
|
|
44
43
|
function random(m, n) {
|
|
45
44
|
return Math.floor(Math.random() * (n - m + 1));
|
|
46
45
|
}
|
|
47
46
|
|
|
48
|
-
function generateSeries(idx, seriesCount =
|
|
47
|
+
function generateSeries(idx, seriesCount = 2) {
|
|
49
48
|
const series = [];
|
|
50
49
|
|
|
51
50
|
for (let n = 1; n <= seriesCount; n++) {
|
|
@@ -56,7 +55,8 @@ function generateSeries(idx, seriesCount = 3) {
|
|
|
56
55
|
seriesData.push({
|
|
57
56
|
timestamp:
|
|
58
57
|
1609430399 + m * (m < 100 ? (idx === 0 ? 1000 : 1001) : 1000),
|
|
59
|
-
value:
|
|
58
|
+
value: random(0, n === 1 ? 100 : 1000000),
|
|
59
|
+
// value: m < 100 ? random(0, 100000000) : random(0, 1000000000),
|
|
60
60
|
});
|
|
61
61
|
}
|
|
62
62
|
|
|
@@ -65,20 +65,19 @@ function generateSeries(idx, seriesCount = 3) {
|
|
|
65
65
|
data: seriesData,
|
|
66
66
|
});
|
|
67
67
|
}
|
|
68
|
+
console.log("series", series);
|
|
68
69
|
return series;
|
|
69
70
|
}
|
|
70
71
|
|
|
71
|
-
const graphsCount =
|
|
72
|
+
const graphsCount = 1;
|
|
72
73
|
const charts = [];
|
|
73
74
|
|
|
74
|
-
console.log(222, generateSeries(0));
|
|
75
|
-
|
|
76
75
|
for (let i = 0; i < graphsCount; i++) {
|
|
77
76
|
const id = `c${i}`;
|
|
78
77
|
const renderTo = document.createElement("div");
|
|
79
78
|
renderTo.id = id;
|
|
80
|
-
renderTo.style.width =
|
|
81
|
-
renderTo.style.height =
|
|
79
|
+
renderTo.style.width = `${(i + 1) * 1000}px`;
|
|
80
|
+
renderTo.style.height = `${(i + 1) * 400}px`;
|
|
82
81
|
renderTo.style.margin = "20px";
|
|
83
82
|
renderTo.style.border = "1px solid #ccc";
|
|
84
83
|
document.body.appendChild(renderTo);
|
|
@@ -100,6 +99,10 @@ for (let i = 0; i < graphsCount; i++) {
|
|
|
100
99
|
line: {
|
|
101
100
|
width: 1,
|
|
102
101
|
},
|
|
102
|
+
yAxis2: {
|
|
103
|
+
visible: true,
|
|
104
|
+
matchName: "series_2",
|
|
105
|
+
},
|
|
103
106
|
// xAxis: {
|
|
104
107
|
// visible: false,
|
|
105
108
|
// },
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -14,6 +14,7 @@ import { addListener, removeListener } from "resize-detector";
|
|
|
14
14
|
import EventEmitter from "events";
|
|
15
15
|
import XAxis from "./xAxis";
|
|
16
16
|
import YAxis from "./yAxis";
|
|
17
|
+
import YAxis2 from "./yAxis2";
|
|
17
18
|
import Tooltip from "./tooltip";
|
|
18
19
|
import Line from "./line";
|
|
19
20
|
import Bar from "./bar";
|
|
@@ -49,7 +50,9 @@ export default class TsGraph {
|
|
|
49
50
|
xAxis!: XAxis;
|
|
50
51
|
xScales!: XScales;
|
|
51
52
|
yAxis!: YAxis;
|
|
53
|
+
yAxis2!: YAxis2;
|
|
52
54
|
yScales!: YScales;
|
|
55
|
+
y2Scales!: YScales;
|
|
53
56
|
line!: Line;
|
|
54
57
|
bar!: Bar;
|
|
55
58
|
legend!: Legend;
|
|
@@ -85,8 +88,8 @@ export default class TsGraph {
|
|
|
85
88
|
"#339966",
|
|
86
89
|
"#993333",
|
|
87
90
|
],
|
|
88
|
-
width: userOptions.chart.renderTo.
|
|
89
|
-
height: userOptions.chart.renderTo.
|
|
91
|
+
width: userOptions.chart.renderTo.clientWidth,
|
|
92
|
+
height: userOptions.chart.renderTo.clientHeight || 350,
|
|
90
93
|
marginTop: 10,
|
|
91
94
|
marginRight: 10,
|
|
92
95
|
marginBottom: 10,
|
|
@@ -123,6 +126,22 @@ export default class TsGraph {
|
|
|
123
126
|
fontSize: 11,
|
|
124
127
|
},
|
|
125
128
|
},
|
|
129
|
+
yAxis2: {
|
|
130
|
+
scale: {
|
|
131
|
+
type: "linear",
|
|
132
|
+
log: 10,
|
|
133
|
+
},
|
|
134
|
+
visible: false,
|
|
135
|
+
lineColor: "#ccc",
|
|
136
|
+
lineWidth: 1,
|
|
137
|
+
tickLength: 5,
|
|
138
|
+
tickpadding: 5,
|
|
139
|
+
tickColor: "#ccc",
|
|
140
|
+
labels: {
|
|
141
|
+
color: "#999",
|
|
142
|
+
fontSize: 11,
|
|
143
|
+
},
|
|
144
|
+
},
|
|
126
145
|
type: "line",
|
|
127
146
|
line: {
|
|
128
147
|
enable: true,
|
|
@@ -218,7 +237,7 @@ export default class TsGraph {
|
|
|
218
237
|
this.xAxis.draw(this.xScales);
|
|
219
238
|
}
|
|
220
239
|
if (this.options.type === "line") {
|
|
221
|
-
this.line.draw(this.xScales, this.yScales);
|
|
240
|
+
this.line.draw(this.xScales, this.yScales, this.y2Scales);
|
|
222
241
|
}
|
|
223
242
|
if (this.options.type === "bar") {
|
|
224
243
|
this.bar.draw(this.xScales, this.yScales, transform);
|
|
@@ -228,6 +247,9 @@ export default class TsGraph {
|
|
|
228
247
|
if (this.options.yAxis.visible) {
|
|
229
248
|
this.yAxis.draw(this.yScales);
|
|
230
249
|
}
|
|
250
|
+
if (this.options.yAxis2.visible && this.options.yAxis2.matchName) {
|
|
251
|
+
this.yAxis2.draw(this.y2Scales);
|
|
252
|
+
}
|
|
231
253
|
if (redrawLegend) {
|
|
232
254
|
this.legend.draw();
|
|
233
255
|
}
|
|
@@ -264,9 +286,24 @@ export default class TsGraph {
|
|
|
264
286
|
return [...this.options.series];
|
|
265
287
|
}
|
|
266
288
|
|
|
267
|
-
showTooltip = (
|
|
289
|
+
showTooltip = (
|
|
290
|
+
eventPosition: EventPosition,
|
|
291
|
+
forceTimestamp: number,
|
|
292
|
+
scaleX: number,
|
|
293
|
+
scaleY: number
|
|
294
|
+
) => {
|
|
268
295
|
if (!this.isMouserover) {
|
|
269
|
-
this.
|
|
296
|
+
const width = this.options.chart.width;
|
|
297
|
+
const height = this.options.chart.height;
|
|
298
|
+
const crosshairX = width * scaleX;
|
|
299
|
+
const crosshairY = height * scaleY;
|
|
300
|
+
this.tooltip.draw(
|
|
301
|
+
eventPosition,
|
|
302
|
+
this,
|
|
303
|
+
forceTimestamp,
|
|
304
|
+
crosshairX,
|
|
305
|
+
crosshairY
|
|
306
|
+
);
|
|
270
307
|
}
|
|
271
308
|
};
|
|
272
309
|
|
|
@@ -312,6 +349,7 @@ export default class TsGraph {
|
|
|
312
349
|
d3.select(this.eventCanvas)
|
|
313
350
|
.on("mousemove", function mousemove(this: HTMLCanvasElement) {
|
|
314
351
|
_this.isMouserover = true;
|
|
352
|
+
|
|
315
353
|
handleMouseover(d3.event);
|
|
316
354
|
if (cascade) {
|
|
317
355
|
const { nearestPoints } = getNearestPointsByEvent(
|
|
@@ -325,7 +363,17 @@ export default class TsGraph {
|
|
|
325
363
|
const firstNearestPoint = nearestPoints[0];
|
|
326
364
|
timestamp = firstNearestPoint.timestamp;
|
|
327
365
|
}
|
|
328
|
-
|
|
366
|
+
const x = d3.event.offsetX || d3.event.layerX;
|
|
367
|
+
const y = d3.event.offsetY || d3.event.layerY;
|
|
368
|
+
const width = _this.options.chart.width;
|
|
369
|
+
const height = _this.options.chart.height;
|
|
370
|
+
eventEmitter.emit(
|
|
371
|
+
plotmoveType,
|
|
372
|
+
d3.event,
|
|
373
|
+
timestamp,
|
|
374
|
+
x / width,
|
|
375
|
+
y / height
|
|
376
|
+
);
|
|
329
377
|
}
|
|
330
378
|
})
|
|
331
379
|
.on("mouseleave", function mouseleave(this: HTMLCanvasElement) {
|
|
@@ -494,7 +542,7 @@ export default class TsGraph {
|
|
|
494
542
|
}
|
|
495
543
|
this.options.onZoomWithoutDefult(times);
|
|
496
544
|
} else {
|
|
497
|
-
const { ykey, ykey2, yAxis, ykeyFormatter } = this.options;
|
|
545
|
+
const { ykey, ykey2, yAxis, yAxis2, ykeyFormatter } = this.options;
|
|
498
546
|
let { series } = this.options;
|
|
499
547
|
if (transform) {
|
|
500
548
|
this.transform = transform;
|
|
@@ -508,6 +556,8 @@ export default class TsGraph {
|
|
|
508
556
|
if (Array.isArray(series)) {
|
|
509
557
|
let ymin = yAxis.min || -Infinity;
|
|
510
558
|
let ymax = yAxis.max || Infinity;
|
|
559
|
+
let y2min = yAxis2.min || -Infinity;
|
|
560
|
+
let y2max = yAxis2.max || Infinity;
|
|
511
561
|
for (const serie of series) {
|
|
512
562
|
const data = Array.isArray(serie.data) ? serie.data : [];
|
|
513
563
|
let dataIdx;
|
|
@@ -517,11 +567,24 @@ export default class TsGraph {
|
|
|
517
567
|
|
|
518
568
|
if (y === null) continue;
|
|
519
569
|
// get axis domain
|
|
520
|
-
if (
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
570
|
+
if (
|
|
571
|
+
yAxis2.visible &&
|
|
572
|
+
yAxis2.matchName &&
|
|
573
|
+
yAxis2.matchName === serie.name
|
|
574
|
+
) {
|
|
575
|
+
if (y2min < y) {
|
|
576
|
+
y2min = y;
|
|
577
|
+
}
|
|
578
|
+
if (y2max > y) {
|
|
579
|
+
y2max = y;
|
|
580
|
+
}
|
|
581
|
+
} else {
|
|
582
|
+
if (ymin < y) {
|
|
583
|
+
ymin = y;
|
|
584
|
+
}
|
|
585
|
+
if (ymax > y) {
|
|
586
|
+
ymax = y;
|
|
587
|
+
}
|
|
525
588
|
}
|
|
526
589
|
if (ykey2) {
|
|
527
590
|
const y2 = getYkeyValue(item[ykey2], ykeyFormatter);
|
|
@@ -538,6 +601,9 @@ export default class TsGraph {
|
|
|
538
601
|
// 如果缩放至没有数据点(无法计算出 ymin 和 ymax),则不更新 domain
|
|
539
602
|
if (ymin !== -Infinity && ymax !== Infinity) {
|
|
540
603
|
this.yAxis.setDomain(this.yScales, { ymin, ymax });
|
|
604
|
+
if (yAxis2.visible && yAxis2.matchName) {
|
|
605
|
+
this.yAxis2.setDomain(this.y2Scales, { y2min, y2max });
|
|
606
|
+
}
|
|
541
607
|
}
|
|
542
608
|
}
|
|
543
609
|
this.options.onZoom(this.getZoomedSeries);
|
|
@@ -623,6 +689,7 @@ export default class TsGraph {
|
|
|
623
689
|
oykey,
|
|
624
690
|
xAxis,
|
|
625
691
|
yAxis,
|
|
692
|
+
yAxis2,
|
|
626
693
|
stack,
|
|
627
694
|
notDisplayedSeries,
|
|
628
695
|
} = this.options;
|
|
@@ -630,6 +697,8 @@ export default class TsGraph {
|
|
|
630
697
|
let xmax = xAxis.max || Infinity;
|
|
631
698
|
let ymin = yAxis.min;
|
|
632
699
|
let ymax = yAxis.max;
|
|
700
|
+
let y2min = yAxis2.min;
|
|
701
|
+
let y2max = yAxis2.max;
|
|
633
702
|
|
|
634
703
|
if (Array.isArray(series)) {
|
|
635
704
|
const newSeries: Serie[] = [];
|
|
@@ -719,17 +788,30 @@ export default class TsGraph {
|
|
|
719
788
|
xmax = x;
|
|
720
789
|
}
|
|
721
790
|
if (typeof y === "number" && !isNaN(y)) {
|
|
722
|
-
if (
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
791
|
+
if (
|
|
792
|
+
yAxis2.visible &&
|
|
793
|
+
yAxis2.matchName &&
|
|
794
|
+
yAxis2.matchName === serie.name
|
|
795
|
+
) {
|
|
796
|
+
if (typeof y2min !== "number" || y < y2min) {
|
|
797
|
+
y2min = y;
|
|
798
|
+
}
|
|
799
|
+
if (typeof y2max !== "number" || y > y2max) {
|
|
800
|
+
y2max = y;
|
|
801
|
+
}
|
|
802
|
+
} else {
|
|
803
|
+
if (typeof ymin !== "number" || y < ymin) {
|
|
804
|
+
ymin = y;
|
|
805
|
+
}
|
|
806
|
+
if (typeof y2 === "number" && y2 < ymin) {
|
|
807
|
+
ymin = y2;
|
|
808
|
+
}
|
|
809
|
+
if (typeof ymax !== "number" || y > ymax) {
|
|
810
|
+
ymax = y;
|
|
811
|
+
}
|
|
812
|
+
if (typeof y2 === "number" && y2 > ymax) {
|
|
813
|
+
ymax = y2;
|
|
814
|
+
}
|
|
733
815
|
}
|
|
734
816
|
} else if (typeof fillNull === "number") {
|
|
735
817
|
if (fillNull < ymin) {
|
|
@@ -769,6 +851,8 @@ export default class TsGraph {
|
|
|
769
851
|
this.options.xmax = xmax;
|
|
770
852
|
this.options.ymin = ymin;
|
|
771
853
|
this.options.ymax = ymax;
|
|
854
|
+
this.options.y2min = y2min;
|
|
855
|
+
this.options.y2max = y2max;
|
|
772
856
|
}
|
|
773
857
|
}
|
|
774
858
|
|
|
@@ -812,7 +896,18 @@ export default class TsGraph {
|
|
|
812
896
|
this.yAxis = yAxis;
|
|
813
897
|
this.yScales = yAxis.init();
|
|
814
898
|
|
|
815
|
-
|
|
899
|
+
if (this.options.yAxis2.visible && this.options.yAxis2.matchName) {
|
|
900
|
+
const yAxis2 = new YAxis2(this.options, this.backContext);
|
|
901
|
+
this.yAxis2 = yAxis2;
|
|
902
|
+
this.y2Scales = yAxis2.init();
|
|
903
|
+
}
|
|
904
|
+
|
|
905
|
+
const xAxis = new XAxis(
|
|
906
|
+
this.options,
|
|
907
|
+
this.backContext,
|
|
908
|
+
this.yAxis,
|
|
909
|
+
this.yAxis2
|
|
910
|
+
);
|
|
816
911
|
this.xAxis = xAxis;
|
|
817
912
|
let xScales = xAxis.init();
|
|
818
913
|
if (this.transform) {
|
package/src/interface.ts
CHANGED
|
@@ -82,6 +82,7 @@ export type YAxis = {
|
|
|
82
82
|
plotLines: PlotLine[];
|
|
83
83
|
plotLinesFixed?: boolean;
|
|
84
84
|
tickValueFormatter?: (value: number) => string;
|
|
85
|
+
matchName?: string; // 用于匹配 y 轴,如果不填则默认匹配第一个 y 轴
|
|
85
86
|
};
|
|
86
87
|
|
|
87
88
|
export type SerieDataItemMarker = {
|
|
@@ -178,6 +179,7 @@ export interface Options extends BaseOptions {
|
|
|
178
179
|
chart: Chart;
|
|
179
180
|
xAxis: XAxis;
|
|
180
181
|
yAxis: YAxis;
|
|
182
|
+
yAxis2: YAxis;
|
|
181
183
|
tooltip: Tooltip;
|
|
182
184
|
type: "line" | "bar";
|
|
183
185
|
line: {
|
|
@@ -204,6 +206,8 @@ export interface Options extends BaseOptions {
|
|
|
204
206
|
xmax: number;
|
|
205
207
|
ymin: number;
|
|
206
208
|
ymax: number;
|
|
209
|
+
y2min: number;
|
|
210
|
+
y2max: number;
|
|
207
211
|
shapes: any[];
|
|
208
212
|
onClick: (
|
|
209
213
|
d3Event: any,
|
package/src/line.ts
CHANGED
|
@@ -11,11 +11,12 @@ export default class Line {
|
|
|
11
11
|
this.ctx = ctx;
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
draw(xScales: XScales, yScales: YScales) {
|
|
14
|
+
draw(xScales: XScales, yScales: YScales, y2Scales: YScales) {
|
|
15
15
|
const {
|
|
16
16
|
series,
|
|
17
17
|
chart: { colors, height },
|
|
18
18
|
xAxis,
|
|
19
|
+
yAxis2,
|
|
19
20
|
xkey,
|
|
20
21
|
ykey,
|
|
21
22
|
ykey2,
|
|
@@ -37,12 +38,16 @@ export default class Line {
|
|
|
37
38
|
const x = xScales(new Date(xVal));
|
|
38
39
|
return x;
|
|
39
40
|
};
|
|
40
|
-
const yAccessor = (d: SerieDataItem, ykey: any) => {
|
|
41
|
+
const yAccessor = (d: SerieDataItem, ykey: any, serieName: string) => {
|
|
41
42
|
const val = d[ykey];
|
|
43
|
+
const yScalesFunc =
|
|
44
|
+
yAxis2.visible && yAxis2.matchName && serieName === yAxis2.matchName
|
|
45
|
+
? y2Scales
|
|
46
|
+
: yScales;
|
|
42
47
|
if (typeof val === "number" && !isNaN(val)) {
|
|
43
|
-
return
|
|
48
|
+
return yScalesFunc(val);
|
|
44
49
|
} else if (typeof fillNull === "number") {
|
|
45
|
-
return
|
|
50
|
+
return yScalesFunc(fillNull);
|
|
46
51
|
}
|
|
47
52
|
return undefined;
|
|
48
53
|
};
|
|
@@ -73,7 +78,7 @@ export default class Line {
|
|
|
73
78
|
.x(xAccessor)
|
|
74
79
|
.y0((d: SerieDataItem) => {
|
|
75
80
|
if (ykey2 && ykey2 in d) {
|
|
76
|
-
return yAccessor(d, ykey);
|
|
81
|
+
return yAccessor(d, ykey, serie.name);
|
|
77
82
|
}
|
|
78
83
|
if (xAxis.visible) {
|
|
79
84
|
return height - xAxis.tickpadding - xAxis.labels.fontSize - 5;
|
|
@@ -82,9 +87,9 @@ export default class Line {
|
|
|
82
87
|
})
|
|
83
88
|
.y1((d: SerieDataItem) => {
|
|
84
89
|
if (ykey2 && ykey2 in d) {
|
|
85
|
-
return yAccessor(d, ykey2);
|
|
90
|
+
return yAccessor(d, ykey2, serie.name);
|
|
86
91
|
}
|
|
87
|
-
return yAccessor(d, ykey);
|
|
92
|
+
return yAccessor(d, ykey, serie.name);
|
|
88
93
|
})
|
|
89
94
|
.defined(definedAccessor)
|
|
90
95
|
.context(ctx);
|
|
@@ -110,7 +115,7 @@ export default class Line {
|
|
|
110
115
|
.line()
|
|
111
116
|
.x(xAccessor)
|
|
112
117
|
.y((d: SerieDataItem) => {
|
|
113
|
-
return yAccessor(d, ykey);
|
|
118
|
+
return yAccessor(d, ykey, serie.name);
|
|
114
119
|
})
|
|
115
120
|
.defined(definedAccessor)
|
|
116
121
|
.context(ctx);
|
package/src/tooltip.ts
CHANGED
|
@@ -68,6 +68,7 @@ export default class Tooltip {
|
|
|
68
68
|
eventPosition: EventPosition,
|
|
69
69
|
xScales: XScales,
|
|
70
70
|
yScales: YScales,
|
|
71
|
+
y2Scales: YScales,
|
|
71
72
|
cbk: (nearestPoints: Point[], nearestPoint: Point) => void,
|
|
72
73
|
forceTimestamp?: number
|
|
73
74
|
) {
|
|
@@ -81,6 +82,7 @@ export default class Tooltip {
|
|
|
81
82
|
oykey,
|
|
82
83
|
timestamp,
|
|
83
84
|
fillNull,
|
|
85
|
+
yAxis2,
|
|
84
86
|
} = this.options;
|
|
85
87
|
const offsetX = eventPosition.offsetX || eventPosition.layerX;
|
|
86
88
|
const offsetY = eventPosition.offsetY || eventPosition.layerY;
|
|
@@ -106,10 +108,14 @@ export default class Tooltip {
|
|
|
106
108
|
}
|
|
107
109
|
|
|
108
110
|
nearestPoints = tempNearestPoints.map((item: any) => {
|
|
111
|
+
const yScalesFunc =
|
|
112
|
+
yAxis2.visible && yAxis2.matchName && item.name === yAxis2.matchName
|
|
113
|
+
? y2Scales
|
|
114
|
+
: yScales;
|
|
109
115
|
return {
|
|
110
116
|
...item,
|
|
111
117
|
x: xScales(item.timestamp),
|
|
112
|
-
y:
|
|
118
|
+
y: yScalesFunc(item.value),
|
|
113
119
|
color: item.color || getColor(colors, item.serieIndex),
|
|
114
120
|
};
|
|
115
121
|
});
|
|
@@ -159,20 +165,23 @@ export default class Tooltip {
|
|
|
159
165
|
draw(
|
|
160
166
|
eventPosition: EventPosition,
|
|
161
167
|
instance: TsGraph,
|
|
162
|
-
forceTimestamp?: number
|
|
168
|
+
forceTimestamp?: number,
|
|
169
|
+
crosshairX?: number,
|
|
170
|
+
crosshairY?: number
|
|
163
171
|
) {
|
|
164
|
-
const { xScales, yScales, yAxis, options } = instance;
|
|
172
|
+
const { xScales, yScales, y2Scales, yAxis, options } = instance;
|
|
165
173
|
const cascadeMode = options?.tooltip?.cascadeMode;
|
|
166
174
|
this.isMouserover = true;
|
|
167
175
|
this.getNearestPoints(
|
|
168
176
|
eventPosition,
|
|
169
177
|
xScales,
|
|
170
178
|
yScales,
|
|
179
|
+
y2Scales,
|
|
171
180
|
(nearestPoints, nearestPoint) => {
|
|
172
181
|
this.clear();
|
|
182
|
+
this.drawCrosshair(eventPosition, crosshairX, crosshairY);
|
|
173
183
|
if (nearestPoints.length) {
|
|
174
184
|
if (nearestPoints[0].x < yAxis.tickMaxWidth) return; // 判断是否在 y 轴上
|
|
175
|
-
this.drawCrosshair(eventPosition);
|
|
176
185
|
// 共享 tooltip 的情况下才会存在 forceTimestamp 值
|
|
177
186
|
// 当 forceTimestamp 有值时,模式必须是 sharedTooltip 才会绘制 symbol 和 modal
|
|
178
187
|
if (
|
|
@@ -180,7 +189,13 @@ export default class Tooltip {
|
|
|
180
189
|
(forceTimestamp !== undefined && cascadeMode === "sharedTooltip")
|
|
181
190
|
) {
|
|
182
191
|
this.drawSymbol(nearestPoints);
|
|
183
|
-
this.drawModal(
|
|
192
|
+
this.drawModal(
|
|
193
|
+
nearestPoints,
|
|
194
|
+
nearestPoint,
|
|
195
|
+
eventPosition,
|
|
196
|
+
crosshairX,
|
|
197
|
+
crosshairY
|
|
198
|
+
);
|
|
184
199
|
}
|
|
185
200
|
}
|
|
186
201
|
},
|
|
@@ -191,7 +206,9 @@ export default class Tooltip {
|
|
|
191
206
|
drawModal(
|
|
192
207
|
nearestPoints: Point[],
|
|
193
208
|
nearestPoint: Point,
|
|
194
|
-
eventPosition: EventPosition
|
|
209
|
+
eventPosition: EventPosition,
|
|
210
|
+
crosshairX?: number,
|
|
211
|
+
crosshairY?: number
|
|
195
212
|
) {
|
|
196
213
|
const {
|
|
197
214
|
chart: { id, renderTo },
|
|
@@ -342,8 +359,8 @@ export default class Tooltip {
|
|
|
342
359
|
const tooltipWidth = wrapEle.offsetWidth;
|
|
343
360
|
const tooltipHeight = wrapEle.offsetHeight;
|
|
344
361
|
const containerRect = this.container.getBoundingClientRect();
|
|
345
|
-
const clientX = eventPosition.layerX + containerRect.left;
|
|
346
|
-
const clientY = eventPosition.layerY + containerRect.top;
|
|
362
|
+
const clientX = (crosshairX || eventPosition.layerX) + containerRect.left;
|
|
363
|
+
const clientY = (crosshairY || eventPosition.layerY) + containerRect.top;
|
|
347
364
|
|
|
348
365
|
tooltipNode.style.left = `${clientX - tooltipWidth - 20}px`;
|
|
349
366
|
tooltipNode.style.top = `${clientY + 20}px`;
|
|
@@ -383,11 +400,15 @@ export default class Tooltip {
|
|
|
383
400
|
});
|
|
384
401
|
}
|
|
385
402
|
|
|
386
|
-
drawCrosshair(
|
|
403
|
+
drawCrosshair(
|
|
404
|
+
eventPosition: EventPosition,
|
|
405
|
+
crosshairX?: number,
|
|
406
|
+
crosshairY?: number
|
|
407
|
+
) {
|
|
387
408
|
const { ctx, options } = this;
|
|
388
409
|
const { chart, xAxis } = options;
|
|
389
|
-
const x = eventPosition.offsetX || eventPosition.layerX;
|
|
390
|
-
const y = eventPosition.offsetY || eventPosition.layerY;
|
|
410
|
+
const x = crosshairX || eventPosition.offsetX || eventPosition.layerX;
|
|
411
|
+
const y = crosshairY || eventPosition.offsetY || eventPosition.layerY;
|
|
391
412
|
const tickBottom =
|
|
392
413
|
chart.height -
|
|
393
414
|
xAxis.tickpadding -
|
package/src/utils.ts
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
import * as d3 from "d3";
|
|
2
|
-
import { max, pickBy } from "lodash";
|
|
2
|
+
import { max, pickBy, map, find } from "lodash";
|
|
3
3
|
import {
|
|
4
4
|
Timestamp,
|
|
5
5
|
Options,
|
|
6
6
|
XScales,
|
|
7
7
|
YScales,
|
|
8
8
|
NearestPoint,
|
|
9
|
+
Serie,
|
|
10
|
+
SerieDataItem,
|
|
9
11
|
} from "./interface";
|
|
12
|
+
|
|
10
13
|
import getNearestPoints from "./getNearestPoints";
|
|
11
14
|
|
|
12
15
|
type Point = {
|
package/src/xAxis.ts
CHANGED
|
@@ -2,19 +2,23 @@ import * as d3 from "d3";
|
|
|
2
2
|
import { getMsTs } from "./utils";
|
|
3
3
|
import { Options, XScales } from "./interface";
|
|
4
4
|
import YAxis from "./yAxis";
|
|
5
|
+
import Y2Axis from "./yAxis2";
|
|
5
6
|
|
|
6
7
|
export default class XAxis {
|
|
7
8
|
options: Options;
|
|
8
9
|
ctx: CanvasRenderingContext2D;
|
|
9
10
|
yAxis: YAxis;
|
|
11
|
+
y2Axis: Y2Axis;
|
|
10
12
|
constructor(
|
|
11
13
|
userOptions: Options,
|
|
12
14
|
ctx: CanvasRenderingContext2D,
|
|
13
|
-
yAxis: YAxis
|
|
15
|
+
yAxis: YAxis,
|
|
16
|
+
y2Axis: Y2Axis
|
|
14
17
|
) {
|
|
15
18
|
this.options = userOptions;
|
|
16
19
|
this.ctx = ctx;
|
|
17
20
|
this.yAxis = yAxis;
|
|
21
|
+
this.y2Axis = y2Axis;
|
|
18
22
|
}
|
|
19
23
|
|
|
20
24
|
init() {
|
|
@@ -25,9 +29,13 @@ export default class XAxis {
|
|
|
25
29
|
xmax,
|
|
26
30
|
xAxis,
|
|
27
31
|
} = this.options;
|
|
32
|
+
const y2AxisTickMaxWidth = this.y2Axis?.tickMaxWidth || 0;
|
|
28
33
|
const xScales = d3
|
|
29
34
|
.scaleTime()
|
|
30
|
-
.range([
|
|
35
|
+
.range([
|
|
36
|
+
xAxis.visible ? this.yAxis.tickMaxWidth : 0,
|
|
37
|
+
width - y2AxisTickMaxWidth,
|
|
38
|
+
]);
|
|
31
39
|
|
|
32
40
|
xScales.domain([
|
|
33
41
|
getMsTs(xmin, timestamp) - (xmin === xmax ? 1000 : 0),
|
|
@@ -62,7 +70,7 @@ export default class XAxis {
|
|
|
62
70
|
|
|
63
71
|
// draw line
|
|
64
72
|
ctx.beginPath();
|
|
65
|
-
ctx.moveTo(
|
|
73
|
+
ctx.moveTo(this.yAxis.tickMaxWidth, tickBottom - xAxis.tickLength);
|
|
66
74
|
ctx.lineTo(chart.width, tickBottom - xAxis.tickLength);
|
|
67
75
|
ctx.lineWidth = 1;
|
|
68
76
|
ctx.strokeStyle = xAxis.lineColor;
|
package/src/yAxis.ts
CHANGED
|
@@ -3,10 +3,6 @@ import { map, floor } from "lodash";
|
|
|
3
3
|
import { Options, YScales } from "./interface";
|
|
4
4
|
import { shortUint, getMaxWidthByYAxisTicks } from "./utils";
|
|
5
5
|
|
|
6
|
-
interface RealData {
|
|
7
|
-
[index: string]: any;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
6
|
export default class YAxis {
|
|
11
7
|
options: Options;
|
|
12
8
|
ctx: CanvasRenderingContext2D;
|
|
@@ -40,38 +36,6 @@ export default class YAxis {
|
|
|
40
36
|
return yScales;
|
|
41
37
|
}
|
|
42
38
|
|
|
43
|
-
/**
|
|
44
|
-
* 返回真实的数据,其中包含 plotLines
|
|
45
|
-
* @param {Array} data [description]
|
|
46
|
-
* @return {Array} [description]
|
|
47
|
-
*/
|
|
48
|
-
getRealData(data: RealData) {
|
|
49
|
-
const {
|
|
50
|
-
yAxis: { plotLines },
|
|
51
|
-
ykey,
|
|
52
|
-
fillNull,
|
|
53
|
-
} = this.options;
|
|
54
|
-
|
|
55
|
-
if (Array.isArray(data)) {
|
|
56
|
-
if (Array.isArray(plotLines)) {
|
|
57
|
-
plotLines.forEach((plotLine) => {
|
|
58
|
-
if (typeof plotLine.value === "number") {
|
|
59
|
-
data.push({
|
|
60
|
-
[ykey]: plotLine.value,
|
|
61
|
-
});
|
|
62
|
-
}
|
|
63
|
-
});
|
|
64
|
-
}
|
|
65
|
-
if (typeof fillNull === "number") {
|
|
66
|
-
data.push({
|
|
67
|
-
[ykey]: fillNull,
|
|
68
|
-
});
|
|
69
|
-
}
|
|
70
|
-
return data;
|
|
71
|
-
}
|
|
72
|
-
return [];
|
|
73
|
-
}
|
|
74
|
-
|
|
75
39
|
getPlotLinesMaxAbs() {
|
|
76
40
|
const {
|
|
77
41
|
yAxis: { plotLines },
|
|
@@ -187,7 +151,7 @@ export default class YAxis {
|
|
|
187
151
|
ctx.beginPath();
|
|
188
152
|
this.ticks.forEach((d) => {
|
|
189
153
|
const yValue = yScales(d);
|
|
190
|
-
ctx.moveTo(
|
|
154
|
+
ctx.moveTo(this.tickMaxWidth, yValue);
|
|
191
155
|
ctx.lineTo(chart.width, yValue);
|
|
192
156
|
});
|
|
193
157
|
ctx.lineWidth = 1;
|