@tetacom/svg-charts 1.2.3 → 1.2.6
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/chart/chart/chart.component.d.ts +2 -1
- package/chart/chart-container/chart-container.component.d.ts +5 -7
- package/chart/chart-container/series/linear-series-base.d.ts +1 -1
- package/chart/chart-container/series/scatter-series/scatter-series.component.d.ts +0 -1
- package/chart/chart-container/x-axis/x-axis.component.d.ts +2 -4
- package/chart/core/axis/axis.d.ts +3 -0
- package/chart/model/i-scales-map.d.ts +5 -0
- package/chart/model/public-api.d.ts +1 -0
- package/chart/service/chart.service.d.ts +4 -0
- package/chart/service/scale.service.d.ts +2 -5
- package/esm2020/chart/chart/chart.component.mjs +14 -6
- package/esm2020/chart/chart-container/annotation/annotation.component.mjs +3 -3
- package/esm2020/chart/chart-container/chart-container.component.mjs +20 -29
- package/esm2020/chart/chart-container/gridlines/gridlines.component.mjs +7 -7
- package/esm2020/chart/chart-container/series/area-series/area-series.component.mjs +6 -9
- package/esm2020/chart/chart-container/series/bar/bar-series.component.mjs +5 -5
- package/esm2020/chart/chart-container/series/block-area-series/block-area-series.component.mjs +3 -3
- package/esm2020/chart/chart-container/series/block-series/block-series.component.mjs +3 -3
- package/esm2020/chart/chart-container/series/linear-series-base.mjs +21 -26
- package/esm2020/chart/chart-container/series/scatter-series/scatter-series.component.mjs +3 -3
- package/esm2020/chart/chart-container/x-axis/x-axis.component.mjs +3 -27
- package/esm2020/chart/chart-container/y-axis/y-axis.component.mjs +3 -3
- package/esm2020/chart/core/axis/axis.mjs +7 -1
- package/esm2020/chart/default/default-axis-config.mjs +2 -2
- package/esm2020/chart/directives/brushable.directive.mjs +1 -1
- package/esm2020/chart/directives/zoomable.directive.mjs +4 -3
- package/esm2020/chart/model/i-scales-map.mjs +2 -0
- package/esm2020/chart/model/public-api.mjs +2 -1
- package/esm2020/chart/service/brush.service.mjs +16 -13
- package/esm2020/chart/service/chart.service.mjs +6 -1
- package/esm2020/chart/service/scale.service.mjs +37 -65
- package/esm2020/chart/service/zoom.service.mjs +2 -2
- package/fesm2015/tetacom-svg-charts.mjs +149 -194
- package/fesm2015/tetacom-svg-charts.mjs.map +1 -1
- package/fesm2020/tetacom-svg-charts.mjs +141 -188
- package/fesm2020/tetacom-svg-charts.mjs.map +1 -1
- package/package.json +1 -1
|
@@ -7,9 +7,9 @@ import * as d3 from 'd3';
|
|
|
7
7
|
import { zoomIdentity } from 'd3';
|
|
8
8
|
import objectHash from 'object-hash';
|
|
9
9
|
import { maxIndex } from 'd3-array';
|
|
10
|
+
import { debounceTime, tap as tap$1 } from 'rxjs/operators';
|
|
10
11
|
import { tetaZoneFull } from '@tetacom/ng-components';
|
|
11
12
|
import * as i3 from '@angular/platform-browser';
|
|
12
|
-
import { tap as tap$1, debounceTime } from 'rxjs/operators';
|
|
13
13
|
|
|
14
14
|
var ZoomType;
|
|
15
15
|
(function (ZoomType) {
|
|
@@ -94,7 +94,7 @@ const defaultAxisConfig = {
|
|
|
94
94
|
scaleType: {
|
|
95
95
|
type: ScaleType.linear,
|
|
96
96
|
},
|
|
97
|
-
niceTicks:
|
|
97
|
+
niceTicks: false,
|
|
98
98
|
};
|
|
99
99
|
|
|
100
100
|
var SeriesType;
|
|
@@ -148,6 +148,7 @@ class ChartService {
|
|
|
148
148
|
this.chartContextMenu$ = new Subject();
|
|
149
149
|
this.annotationEvent$ = new Subject();
|
|
150
150
|
this.annotationMove$ = new Subject();
|
|
151
|
+
this.zoomInstance$ = new Subject();
|
|
151
152
|
this.id = of((Date.now() + Math.random()).toString(36));
|
|
152
153
|
this.config = this.config$.asObservable().pipe(withLatestFrom(this.id), map(this.setDefaults), map(this.setPreparationData), map(this.restoreLocalStorage), shareReplay({
|
|
153
154
|
bufferSize: 1,
|
|
@@ -174,6 +175,7 @@ class ChartService {
|
|
|
174
175
|
this.plotBandContextMenu = this.plotBandEvent$
|
|
175
176
|
.asObservable()
|
|
176
177
|
.pipe(filter((_) => _?.event?.type === 'contextmenu'));
|
|
178
|
+
this.zoomInstance = this.zoomInstance$.asObservable();
|
|
177
179
|
}
|
|
178
180
|
setConfig(config) {
|
|
179
181
|
this.clearTooltips();
|
|
@@ -240,6 +242,9 @@ class ChartService {
|
|
|
240
242
|
emitChartContextMenu(event) {
|
|
241
243
|
this.chartContextMenu$.next(event);
|
|
242
244
|
}
|
|
245
|
+
emitZoomInstance(event) {
|
|
246
|
+
this.zoomInstance$.next(event);
|
|
247
|
+
}
|
|
243
248
|
saveCookie(config) {
|
|
244
249
|
if (!config.name)
|
|
245
250
|
return;
|
|
@@ -361,7 +366,7 @@ class ZoomService {
|
|
|
361
366
|
this.scaleHashMap = new Map();
|
|
362
367
|
this.elementHashMap = new Map();
|
|
363
368
|
this.zoomHashMap = new Map();
|
|
364
|
-
this.zoomed$ = new BehaviorSubject(
|
|
369
|
+
this.zoomed$ = new BehaviorSubject({});
|
|
365
370
|
this.zoomed = this.zoomed$.asObservable().pipe(shareReplay({
|
|
366
371
|
bufferSize: 1,
|
|
367
372
|
refCount: true
|
|
@@ -567,6 +572,9 @@ class Axis {
|
|
|
567
572
|
setOriginDomain(domain) {
|
|
568
573
|
this._originDomain = domain;
|
|
569
574
|
}
|
|
575
|
+
setScale(scale) {
|
|
576
|
+
this._scale = scale;
|
|
577
|
+
}
|
|
570
578
|
setSelfSize() {
|
|
571
579
|
this._selfSize = new AxisSizeBuilder().build(this);
|
|
572
580
|
}
|
|
@@ -579,6 +587,9 @@ class Axis {
|
|
|
579
587
|
: this.chartConfig.yAxis[this.index];
|
|
580
588
|
this._options = options;
|
|
581
589
|
}
|
|
590
|
+
get scale() {
|
|
591
|
+
return this._scale;
|
|
592
|
+
}
|
|
582
593
|
get extremes() {
|
|
583
594
|
return this._extremes;
|
|
584
595
|
}
|
|
@@ -622,49 +633,29 @@ class ScaleService {
|
|
|
622
633
|
.set(ScaleType.symlog, d3.scaleSymlog)
|
|
623
634
|
.set(ScaleType.pow, d3.scalePow)
|
|
624
635
|
.set(ScaleType.sqrt, d3.scaleSqrt);
|
|
625
|
-
this.
|
|
626
|
-
this.chartService.size,
|
|
627
|
-
this.chartService.config,
|
|
628
|
-
]).pipe(map((data) => {
|
|
629
|
-
const [, config] = data;
|
|
630
|
-
const map = new Map();
|
|
631
|
-
config.xAxis.map((_, index) => {
|
|
632
|
-
map.set(index, Axis.createAxis(AxisOrientation.x, config, index));
|
|
633
|
-
});
|
|
634
|
-
return map;
|
|
635
|
-
}), shareReplay({
|
|
636
|
-
bufferSize: 1,
|
|
637
|
-
refCount: true,
|
|
638
|
-
}));
|
|
639
|
-
this.yAxisMap = combineLatest([
|
|
636
|
+
this.scales = combineLatest([
|
|
640
637
|
this.chartService.size,
|
|
641
638
|
this.chartService.config,
|
|
639
|
+
this.zoomService.zoomed,
|
|
642
640
|
]).pipe(map((data) => {
|
|
643
|
-
const [, config] = data;
|
|
644
|
-
const
|
|
641
|
+
const [size, config, zoom] = data;
|
|
642
|
+
const xAxisMap = new Map();
|
|
643
|
+
const yAxisMap = new Map();
|
|
645
644
|
config.yAxis.map((_, index) => {
|
|
646
|
-
|
|
645
|
+
yAxisMap.set(index, Axis.createAxis(AxisOrientation.y, config, index));
|
|
647
646
|
});
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
this.xScaleMap = combineLatest([
|
|
654
|
-
this.chartService.size,
|
|
655
|
-
this.chartService.config,
|
|
656
|
-
this.zoomService.zoomed,
|
|
657
|
-
]).pipe(withLatestFrom(this.yAxisMap, this.xAxisMap), map((data) => {
|
|
658
|
-
const [[size, config, zoom], yAxes, xAxes] = data;
|
|
659
|
-
const map = new Map();
|
|
660
|
-
const left = [...yAxes.values()]
|
|
647
|
+
config.xAxis.map((_, index) => {
|
|
648
|
+
xAxisMap.set(index, Axis.createAxis(AxisOrientation.x, config, index));
|
|
649
|
+
});
|
|
650
|
+
// Generate x scales
|
|
651
|
+
const left = Array.from(yAxisMap.values())
|
|
661
652
|
.filter((_) => _.options?.visible && _.options?.opposite)
|
|
662
653
|
.reduce((acc, cur) => acc + cur.selfSize, 0);
|
|
663
|
-
const right =
|
|
654
|
+
const right = Array.from(yAxisMap.values())
|
|
664
655
|
.filter((_) => _.options?.visible && _.options?.opposite !== true)
|
|
665
656
|
.reduce((acc, cur) => acc + cur.selfSize, 0);
|
|
666
657
|
const finalWidth = (size.width || 0) - left - right;
|
|
667
|
-
|
|
658
|
+
xAxisMap.forEach((axis) => {
|
|
668
659
|
let domain = axis.extremes;
|
|
669
660
|
if (axis?.options.inverted) {
|
|
670
661
|
domain = [...axis.extremes].reverse();
|
|
@@ -679,44 +670,33 @@ class ScaleService {
|
|
|
679
670
|
if (axis.options.scaleType.type === ScaleType.log) {
|
|
680
671
|
scale.base(axis.options.scaleType.base);
|
|
681
672
|
}
|
|
682
|
-
|
|
673
|
+
axis.setScale(scale);
|
|
683
674
|
axis.setOriginDomain(scale.domain());
|
|
684
675
|
const hasCache = this.transformCacheX.has(axis.index);
|
|
685
676
|
const shouldRestore = zoom?.target?.orientation !== AxisOrientation.x ||
|
|
686
677
|
zoom.target?.index !== axis.index;
|
|
687
678
|
if (hasCache && shouldRestore) {
|
|
688
679
|
const restoredTransform = this.transformCacheX.get(axis.index);
|
|
689
|
-
|
|
680
|
+
axis.setScale(restoredTransform.rescaleX(scale));
|
|
690
681
|
}
|
|
691
682
|
});
|
|
692
683
|
if (zoom) {
|
|
693
684
|
const event = zoom.event;
|
|
694
685
|
if (zoom.target?.orientation === AxisOrientation.x) {
|
|
695
|
-
if (
|
|
696
|
-
const
|
|
697
|
-
const rescaled = event.transform.rescaleX(
|
|
698
|
-
|
|
699
|
-
const axis =
|
|
686
|
+
if (xAxisMap.has(zoom.target.index)) {
|
|
687
|
+
const x = xAxisMap.get(zoom.target.index);
|
|
688
|
+
const rescaled = event.transform.rescaleX(x.scale);
|
|
689
|
+
x.setScale(rescaled);
|
|
690
|
+
const axis = xAxisMap.get(zoom.target.index);
|
|
700
691
|
this.transformCacheX.set(axis.index, event.transform);
|
|
701
692
|
}
|
|
702
693
|
}
|
|
703
694
|
}
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
bufferSize: 1,
|
|
707
|
-
refCount: true,
|
|
708
|
-
}));
|
|
709
|
-
this.yScaleMap = combineLatest([
|
|
710
|
-
this.chartService.size,
|
|
711
|
-
this.chartService.config,
|
|
712
|
-
this.zoomService.zoomed,
|
|
713
|
-
]).pipe(withLatestFrom(this.yAxisMap, this.xAxisMap), map((data) => {
|
|
714
|
-
const [[size, config, zoom], yAxes, xAxes] = data;
|
|
715
|
-
const map = new Map();
|
|
716
|
-
const top = [...xAxes.values()]
|
|
695
|
+
// Generate y axis
|
|
696
|
+
const top = Array.from(xAxisMap.values())
|
|
717
697
|
.filter((_) => _.options?.visible && _.options?.opposite)
|
|
718
698
|
.reduce((acc, cur) => acc + cur.selfSize, 0);
|
|
719
|
-
const bottom =
|
|
699
|
+
const bottom = Array.from(xAxisMap.values())
|
|
720
700
|
.filter((_) => _.options?.visible && _.options?.opposite !== true)
|
|
721
701
|
.reduce((acc, cur) => acc + cur.selfSize, 0);
|
|
722
702
|
const finalHeight = (size.height || 0) -
|
|
@@ -724,7 +704,7 @@ class ScaleService {
|
|
|
724
704
|
bottom -
|
|
725
705
|
config?.bounds?.top -
|
|
726
706
|
config.bounds?.bottom;
|
|
727
|
-
|
|
707
|
+
yAxisMap.forEach((axis) => {
|
|
728
708
|
let domain = axis.extremes;
|
|
729
709
|
if (axis.orientation === AxisOrientation.y) {
|
|
730
710
|
domain = [...axis.extremes].reverse();
|
|
@@ -742,29 +722,32 @@ class ScaleService {
|
|
|
742
722
|
if (axis.options.scaleType.type === ScaleType.log) {
|
|
743
723
|
scale.base(axis.options.scaleType.base);
|
|
744
724
|
}
|
|
745
|
-
|
|
725
|
+
axis.setScale(scale);
|
|
746
726
|
axis.setOriginDomain(scale.domain());
|
|
747
727
|
const hasCache = this.transformCacheY.has(axis.index);
|
|
748
728
|
const shouldRestore = zoom?.target?.orientation !== AxisOrientation.y ||
|
|
749
729
|
zoom.target?.index !== axis.index;
|
|
750
730
|
if (hasCache && shouldRestore) {
|
|
751
731
|
const restoredTransform = this.transformCacheY.get(axis.index);
|
|
752
|
-
|
|
732
|
+
axis.setScale(restoredTransform.rescaleY(scale));
|
|
753
733
|
}
|
|
754
734
|
});
|
|
755
735
|
if (zoom) {
|
|
756
736
|
const event = zoom.event;
|
|
757
737
|
if (zoom.target?.orientation === AxisOrientation.y) {
|
|
758
|
-
if (
|
|
759
|
-
const
|
|
760
|
-
const rescaled = event.transform.rescaleY(
|
|
761
|
-
|
|
762
|
-
const axis =
|
|
738
|
+
if (yAxisMap.has(zoom.target.index)) {
|
|
739
|
+
const y = yAxisMap.get(zoom.target.index);
|
|
740
|
+
const rescaled = event.transform.rescaleY(y.scale);
|
|
741
|
+
y.setScale(rescaled);
|
|
742
|
+
const axis = yAxisMap.get(zoom.target.index);
|
|
763
743
|
this.transformCacheY.set(axis.index, event.transform);
|
|
764
744
|
}
|
|
765
745
|
}
|
|
766
746
|
}
|
|
767
|
-
return
|
|
747
|
+
return {
|
|
748
|
+
x: xAxisMap,
|
|
749
|
+
y: yAxisMap
|
|
750
|
+
};
|
|
768
751
|
}), shareReplay({
|
|
769
752
|
bufferSize: 1,
|
|
770
753
|
refCount: true,
|
|
@@ -956,20 +939,22 @@ class BrushService {
|
|
|
956
939
|
brushScale(domain[0]),
|
|
957
940
|
brushScale(domain[1]),
|
|
958
941
|
]);
|
|
959
|
-
if (m.message.event.type === 'end') {
|
|
960
|
-
const brushMessage = new BrushMessage({
|
|
961
|
-
event: null,
|
|
962
|
-
selection: domain,
|
|
963
|
-
brushType: config?.brush?.type ?? BrushType.x,
|
|
964
|
-
brushScale,
|
|
965
|
-
});
|
|
966
|
-
this.broadcastService.broadcastBrush({
|
|
967
|
-
channel: config?.zoom?.syncChannel,
|
|
968
|
-
message: brushMessage,
|
|
969
|
-
});
|
|
970
|
-
}
|
|
971
942
|
this.selection = domain;
|
|
972
943
|
}
|
|
944
|
+
}), debounceTime(30), tap((m) => {
|
|
945
|
+
const { message: { domain }, } = m;
|
|
946
|
+
if (m.message.event.type === 'zoom') {
|
|
947
|
+
const brushMessage = new BrushMessage({
|
|
948
|
+
event: null,
|
|
949
|
+
selection: domain,
|
|
950
|
+
brushType: config?.brush?.type ?? BrushType.x,
|
|
951
|
+
brushScale,
|
|
952
|
+
});
|
|
953
|
+
this.broadcastService.broadcastBrush({
|
|
954
|
+
channel: config?.zoom?.syncChannel,
|
|
955
|
+
message: brushMessage,
|
|
956
|
+
});
|
|
957
|
+
}
|
|
973
958
|
}))
|
|
974
959
|
.subscribe();
|
|
975
960
|
}
|
|
@@ -1067,17 +1052,14 @@ class LinearSeriesBase extends SeriesBaseComponent {
|
|
|
1067
1052
|
};
|
|
1068
1053
|
this.defaultClipPointsMapping.set(ClipPointsDirection.x, filterX);
|
|
1069
1054
|
this.defaultClipPointsMapping.set(ClipPointsDirection.y, filterY);
|
|
1070
|
-
this.transform = this.svc.pointerMove.pipe(withLatestFrom(this.scaleService.
|
|
1071
|
-
const [event, x, y] = data;
|
|
1072
|
-
return this.getTransform(event, x, y);
|
|
1055
|
+
this.transform = this.svc.pointerMove.pipe(withLatestFrom(this.scaleService.scales), map((data) => {
|
|
1056
|
+
const [event, { x, y }] = data;
|
|
1057
|
+
return this.getTransform(event, x.get(this.series.xAxisIndex).scale, y.get(this.series.yAxisIndex).scale);
|
|
1073
1058
|
}), tap(() => setTimeout(() => this.cdr.detectChanges())));
|
|
1074
|
-
this.path =
|
|
1075
|
-
|
|
1076
|
-
this.
|
|
1077
|
-
|
|
1078
|
-
const [x, y] = data;
|
|
1079
|
-
this.x = x.get(this.series.xAxisIndex);
|
|
1080
|
-
this.y = y.get(this.series.yAxisIndex);
|
|
1059
|
+
this.path = this.scaleService.scales.pipe(map((data) => {
|
|
1060
|
+
const { x, y } = data;
|
|
1061
|
+
this.x = x.get(this.series.xAxisIndex).scale;
|
|
1062
|
+
this.y = y.get(this.series.yAxisIndex).scale;
|
|
1081
1063
|
const filter = this.defaultClipPointsMapping.get(this.series.clipPointsDirection);
|
|
1082
1064
|
const line = d3
|
|
1083
1065
|
.line()
|
|
@@ -1160,8 +1142,6 @@ class LinearSeriesBase extends SeriesBaseComponent {
|
|
|
1160
1142
|
return null;
|
|
1161
1143
|
}
|
|
1162
1144
|
const mouse = [event?.offsetX, event?.offsetY];
|
|
1163
|
-
const foundX = scaleX.get(this.series.xAxisIndex);
|
|
1164
|
-
const foundY = scaleY.get(this.series.yAxisIndex);
|
|
1165
1145
|
const tooltipTracking = this.config?.tooltip?.tracking;
|
|
1166
1146
|
const lineIntersection = (p0_x, p0_y, p1_x, p1_y, p2_x, p2_y, p3_x, p3_y) => {
|
|
1167
1147
|
const rV = {};
|
|
@@ -1187,18 +1167,18 @@ class LinearSeriesBase extends SeriesBaseComponent {
|
|
|
1187
1167
|
if (tooltipTracking === TooltipTracking.x) {
|
|
1188
1168
|
const bisect = d3.bisector((_) => _.x).right;
|
|
1189
1169
|
const pointer = mouse[0];
|
|
1190
|
-
let x0 =
|
|
1170
|
+
let x0 = scaleX.invert(pointer);
|
|
1191
1171
|
if (x0 instanceof Date) {
|
|
1192
1172
|
x0 = x0.getTime();
|
|
1193
1173
|
}
|
|
1194
1174
|
const rightId = bisect(this.series.data, x0);
|
|
1195
|
-
const range =
|
|
1196
|
-
const intersect = lineIntersection(pointer, range[0], pointer, range[1],
|
|
1197
|
-
const x =
|
|
1198
|
-
const y =
|
|
1175
|
+
const range = scaleY.range();
|
|
1176
|
+
const intersect = lineIntersection(pointer, range[0], pointer, range[1], scaleX(this.series.data[rightId - 1]?.x), scaleY(this.series.data[rightId - 1]?.y), scaleX(this.series.data[rightId]?.x), scaleY(this.series.data[rightId]?.y));
|
|
1177
|
+
const x = scaleX.invert(intersect.x);
|
|
1178
|
+
const y = scaleY.invert(intersect.y);
|
|
1199
1179
|
if (x !== null && x !== undefined && !isNaN(x) && y !== null && y !== undefined && !isNaN(y)) {
|
|
1200
1180
|
this.svc.setTooltip({
|
|
1201
|
-
point: { x:
|
|
1181
|
+
point: { x: scaleX.invert(intersect.x), y: scaleY.invert(intersect.y) },
|
|
1202
1182
|
series: this.series,
|
|
1203
1183
|
});
|
|
1204
1184
|
}
|
|
@@ -1215,18 +1195,18 @@ class LinearSeriesBase extends SeriesBaseComponent {
|
|
|
1215
1195
|
}
|
|
1216
1196
|
if (tooltipTracking === TooltipTracking.y) {
|
|
1217
1197
|
const bisect = d3.bisector((_) => _.y).right;
|
|
1218
|
-
let y0 =
|
|
1198
|
+
let y0 = scaleY.invert(mouse[1]);
|
|
1219
1199
|
if (y0 instanceof Date) {
|
|
1220
1200
|
y0 = y0.getTime();
|
|
1221
1201
|
}
|
|
1222
1202
|
const rightId = bisect(this.series.data, y0);
|
|
1223
|
-
const range =
|
|
1224
|
-
const intersect = lineIntersection(range[0], mouse[1], range[1], mouse[1],
|
|
1225
|
-
const x =
|
|
1226
|
-
const y =
|
|
1203
|
+
const range = scaleX.range();
|
|
1204
|
+
const intersect = lineIntersection(range[0], mouse[1], range[1], mouse[1], scaleX(this.series.data[rightId - 1]?.x), scaleY(this.series.data[rightId - 1]?.y), scaleX(this.series.data[rightId]?.x), scaleY(this.series.data[rightId]?.y));
|
|
1205
|
+
const x = scaleX.invert(intersect.x);
|
|
1206
|
+
const y = scaleY.invert(intersect.y);
|
|
1227
1207
|
if (x !== null && x !== undefined && !isNaN(x) && y !== null && y !== undefined && !isNaN(y)) {
|
|
1228
1208
|
this.svc.setTooltip({
|
|
1229
|
-
point: { x:
|
|
1209
|
+
point: { x: scaleX.invert(intersect.x), y: scaleY.invert(intersect.y) },
|
|
1230
1210
|
series: this.series,
|
|
1231
1211
|
});
|
|
1232
1212
|
}
|
|
@@ -1284,8 +1264,8 @@ class BarSeriesComponent extends SeriesBaseComponent {
|
|
|
1284
1264
|
const count = _.series.filter((_) => _.type === SeriesType.bar && _.xAxisIndex === this.series.xAxisIndex);
|
|
1285
1265
|
return count.length;
|
|
1286
1266
|
}));
|
|
1287
|
-
this.x1 = this.scaleService.
|
|
1288
|
-
const x = _.get(this.series.xAxisIndex);
|
|
1267
|
+
this.x1 = this.scaleService.scales.pipe(map((_) => {
|
|
1268
|
+
const x = _.x.get(this.series.xAxisIndex).scale;
|
|
1289
1269
|
const range = x.range();
|
|
1290
1270
|
const domain = this.series.data.map((_) => _.x);
|
|
1291
1271
|
return d3
|
|
@@ -1294,8 +1274,8 @@ class BarSeriesComponent extends SeriesBaseComponent {
|
|
|
1294
1274
|
.domain(domain)
|
|
1295
1275
|
.padding(0.1);
|
|
1296
1276
|
}));
|
|
1297
|
-
this.x = this.scaleService.
|
|
1298
|
-
this.y = this.scaleService.
|
|
1277
|
+
this.x = this.scaleService.scales.pipe(map((_) => _.x.get(this.series.xAxisIndex).scale));
|
|
1278
|
+
this.y = this.scaleService.scales.pipe(map((_) => _.y.get(this.series.yAxisIndex).scale));
|
|
1299
1279
|
}
|
|
1300
1280
|
mouseenter(point) {
|
|
1301
1281
|
this.svc.setTooltip({
|
|
@@ -1328,8 +1308,8 @@ class ScatterSeriesComponent extends SeriesBaseComponent {
|
|
|
1328
1308
|
this.element = element;
|
|
1329
1309
|
}
|
|
1330
1310
|
ngOnInit() {
|
|
1331
|
-
this.x = this.scaleService.
|
|
1332
|
-
this.y = this.scaleService.
|
|
1311
|
+
this.x = this.scaleService.scales.pipe(map(_ => _.x.get(this.series.xAxisIndex).scale));
|
|
1312
|
+
this.y = this.scaleService.scales.pipe(map(_ => _.y.get(this.series.yAxisIndex).scale));
|
|
1333
1313
|
}
|
|
1334
1314
|
ngAfterViewInit() {
|
|
1335
1315
|
}
|
|
@@ -1367,8 +1347,8 @@ class BlockSeriesComponent extends SeriesBaseComponent {
|
|
|
1367
1347
|
}
|
|
1368
1348
|
ngOnInit() {
|
|
1369
1349
|
const defaultVisiblePixels = 0;
|
|
1370
|
-
this.x = this.scaleService.
|
|
1371
|
-
this.y = this.scaleService.
|
|
1350
|
+
this.x = this.scaleService.scales.pipe(map((_) => _.x.get(this.series.xAxisIndex).scale));
|
|
1351
|
+
this.y = this.scaleService.scales.pipe(map((_) => _.y.get(this.series.yAxisIndex).scale));
|
|
1372
1352
|
this.displayPoints = this.y.pipe(map((y) => {
|
|
1373
1353
|
return this.series.data.filter((point, index, arr) => {
|
|
1374
1354
|
const [min, max] = y.domain();
|
|
@@ -1419,8 +1399,8 @@ class BlockAreaSeriesComponent extends SeriesBaseComponent {
|
|
|
1419
1399
|
}
|
|
1420
1400
|
ngOnInit() {
|
|
1421
1401
|
const defaultVisiblePixels = 0;
|
|
1422
|
-
this.x = this.scaleService.
|
|
1423
|
-
this.y = this.scaleService.
|
|
1402
|
+
this.x = this.scaleService.scales.pipe(map((_) => _.x.get(this.series.xAxisIndex).scale));
|
|
1403
|
+
this.y = this.scaleService.scales.pipe(map((_) => _.y.get(this.series.yAxisIndex).scale));
|
|
1424
1404
|
this.displayPoints = this.y.pipe(map((y) => {
|
|
1425
1405
|
return this.series.data.filter((point, index, arr) => {
|
|
1426
1406
|
const [min, max] = y.domain();
|
|
@@ -1471,13 +1451,10 @@ class AreaSeriesComponent extends LinearSeriesBase {
|
|
|
1471
1451
|
}
|
|
1472
1452
|
ngOnInit() {
|
|
1473
1453
|
super.ngOnInit();
|
|
1474
|
-
this.areaPath =
|
|
1475
|
-
|
|
1476
|
-
this.
|
|
1477
|
-
|
|
1478
|
-
const [x, y] = data;
|
|
1479
|
-
this.x = x.get(this.series.xAxisIndex);
|
|
1480
|
-
this.y = y.get(this.series.yAxisIndex);
|
|
1454
|
+
this.areaPath = this.scaleService.scales.pipe(map((data) => {
|
|
1455
|
+
const { x, y } = data;
|
|
1456
|
+
this.x = x.get(this.series.xAxisIndex).scale;
|
|
1457
|
+
this.y = y.get(this.series.yAxisIndex).scale;
|
|
1481
1458
|
const area = d3
|
|
1482
1459
|
.area()
|
|
1483
1460
|
.defined((point) => point.x !== null &&
|
|
@@ -1567,16 +1544,16 @@ class GridlinesComponent {
|
|
|
1567
1544
|
this.svc = svc;
|
|
1568
1545
|
this.chartService = chartService;
|
|
1569
1546
|
this.config = this.chartService.config;
|
|
1570
|
-
this.tickYValues = this.svc.
|
|
1547
|
+
this.tickYValues = this.svc.scales.pipe(map((_) => {
|
|
1571
1548
|
const ratio = this.size.height / 40;
|
|
1572
|
-
return _.get(0).ticks(ratio);
|
|
1549
|
+
return _.y.get(0).scale.ticks(ratio);
|
|
1573
1550
|
}));
|
|
1574
|
-
this.tickXValues = this.svc.
|
|
1551
|
+
this.tickXValues = this.svc.scales.pipe(map((_) => {
|
|
1575
1552
|
const ratio = this.size.width / 40;
|
|
1576
|
-
return _.get(0).ticks(ratio);
|
|
1553
|
+
return _.x.get(0).scale.ticks(ratio);
|
|
1577
1554
|
}));
|
|
1578
|
-
this.y = this.svc.
|
|
1579
|
-
this.x = this.svc.
|
|
1555
|
+
this.y = this.svc.scales.pipe(map((_) => _.y.get(0).scale));
|
|
1556
|
+
this.x = this.svc.scales.pipe(map((_) => _.x.get(0).scale));
|
|
1580
1557
|
}
|
|
1581
1558
|
ngAfterViewInit() {
|
|
1582
1559
|
}
|
|
@@ -1594,8 +1571,8 @@ class XAxisComponent {
|
|
|
1594
1571
|
constructor(scaleService) {
|
|
1595
1572
|
this.scaleService = scaleService;
|
|
1596
1573
|
this._alive = true;
|
|
1597
|
-
this.x = this.scaleService.
|
|
1598
|
-
return _.get(this.axis.index);
|
|
1574
|
+
this.x = this.scaleService.scales.pipe(map((_) => {
|
|
1575
|
+
return _.x.get(this.axis.index)?.scale;
|
|
1599
1576
|
}));
|
|
1600
1577
|
}
|
|
1601
1578
|
getLabelTransform() {
|
|
@@ -1605,30 +1582,6 @@ class XAxisComponent {
|
|
|
1605
1582
|
ngOnDestroy() {
|
|
1606
1583
|
this._alive = false;
|
|
1607
1584
|
}
|
|
1608
|
-
ngAfterViewInit() {
|
|
1609
|
-
// this.draw();
|
|
1610
|
-
}
|
|
1611
|
-
draw() {
|
|
1612
|
-
// if (!this.node || !this.axis) {
|
|
1613
|
-
// return;
|
|
1614
|
-
// }
|
|
1615
|
-
//
|
|
1616
|
-
// const axis = this.axis.options.opposite
|
|
1617
|
-
// ? d3
|
|
1618
|
-
// .axisTop(this.scale)
|
|
1619
|
-
// .tickFormat(
|
|
1620
|
-
// this.axis.options.tickFormat ?? this.axis.defaultFormatter()
|
|
1621
|
-
// )
|
|
1622
|
-
// : d3
|
|
1623
|
-
// .axisBottom(this.scale)
|
|
1624
|
-
// .tickFormat(
|
|
1625
|
-
// this.axis.options.tickFormat ?? this.axis.defaultFormatter()
|
|
1626
|
-
// );
|
|
1627
|
-
//
|
|
1628
|
-
// d3.select(this.node.nativeElement)
|
|
1629
|
-
// .call(axis)
|
|
1630
|
-
// .call((_) => _.select('.domain').remove());
|
|
1631
|
-
}
|
|
1632
1585
|
}
|
|
1633
1586
|
XAxisComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.2", ngImport: i0, type: XAxisComponent, deps: [{ token: ScaleService }], target: i0.ɵɵFactoryTarget.Component });
|
|
1634
1587
|
XAxisComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.0.2", type: XAxisComponent, selector: "[teta-x-axis]", inputs: { axis: "axis", size: "size" }, ngImport: i0, template: "<ng-container *ngIf=\"x | async as scale\">\n <svg:g text-anchor=\"middle\" *ngFor=\"let tick of scale.ticks()\" [attr.transform]=\"'translate('+ scale(tick) +', 0)'\">\n <text fill=\"var(--color-text-70)\" [attr.dy]=\"axis.options.opposite ? '-0.71em' : '0.71em'\" [attr.y]=\"axis.options.opposite ? 0 : 9\">{{ this.axis.options.tickFormat ? this.axis.options.tickFormat(tick) : this.axis.defaultFormatter()(tick) }}</text>\n <line stroke=\"var(--color-text-30)\" [attr.y2]=\"axis.options.opposite ? -6 : 6\"></line>\n </svg:g>\n\n <svg:g class=\"label-axis font-caption\" [attr.transform]=\"getLabelTransform()\">\n <text fill=\"var(--color-text-70)\" text-anchor=\"middle\" dominant-baseline=\"middle\">{{ axis.options.title }}</text>\n </svg:g>\n</ng-container>\n\n", styles: [":host .tick{stroke:var(--color-text-20)}\n"], dependencies: [{ kind: "directive", type: i4.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: i4.AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
@@ -1645,8 +1598,8 @@ class YAxisComponent {
|
|
|
1645
1598
|
constructor(scaleService) {
|
|
1646
1599
|
this.scaleService = scaleService;
|
|
1647
1600
|
this._alive = true;
|
|
1648
|
-
this.y = this.scaleService.
|
|
1649
|
-
return _.get(this.axis.index);
|
|
1601
|
+
this.y = this.scaleService.scales.pipe(map((_) => {
|
|
1602
|
+
return _.y.get(this.axis.index)?.scale;
|
|
1650
1603
|
}));
|
|
1651
1604
|
}
|
|
1652
1605
|
ngOnInit() { }
|
|
@@ -2069,6 +2022,7 @@ class ZoomableDirective {
|
|
|
2069
2022
|
this.zoom.scaleExtent([maxZoom, minZoom]);
|
|
2070
2023
|
this.zoom.on('zoom end', this.zoomed);
|
|
2071
2024
|
this._element.call(this.zoom).on('dblclick.zoom', null); // Disable dbclick zoom
|
|
2025
|
+
this.chartService.emitZoomInstance(this.zoomService);
|
|
2072
2026
|
if (this.config?.zoom?.zoomBehavior === ZoomBehaviorType.wheel) {
|
|
2073
2027
|
this.runWheelZoom();
|
|
2074
2028
|
}
|
|
@@ -2121,7 +2075,7 @@ class ZoomableDirective {
|
|
|
2121
2075
|
.pipe(combineLatestWith(this.chartService.size), takeWhile((_) => this.alive), filter((data) => {
|
|
2122
2076
|
const [m] = data;
|
|
2123
2077
|
return Boolean(m.message.selection);
|
|
2124
|
-
}),
|
|
2078
|
+
}), tap$1((data) => {
|
|
2125
2079
|
const [m] = data;
|
|
2126
2080
|
const currentTransform = d3.zoomTransform(this._element.node());
|
|
2127
2081
|
if (!m.message.event &&
|
|
@@ -2300,8 +2254,8 @@ class AnnotationComponent {
|
|
|
2300
2254
|
this.scaleService = scaleService;
|
|
2301
2255
|
this.cdr = cdr;
|
|
2302
2256
|
this.chartService = chartService;
|
|
2303
|
-
this.x = this.scaleService.
|
|
2304
|
-
this.y = this.scaleService.
|
|
2257
|
+
this.x = this.scaleService.scales.pipe(map((_) => _.x.get(this.annotation.xAxisIndex ?? 0).scale));
|
|
2258
|
+
this.y = this.scaleService.scales.pipe(map((_) => _.y.get(this.annotation.yAxisIndex ?? 0).scale));
|
|
2305
2259
|
this.drag = d3.drag();
|
|
2306
2260
|
}
|
|
2307
2261
|
set annotation(annotation) {
|
|
@@ -2415,30 +2369,21 @@ class ChartContainerComponent {
|
|
|
2415
2369
|
this.sumSize = (acc, curr) => acc + curr.selfSize;
|
|
2416
2370
|
this.config = this._svc.config;
|
|
2417
2371
|
this.size = this._svc.size;
|
|
2418
|
-
this.
|
|
2419
|
-
this.xAxisMap = this._scaleService.xAxisMap;
|
|
2420
|
-
this.yScaleMap = this._scaleService.yScaleMap.pipe(observeOn(animationFrameScheduler, 10), tetaZoneFull(this._zone), shareReplay({
|
|
2372
|
+
this.scales = this._scaleService.scales.pipe(observeOn(animationFrameScheduler), tetaZoneFull(this._zone), shareReplay({
|
|
2421
2373
|
bufferSize: 1,
|
|
2422
2374
|
refCount: true,
|
|
2423
2375
|
}));
|
|
2424
|
-
this.
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
}));
|
|
2428
|
-
this.brushScale = combineLatest([
|
|
2429
|
-
this._scaleService.xScaleMap,
|
|
2430
|
-
this._scaleService.yScaleMap,
|
|
2431
|
-
]).pipe(withLatestFrom(this.config), map((data) => {
|
|
2432
|
-
const [[x, y], config] = data;
|
|
2433
|
-
return config.brush?.type === BrushType.x || config?.zoom?.type === ZoomType.x ? x.get(0) : y.get(0);
|
|
2376
|
+
this.brushScale = this._scaleService.scales.pipe(withLatestFrom(this.config), map((data) => {
|
|
2377
|
+
const [{ x, y }, config] = data;
|
|
2378
|
+
return config.brush?.type === BrushType.x || config?.zoom?.type === ZoomType.x ? x.get(0).scale : y.get(0).scale;
|
|
2434
2379
|
}), shareReplay({
|
|
2435
2380
|
bufferSize: 1,
|
|
2436
2381
|
refCount: true,
|
|
2437
2382
|
}));
|
|
2438
|
-
this.visibleRect = this.size.pipe(combineLatestWith(this.
|
|
2439
|
-
const [[size, x, y], config] = data;
|
|
2440
|
-
const yAxesArray =
|
|
2441
|
-
const xAxesArray =
|
|
2383
|
+
this.visibleRect = this.size.pipe(combineLatestWith(this.scales)).pipe(withLatestFrom(this.config), map((data) => {
|
|
2384
|
+
const [[size, { x, y }], config] = data;
|
|
2385
|
+
const yAxesArray = Array.from(y.values());
|
|
2386
|
+
const xAxesArray = Array.from(x.values());
|
|
2442
2387
|
const left = yAxesArray
|
|
2443
2388
|
.filter((_) => _.options.opposite !== true && _.options.visible)
|
|
2444
2389
|
.reduce(this.sumSize, 0);
|
|
@@ -2490,10 +2435,10 @@ class ChartContainerComponent {
|
|
|
2490
2435
|
this._observer.disconnect();
|
|
2491
2436
|
}
|
|
2492
2437
|
getTranslate(axis, size) {
|
|
2493
|
-
return
|
|
2494
|
-
const [
|
|
2495
|
-
const xAxesArray =
|
|
2496
|
-
const yAxesArray =
|
|
2438
|
+
return this.scales.pipe(withLatestFrom(this.config), map((data) => {
|
|
2439
|
+
const [{ x, y }, config] = data;
|
|
2440
|
+
const xAxesArray = Array.from(x.values());
|
|
2441
|
+
const yAxesArray = Array.from(y.values());
|
|
2497
2442
|
const oppositeFilter = this.filterPositionMap.get(true);
|
|
2498
2443
|
const nonOppositeFilter = this.filterPositionMap.get(false);
|
|
2499
2444
|
const oppositeOffsetY = yAxesArray.filter(oppositeFilter(axis));
|
|
@@ -2527,8 +2472,8 @@ class ChartContainerComponent {
|
|
|
2527
2472
|
return item.value.index;
|
|
2528
2473
|
}
|
|
2529
2474
|
click(event, xScales, yScales) {
|
|
2530
|
-
const x = xScales.get(0);
|
|
2531
|
-
const y = yScales.get(0);
|
|
2475
|
+
const x = xScales.get(0).scale;
|
|
2476
|
+
const y = yScales.get(0).scale;
|
|
2532
2477
|
this._svc.emitChartClick({
|
|
2533
2478
|
event: event,
|
|
2534
2479
|
target: {
|
|
@@ -2538,8 +2483,8 @@ class ChartContainerComponent {
|
|
|
2538
2483
|
});
|
|
2539
2484
|
}
|
|
2540
2485
|
contextMenu(event, xScales, yScales) {
|
|
2541
|
-
const x = xScales.get(0);
|
|
2542
|
-
const y = yScales.get(0);
|
|
2486
|
+
const x = xScales.get(0).scale;
|
|
2487
|
+
const y = yScales.get(0).scale;
|
|
2543
2488
|
this._svc.emitChartContextMenu({
|
|
2544
2489
|
event: event,
|
|
2545
2490
|
target: {
|
|
@@ -2556,10 +2501,10 @@ class ChartContainerComponent {
|
|
|
2556
2501
|
}
|
|
2557
2502
|
}
|
|
2558
2503
|
ChartContainerComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.2", ngImport: i0, type: ChartContainerComponent, deps: [{ token: ChartService }, { token: i0.ChangeDetectorRef }, { token: ScaleService }, { token: ZoomService }, { token: i0.ElementRef }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Component });
|
|
2559
|
-
ChartContainerComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.0.2", type: ChartContainerComponent, selector: "teta-chart-container", ngImport: i0, template: "<ng-container *ngIf=\"{\n size: size | async,\n config: config | async,\n
|
|
2504
|
+
ChartContainerComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.0.2", type: ChartContainerComponent, selector: "teta-chart-container", ngImport: i0, template: "<ng-container *ngIf=\"{\n size: size | async,\n config: config | async,\n scales: scales | async,\n visibleRect: visibleRect | async,\n brushScale: brushScale | async\n} as data\" xmlns:svg=\"http://www.w3.org/1999/html\">\n <teta-tooltip *ngIf=\"data.config?.tooltip?.enable\"\n [size]=\"data.size\"\n [config]=\"data.config\"></teta-tooltip>\n <ng-container *ngIf=\"data.visibleRect?.width > 0 && data.visibleRect?.height > 0 && data.scales.x && data.scales.y\">\n <svg height=\"100%\" width=\"100%\" class=\"position-absolute\">\n <g class=\"y-axis-container\">\n <ng-container *ngFor=\"let item of data.scales.y | keyvalue; trackBy: identify\">\n <ng-container *ngIf=\"item.value.options.visible\">\n <g\n teta-y-axis\n [axis]=\"item.value\"\n [size]=\"data.visibleRect\"\n [attr.transform]=\"getTranslate(item.value, data.size) | async\"></g>\n <rect\n tetaZoomable\n fill-opacity=\"0\"\n [brushScale]=\"data.brushScale\"\n [scale]=\"data.scales.y.get(item.key).scale\"\n [axis]=\"item.value\"\n [config]=\"data.config\"\n [size]=\"data.visibleRect\"\n [attr.x]=\"item.value.options.opposite ? 0 : -item.value.selfSize\"\n [attr.y]=\"0\"\n [attr.height]=\"data.visibleRect.height\"\n [attr.width]=\"item.value.selfSize\"\n [attr.transform]=\"getTranslate(item.value, data.size) | async\"></rect>\n </ng-container>\n\n </ng-container>\n </g>\n <g class=\"x-axis-container\">\n <ng-container *ngFor=\"let item of data.scales.x | keyvalue; trackBy: identify\">\n <ng-container *ngIf=\"item.value.options.visible && data.scales.x && data.scales.y\">\n <g\n teta-x-axis\n [axis]=\"item.value\"\n [size]=\"data.visibleRect\"\n [attr.transform]=\"getTranslate(item.value, data.size) | async\"></g>\n <rect\n tetaZoomable\n fill-opacity=\"0\"\n [brushScale]=\"data.brushScale\"\n [scale]=\"data.scales.x.get(item.key).scale\"\n [axis]=\"item.value\"\n [config]=\"data.config\"\n [size]=\"data.visibleRect\"\n [attr.x]=\"0\"\n [attr.y]=\"item.value.options.opposite ? -item.value.selfSize : 0\"\n [attr.width]=\"data.visibleRect.width\"\n [attr.height]=\"item.value.selfSize\"\n [attr.transform]=\"getTranslate(item.value, data.size) | async\"></rect>\n </ng-container>\n </ng-container>\n </g>\n </svg>\n </ng-container>\n <ng-container *ngIf=\"data.visibleRect?.width > 0 && data.visibleRect?.height > 0 && data.scales.x && data.scales.y\">\n <svg\n tetaBrushable\n tetaZoomable\n class=\"position-absolute\"\n [size]=\"data.visibleRect\"\n [brushScale]=\"data.brushScale\"\n [scale]=\"data.brushScale\"\n [config]=\"data.config\"\n [axis]=\"data.config?.zoom?.type === zoomType.x ? data.scales.x.get(0) : data.scales.y.get(0)\"\n [attr.width]=\"data.visibleRect.width\"\n [attr.height]=\"data.visibleRect.height\"\n [attr.viewBox]=\"'0 0 ' + data.visibleRect.width + ' ' + data.visibleRect.height\"\n [style.transform]=\"'translate('+ data.visibleRect.x +'px, '+ data.visibleRect.y +'px)'\"\n (contextmenu)=\"contextMenu($event, data.scales.x, data.scales.y)\"\n (click)=\"click($event, data.scales.x, data.scales.y)\"\n (mouseleave)=\"mouseLeave($event)\"\n (mousemove)=\"mouseMove($event)\">\n\n <g class=\"gridlines\"\n teta-gridlines\n *ngIf=\"data.config.gridLines?.enable !== false\"\n [size]=\"data.size\"></g>\n\n <g class=\"x-axis-plotband-container\">\n <ng-container *ngFor=\"let axis of data.config.xAxis; let i = index\">\n <g teta-plot-band *ngFor=\"let plotBand of axis.plotBands\"\n [plotBand]=\"plotBand\"\n [scale]=\"data.scales.x.get(i).scale\"\n [size]=\"data.size\"\n [axis]=\"data.scales.x.get(i)\"></g>\n </ng-container>\n </g>\n <g class=\"y-axis-plotband-container\">\n <ng-container *ngFor=\"let axis of data.config.yAxis; let i = index\">\n <g teta-plot-band *ngFor=\"let plotBand of axis.plotBands\"\n [plotBand]=\"plotBand\"\n [scale]=\"data.scales.y.get(i).scale\"\n [size]=\"data.size\"\n [axis]=\"data.scales.y.get(i)\"></g>\n </ng-container>\n </g>\n <g class=\"x-axis-plotline-container\">\n <ng-container *ngFor=\"let axis of data.config.xAxis; let i = index\">\n <g teta-plot-line *ngFor=\"let plotLine of axis.plotLines\"\n [plotLine]=\"plotLine\"\n [scale]=\"data.scales.x.get(i).scale\"\n [size]=\"data.size\"\n [axis]=\"data.scales.x.get(i)\"></g>\n </ng-container>\n </g>\n <g class=\"y-axis-plotline-container\">\n <ng-container *ngFor=\"let axis of data.config.yAxis; let i = index\">\n <g teta-plot-line *ngFor=\"let plotLine of axis.plotLines\"\n [plotLine]=\"plotLine\"\n [scale]=\"data.scales.y.get(i).scale\"\n [size]=\"data.size\"\n [axis]=\"data.scales.x.get(i)\"></g>\n </ng-container>\n </g>\n <g class=\"series-container\">\n <ng-container *ngFor=\"let series of data.config.series\">\n <g teta-series-host\n *ngIf=\"series.visible\"\n [config]=\"data.config\"\n [series]=\"series\"></g>\n </ng-container>\n </g>\n <g class=\"annotations\">\n <g teta-annotation\n *ngFor=\"let annotation of data.config.annotations\"\n [annotation]=\"annotation\"></g>\n </g>\n <g class=\"crosshair\" *ngIf=\"data.config.tooltip?.showCrosshair\">\n <g teta-crosshair [size]=\"data.visibleRect\"></g>\n </g>\n </svg>\n\n </ng-container>\n</ng-container>\n", styles: [":host{display:flex;flex-direction:column;flex-grow:1;min-width:0;min-height:0}:host .zoomable:hover{cursor:grab}:host .zoomable:active{cursor:grabbing}:host .crosshair{cursor:crosshair}\n"], dependencies: [{ kind: "directive", type: i4.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: SeriesHostComponent, selector: "[teta-series-host]", inputs: ["config", "series"] }, { kind: "component", type: GridlinesComponent, selector: "[teta-gridlines]", inputs: ["size"] }, { kind: "component", type: XAxisComponent, selector: "[teta-x-axis]", inputs: ["axis", "size"] }, { kind: "component", type: YAxisComponent, selector: "[teta-y-axis]", inputs: ["axis", "size"] }, { kind: "component", type: PlotlineComponent, selector: "[teta-plot-line]", inputs: ["plotLine", "size", "axis", "scale"] }, { kind: "component", type: PlotBandComponent, selector: "[teta-plot-band]", inputs: ["plotBand", "axis", "scale", "size"] }, { kind: "component", type: TooltipComponent, selector: "teta-tooltip", inputs: ["size", "config"] }, { kind: "directive", type: ZoomableDirective, selector: "[tetaZoomable]", inputs: ["config", "axis", "size", "brushScale", "scale"] }, { kind: "directive", type: BrushableDirective, selector: "[tetaBrushable]", inputs: ["config", "brushScale"] }, { kind: "component", type: AnnotationComponent, selector: "[teta-annotation]", inputs: ["annotation"] }, { kind: "component", type: CrosshairComponent, selector: "[teta-crosshair]", inputs: ["size"] }, { kind: "pipe", type: i4.AsyncPipe, name: "async" }, { kind: "pipe", type: i4.KeyValuePipe, name: "keyvalue" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
2560
2505
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.2", ngImport: i0, type: ChartContainerComponent, decorators: [{
|
|
2561
2506
|
type: Component,
|
|
2562
|
-
args: [{ selector: 'teta-chart-container', changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-container *ngIf=\"{\n size: size | async,\n config: config | async,\n
|
|
2507
|
+
args: [{ selector: 'teta-chart-container', changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-container *ngIf=\"{\n size: size | async,\n config: config | async,\n scales: scales | async,\n visibleRect: visibleRect | async,\n brushScale: brushScale | async\n} as data\" xmlns:svg=\"http://www.w3.org/1999/html\">\n <teta-tooltip *ngIf=\"data.config?.tooltip?.enable\"\n [size]=\"data.size\"\n [config]=\"data.config\"></teta-tooltip>\n <ng-container *ngIf=\"data.visibleRect?.width > 0 && data.visibleRect?.height > 0 && data.scales.x && data.scales.y\">\n <svg height=\"100%\" width=\"100%\" class=\"position-absolute\">\n <g class=\"y-axis-container\">\n <ng-container *ngFor=\"let item of data.scales.y | keyvalue; trackBy: identify\">\n <ng-container *ngIf=\"item.value.options.visible\">\n <g\n teta-y-axis\n [axis]=\"item.value\"\n [size]=\"data.visibleRect\"\n [attr.transform]=\"getTranslate(item.value, data.size) | async\"></g>\n <rect\n tetaZoomable\n fill-opacity=\"0\"\n [brushScale]=\"data.brushScale\"\n [scale]=\"data.scales.y.get(item.key).scale\"\n [axis]=\"item.value\"\n [config]=\"data.config\"\n [size]=\"data.visibleRect\"\n [attr.x]=\"item.value.options.opposite ? 0 : -item.value.selfSize\"\n [attr.y]=\"0\"\n [attr.height]=\"data.visibleRect.height\"\n [attr.width]=\"item.value.selfSize\"\n [attr.transform]=\"getTranslate(item.value, data.size) | async\"></rect>\n </ng-container>\n\n </ng-container>\n </g>\n <g class=\"x-axis-container\">\n <ng-container *ngFor=\"let item of data.scales.x | keyvalue; trackBy: identify\">\n <ng-container *ngIf=\"item.value.options.visible && data.scales.x && data.scales.y\">\n <g\n teta-x-axis\n [axis]=\"item.value\"\n [size]=\"data.visibleRect\"\n [attr.transform]=\"getTranslate(item.value, data.size) | async\"></g>\n <rect\n tetaZoomable\n fill-opacity=\"0\"\n [brushScale]=\"data.brushScale\"\n [scale]=\"data.scales.x.get(item.key).scale\"\n [axis]=\"item.value\"\n [config]=\"data.config\"\n [size]=\"data.visibleRect\"\n [attr.x]=\"0\"\n [attr.y]=\"item.value.options.opposite ? -item.value.selfSize : 0\"\n [attr.width]=\"data.visibleRect.width\"\n [attr.height]=\"item.value.selfSize\"\n [attr.transform]=\"getTranslate(item.value, data.size) | async\"></rect>\n </ng-container>\n </ng-container>\n </g>\n </svg>\n </ng-container>\n <ng-container *ngIf=\"data.visibleRect?.width > 0 && data.visibleRect?.height > 0 && data.scales.x && data.scales.y\">\n <svg\n tetaBrushable\n tetaZoomable\n class=\"position-absolute\"\n [size]=\"data.visibleRect\"\n [brushScale]=\"data.brushScale\"\n [scale]=\"data.brushScale\"\n [config]=\"data.config\"\n [axis]=\"data.config?.zoom?.type === zoomType.x ? data.scales.x.get(0) : data.scales.y.get(0)\"\n [attr.width]=\"data.visibleRect.width\"\n [attr.height]=\"data.visibleRect.height\"\n [attr.viewBox]=\"'0 0 ' + data.visibleRect.width + ' ' + data.visibleRect.height\"\n [style.transform]=\"'translate('+ data.visibleRect.x +'px, '+ data.visibleRect.y +'px)'\"\n (contextmenu)=\"contextMenu($event, data.scales.x, data.scales.y)\"\n (click)=\"click($event, data.scales.x, data.scales.y)\"\n (mouseleave)=\"mouseLeave($event)\"\n (mousemove)=\"mouseMove($event)\">\n\n <g class=\"gridlines\"\n teta-gridlines\n *ngIf=\"data.config.gridLines?.enable !== false\"\n [size]=\"data.size\"></g>\n\n <g class=\"x-axis-plotband-container\">\n <ng-container *ngFor=\"let axis of data.config.xAxis; let i = index\">\n <g teta-plot-band *ngFor=\"let plotBand of axis.plotBands\"\n [plotBand]=\"plotBand\"\n [scale]=\"data.scales.x.get(i).scale\"\n [size]=\"data.size\"\n [axis]=\"data.scales.x.get(i)\"></g>\n </ng-container>\n </g>\n <g class=\"y-axis-plotband-container\">\n <ng-container *ngFor=\"let axis of data.config.yAxis; let i = index\">\n <g teta-plot-band *ngFor=\"let plotBand of axis.plotBands\"\n [plotBand]=\"plotBand\"\n [scale]=\"data.scales.y.get(i).scale\"\n [size]=\"data.size\"\n [axis]=\"data.scales.y.get(i)\"></g>\n </ng-container>\n </g>\n <g class=\"x-axis-plotline-container\">\n <ng-container *ngFor=\"let axis of data.config.xAxis; let i = index\">\n <g teta-plot-line *ngFor=\"let plotLine of axis.plotLines\"\n [plotLine]=\"plotLine\"\n [scale]=\"data.scales.x.get(i).scale\"\n [size]=\"data.size\"\n [axis]=\"data.scales.x.get(i)\"></g>\n </ng-container>\n </g>\n <g class=\"y-axis-plotline-container\">\n <ng-container *ngFor=\"let axis of data.config.yAxis; let i = index\">\n <g teta-plot-line *ngFor=\"let plotLine of axis.plotLines\"\n [plotLine]=\"plotLine\"\n [scale]=\"data.scales.y.get(i).scale\"\n [size]=\"data.size\"\n [axis]=\"data.scales.x.get(i)\"></g>\n </ng-container>\n </g>\n <g class=\"series-container\">\n <ng-container *ngFor=\"let series of data.config.series\">\n <g teta-series-host\n *ngIf=\"series.visible\"\n [config]=\"data.config\"\n [series]=\"series\"></g>\n </ng-container>\n </g>\n <g class=\"annotations\">\n <g teta-annotation\n *ngFor=\"let annotation of data.config.annotations\"\n [annotation]=\"annotation\"></g>\n </g>\n <g class=\"crosshair\" *ngIf=\"data.config.tooltip?.showCrosshair\">\n <g teta-crosshair [size]=\"data.visibleRect\"></g>\n </g>\n </svg>\n\n </ng-container>\n</ng-container>\n", styles: [":host{display:flex;flex-direction:column;flex-grow:1;min-width:0;min-height:0}:host .zoomable:hover{cursor:grab}:host .zoomable:active{cursor:grabbing}:host .crosshair{cursor:crosshair}\n"] }]
|
|
2563
2508
|
}], ctorParameters: function () { return [{ type: ChartService }, { type: i0.ChangeDetectorRef }, { type: ScaleService }, { type: ZoomService }, { type: i0.ElementRef }, { type: i0.NgZone }]; } });
|
|
2564
2509
|
|
|
2565
2510
|
class LegendComponent {
|
|
@@ -2609,6 +2554,7 @@ class ChartComponent {
|
|
|
2609
2554
|
this.annotationContextMenu = new EventEmitter();
|
|
2610
2555
|
this.annotationClick = new EventEmitter();
|
|
2611
2556
|
this.annotationMove = new EventEmitter();
|
|
2557
|
+
this.zoomServiceInstance = new EventEmitter();
|
|
2612
2558
|
this._alive = true;
|
|
2613
2559
|
this.svcConfig = this.chartService.config;
|
|
2614
2560
|
this.hasSeriesData = this.svcConfig.pipe(map((_) => _.series?.length > 0 && _.series?.some((_) => _.data?.length > 0)));
|
|
@@ -2620,14 +2566,14 @@ class ChartComponent {
|
|
|
2620
2566
|
}
|
|
2621
2567
|
ngOnInit() {
|
|
2622
2568
|
this.chartService.pointerMove
|
|
2623
|
-
.pipe(takeWhile(() => this._alive), withLatestFrom(this.scaleService.
|
|
2569
|
+
.pipe(takeWhile(() => this._alive), withLatestFrom(this.scaleService.scales, this.chartService.config))
|
|
2624
2570
|
.subscribe((data) => {
|
|
2625
|
-
const [event, x, y, config] = data;
|
|
2571
|
+
const [event, { x, y }, config] = data;
|
|
2626
2572
|
const tooltipTracking = config?.tooltip?.tracking;
|
|
2627
2573
|
if (tooltipTracking === TooltipTracking.y) {
|
|
2628
2574
|
const result = new Map();
|
|
2629
2575
|
y.forEach((value, key) => {
|
|
2630
|
-
result.set(key, value.invert(event.offsetY));
|
|
2576
|
+
result.set(key, value.scale.invert(event.offsetY));
|
|
2631
2577
|
});
|
|
2632
2578
|
this.pointerMove.emit({
|
|
2633
2579
|
event: event,
|
|
@@ -2637,7 +2583,7 @@ class ChartComponent {
|
|
|
2637
2583
|
else {
|
|
2638
2584
|
const result = new Map();
|
|
2639
2585
|
x.forEach((value, key) => {
|
|
2640
|
-
result.set(key, value.invert(event.offsetX));
|
|
2586
|
+
result.set(key, value.scale.invert(event.offsetX));
|
|
2641
2587
|
});
|
|
2642
2588
|
this.pointerMove.emit({
|
|
2643
2589
|
event: event,
|
|
@@ -2689,6 +2635,11 @@ class ChartComponent {
|
|
|
2689
2635
|
.subscribe((_) => {
|
|
2690
2636
|
this.annotationMove.emit(_);
|
|
2691
2637
|
});
|
|
2638
|
+
this.chartService.zoomInstance
|
|
2639
|
+
.pipe(takeWhile(() => this._alive))
|
|
2640
|
+
.subscribe((_) => {
|
|
2641
|
+
this.zoomServiceInstance.emit(_);
|
|
2642
|
+
});
|
|
2692
2643
|
}
|
|
2693
2644
|
ngAfterViewInit() {
|
|
2694
2645
|
}
|
|
@@ -2700,7 +2651,7 @@ class ChartComponent {
|
|
|
2700
2651
|
}
|
|
2701
2652
|
}
|
|
2702
2653
|
ChartComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.2", ngImport: i0, type: ChartComponent, deps: [{ token: ChartService }, { token: ZoomService }, { token: ScaleService }], target: i0.ɵɵFactoryTarget.Component });
|
|
2703
|
-
ChartComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.0.2", type: ChartComponent, selector: "teta-svg-chart", inputs: { config: "config" }, outputs: { pointerMove: "pointerMove", plotBandsMove: "plotBandsMove", plotBandClick: "plotBandClick", plotBandContextMenu: "plotBandContextMenu", plotLinesMove: "plotLinesMove", pointMove: "pointMove", chartClick: "chartClick", chartContextMenu: "chartContextMenu", annotationContextMenu: "annotationContextMenu", annotationClick: "annotationClick", annotationMove: "annotationMove" }, providers: [ChartService, ZoomService, ScaleService, BrushService], usesOnChanges: true, ngImport: i0, template: "<ng-container *ngIf=\"{\n hasSeriesData: hasSeriesData | async,\n svcConfig: svcConfig | async\n} as data\">\n <ng-container *ngIf=\"data.hasSeriesData === true else noData\">\n <div class=\"column column_auto\">\n <teta-chart-container class=\"chart-container position-relative\"></teta-chart-container>\n </div>\n <teta-legend *ngIf=\"data.svcConfig.legend?.enable === true\" [series]=\"data.svcConfig.series\"></teta-legend>\n </ng-container>\n</ng-container>\n<ng-template #noData>\n <div class=\"column column_auto align-center justify-content-center\">\n <span class=\"font-body-3 color-text-40\">\u0414\u0430\u043D\u043D\u044B\u0435 \u043E\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u044E\u0442</span>\n </div>\n</ng-template>\n", styles: [":host{position:relative;display:flex;flex-direction:column;height:100%;width:100%}\n"], dependencies: [{ kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: ChartContainerComponent, selector: "teta-chart-container" }, { kind: "component", type: LegendComponent, selector: "teta-legend", inputs: ["series"] }, { kind: "pipe", type: i4.AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
2654
|
+
ChartComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.0.2", type: ChartComponent, selector: "teta-svg-chart", inputs: { config: "config" }, outputs: { pointerMove: "pointerMove", plotBandsMove: "plotBandsMove", plotBandClick: "plotBandClick", plotBandContextMenu: "plotBandContextMenu", plotLinesMove: "plotLinesMove", pointMove: "pointMove", chartClick: "chartClick", chartContextMenu: "chartContextMenu", annotationContextMenu: "annotationContextMenu", annotationClick: "annotationClick", annotationMove: "annotationMove", zoomServiceInstance: "zoomServiceInstance" }, providers: [ChartService, ZoomService, ScaleService, BrushService], usesOnChanges: true, ngImport: i0, template: "<ng-container *ngIf=\"{\n hasSeriesData: hasSeriesData | async,\n svcConfig: svcConfig | async\n} as data\">\n <ng-container *ngIf=\"data.hasSeriesData === true else noData\">\n <div class=\"column column_auto\">\n <teta-chart-container class=\"chart-container position-relative\"></teta-chart-container>\n </div>\n <teta-legend *ngIf=\"data.svcConfig.legend?.enable === true\" [series]=\"data.svcConfig.series\"></teta-legend>\n </ng-container>\n</ng-container>\n<ng-template #noData>\n <div class=\"column column_auto align-center justify-content-center\">\n <span class=\"font-body-3 color-text-40\">\u0414\u0430\u043D\u043D\u044B\u0435 \u043E\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u044E\u0442</span>\n </div>\n</ng-template>\n", styles: [":host{position:relative;display:flex;flex-direction:column;height:100%;width:100%}\n"], dependencies: [{ kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: ChartContainerComponent, selector: "teta-chart-container" }, { kind: "component", type: LegendComponent, selector: "teta-legend", inputs: ["series"] }, { kind: "pipe", type: i4.AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
2704
2655
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.2", ngImport: i0, type: ChartComponent, decorators: [{
|
|
2705
2656
|
type: Component,
|
|
2706
2657
|
args: [{ selector: 'teta-svg-chart', providers: [ChartService, ZoomService, ScaleService, BrushService], changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-container *ngIf=\"{\n hasSeriesData: hasSeriesData | async,\n svcConfig: svcConfig | async\n} as data\">\n <ng-container *ngIf=\"data.hasSeriesData === true else noData\">\n <div class=\"column column_auto\">\n <teta-chart-container class=\"chart-container position-relative\"></teta-chart-container>\n </div>\n <teta-legend *ngIf=\"data.svcConfig.legend?.enable === true\" [series]=\"data.svcConfig.series\"></teta-legend>\n </ng-container>\n</ng-container>\n<ng-template #noData>\n <div class=\"column column_auto align-center justify-content-center\">\n <span class=\"font-body-3 color-text-40\">\u0414\u0430\u043D\u043D\u044B\u0435 \u043E\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u044E\u0442</span>\n </div>\n</ng-template>\n", styles: [":host{position:relative;display:flex;flex-direction:column;height:100%;width:100%}\n"] }]
|
|
@@ -2726,6 +2677,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.2", ngImpor
|
|
|
2726
2677
|
type: Output
|
|
2727
2678
|
}], annotationMove: [{
|
|
2728
2679
|
type: Output
|
|
2680
|
+
}], zoomServiceInstance: [{
|
|
2681
|
+
type: Output
|
|
2729
2682
|
}], config: [{
|
|
2730
2683
|
type: Input
|
|
2731
2684
|
}] } });
|