@tetacom/svg-charts 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (216) hide show
  1. package/.browserslistrc +16 -0
  2. package/README.md +24 -0
  3. package/dist/README.md +24 -0
  4. package/dist/chart/base/series-base.component.d.ts +22 -0
  5. package/dist/chart/chart/chart.component.d.ts +29 -0
  6. package/dist/chart/chart-container/chart-container.component.d.ts +42 -0
  7. package/dist/chart/chart-container/gridlines/gridlines.component.d.ts +23 -0
  8. package/dist/chart/chart-container/plotband/plotband.component.d.ts +33 -0
  9. package/dist/chart/chart-container/plotline/plotline.component.d.ts +30 -0
  10. package/dist/chart/chart-container/series/bar/bar-series.component.d.ts +25 -0
  11. package/dist/chart/chart-container/series/line/line-series.component.d.ts +28 -0
  12. package/dist/chart/chart-container/series-host/series-host.component.d.ts +20 -0
  13. package/dist/chart/chart-container/tooltip/tooltip.component.d.ts +29 -0
  14. package/dist/chart/chart-container/x-axis/x-axis.component.d.ts +23 -0
  15. package/dist/chart/chart-container/y-axis/y-axis.component.d.ts +24 -0
  16. package/dist/chart/chart.module.d.ts +22 -0
  17. package/dist/chart/core/axis/axis.d.ts +54 -0
  18. package/dist/chart/core/axis/builders/axis-size-builder.d.ts +8 -0
  19. package/dist/chart/core/axis/builders/extremes-builder.d.ts +7 -0
  20. package/dist/chart/core/axis/builders/public-api.d.ts +2 -0
  21. package/dist/chart/core/utils/generate-ticks.d.ts +1 -0
  22. package/dist/chart/core/utils/get-text-width.d.ts +1 -0
  23. package/dist/chart/core/utils/public-api.d.ts +2 -0
  24. package/dist/chart/directives/brushable.directive.d.ts +17 -0
  25. package/dist/chart/directives/zoomable.directive.d.ts +20 -0
  26. package/dist/chart/legend/legend.component.d.ts +14 -0
  27. package/dist/chart/model/axis-options.d.ts +17 -0
  28. package/dist/chart/model/base-point.d.ts +9 -0
  29. package/dist/chart/model/chart-bounds.d.ts +12 -0
  30. package/dist/chart/model/enum/axis-orientation.d.ts +4 -0
  31. package/dist/chart/model/enum/axis-type.d.ts +7 -0
  32. package/dist/chart/model/enum/brush-type.d.ts +5 -0
  33. package/dist/chart/model/enum/drag-point-type.d.ts +5 -0
  34. package/dist/chart/model/enum/series-type.d.ts +4 -0
  35. package/dist/chart/model/enum/tooltip-tracking.d.ts +4 -0
  36. package/dist/chart/model/enum/zoom-type.d.ts +5 -0
  37. package/dist/chart/model/i-broadcast-message.d.ts +5 -0
  38. package/dist/chart/model/i-builder.d.ts +3 -0
  39. package/dist/chart/model/i-chart-config.d.ts +32 -0
  40. package/dist/chart/model/i-chart-event.d.ts +4 -0
  41. package/dist/chart/model/i-display-tooltip.d.ts +6 -0
  42. package/dist/chart/model/i-point-move.d.ts +6 -0
  43. package/dist/chart/model/marker-options.d.ts +7 -0
  44. package/dist/chart/model/plotband.d.ts +31 -0
  45. package/dist/chart/model/plotline.d.ts +19 -0
  46. package/dist/chart/model/series.d.ts +17 -0
  47. package/dist/chart/model/svg-attributes.d.ts +14 -0
  48. package/dist/chart/model/tooltip-options.d.ts +8 -0
  49. package/dist/chart/service/axes.service.d.ts +11 -0
  50. package/dist/chart/service/broadcast.service.d.ts +11 -0
  51. package/dist/chart/service/brush.service.d.ts +17 -0
  52. package/dist/chart/service/chart.service.d.ts +38 -0
  53. package/dist/chart/service/scale.service.d.ts +14 -0
  54. package/dist/chart/service/zoom.service.d.ts +25 -0
  55. package/dist/esm2020/chart/base/series-base.component.mjs +34 -0
  56. package/dist/esm2020/chart/chart/chart.component.mjs +73 -0
  57. package/dist/esm2020/chart/chart-container/chart-container.component.mjs +151 -0
  58. package/dist/esm2020/chart/chart-container/gridlines/gridlines.component.mjs +41 -0
  59. package/dist/esm2020/chart/chart-container/plotband/plotband.component.mjs +139 -0
  60. package/dist/esm2020/chart/chart-container/plotline/plotline.component.mjs +79 -0
  61. package/dist/esm2020/chart/chart-container/series/bar/bar-series.component.mjs +48 -0
  62. package/dist/esm2020/chart/chart-container/series/line/line-series.component.mjs +148 -0
  63. package/dist/esm2020/chart/chart-container/series-host/series-host.component.mjs +59 -0
  64. package/dist/esm2020/chart/chart-container/tooltip/tooltip.component.mjs +81 -0
  65. package/dist/esm2020/chart/chart-container/x-axis/x-axis.component.mjs +56 -0
  66. package/dist/esm2020/chart/chart-container/y-axis/y-axis.component.mjs +63 -0
  67. package/dist/esm2020/chart/chart.module.mjs +62 -0
  68. package/dist/esm2020/chart/core/axis/axis.mjs +96 -0
  69. package/dist/esm2020/chart/core/axis/builders/axis-size-builder.mjs +24 -0
  70. package/dist/esm2020/chart/core/axis/builders/extremes-builder.mjs +32 -0
  71. package/dist/esm2020/chart/core/axis/builders/public-api.mjs +3 -0
  72. package/dist/esm2020/chart/core/utils/generate-ticks.mjs +11 -0
  73. package/dist/esm2020/chart/core/utils/get-text-width.mjs +6 -0
  74. package/dist/esm2020/chart/core/utils/public-api.mjs +3 -0
  75. package/dist/esm2020/chart/directives/brushable.directive.mjs +28 -0
  76. package/dist/esm2020/chart/directives/zoomable.directive.mjs +37 -0
  77. package/dist/esm2020/chart/legend/legend.component.mjs +30 -0
  78. package/dist/esm2020/chart/model/axis-options.mjs +2 -0
  79. package/dist/esm2020/chart/model/base-point.mjs +2 -0
  80. package/dist/esm2020/chart/model/chart-bounds.mjs +13 -0
  81. package/dist/esm2020/chart/model/enum/axis-orientation.mjs +6 -0
  82. package/dist/esm2020/chart/model/enum/axis-type.mjs +9 -0
  83. package/dist/esm2020/chart/model/enum/brush-type.mjs +7 -0
  84. package/dist/esm2020/chart/model/enum/drag-point-type.mjs +7 -0
  85. package/dist/esm2020/chart/model/enum/series-type.mjs +6 -0
  86. package/dist/esm2020/chart/model/enum/tooltip-tracking.mjs +6 -0
  87. package/dist/esm2020/chart/model/enum/zoom-type.mjs +7 -0
  88. package/dist/esm2020/chart/model/i-broadcast-message.mjs +2 -0
  89. package/dist/esm2020/chart/model/i-builder.mjs +2 -0
  90. package/dist/esm2020/chart/model/i-chart-config.mjs +2 -0
  91. package/dist/esm2020/chart/model/i-chart-event.mjs +2 -0
  92. package/dist/esm2020/chart/model/i-display-tooltip.mjs +2 -0
  93. package/dist/esm2020/chart/model/i-point-move.mjs +2 -0
  94. package/dist/esm2020/chart/model/marker-options.mjs +2 -0
  95. package/dist/esm2020/chart/model/plotband.mjs +16 -0
  96. package/dist/esm2020/chart/model/plotline.mjs +12 -0
  97. package/dist/esm2020/chart/model/series.mjs +2 -0
  98. package/dist/esm2020/chart/model/svg-attributes.mjs +2 -0
  99. package/dist/esm2020/chart/model/tooltip-options.mjs +2 -0
  100. package/dist/esm2020/chart/service/axes.service.mjs +29 -0
  101. package/dist/esm2020/chart/service/broadcast.service.mjs +25 -0
  102. package/dist/esm2020/chart/service/brush.service.mjs +67 -0
  103. package/dist/esm2020/chart/service/chart.service.mjs +76 -0
  104. package/dist/esm2020/chart/service/scale.service.mjs +64 -0
  105. package/dist/esm2020/chart/service/zoom.service.mjs +117 -0
  106. package/dist/esm2020/public-api.mjs +7 -0
  107. package/dist/esm2020/tetacom-svg-charts.mjs +5 -0
  108. package/dist/fesm2015/tetacom-svg-charts.mjs +1589 -0
  109. package/dist/fesm2015/tetacom-svg-charts.mjs.map +1 -0
  110. package/dist/fesm2020/tetacom-svg-charts.mjs +1575 -0
  111. package/dist/fesm2020/tetacom-svg-charts.mjs.map +1 -0
  112. package/dist/package.json +35 -0
  113. package/dist/public-api.d.ts +3 -0
  114. package/dist/tetacom-svg-charts.d.ts +5 -0
  115. package/karma.conf.js +44 -0
  116. package/ng-package.json +7 -0
  117. package/package.json +15 -0
  118. package/src/chart/Chart.stories.ts +397 -0
  119. package/src/chart/base/series-base.component.ts +41 -0
  120. package/src/chart/chart/chart.component.html +5 -0
  121. package/src/chart/chart/chart.component.scss +6 -0
  122. package/src/chart/chart/chart.component.spec.ts +25 -0
  123. package/src/chart/chart/chart.component.ts +97 -0
  124. package/src/chart/chart-container/chart-container.component.html +78 -0
  125. package/src/chart/chart-container/chart-container.component.scss +15 -0
  126. package/src/chart/chart-container/chart-container.component.spec.ts +25 -0
  127. package/src/chart/chart-container/chart-container.component.ts +242 -0
  128. package/src/chart/chart-container/gridlines/gridlines.component.html +7 -0
  129. package/src/chart/chart-container/gridlines/gridlines.component.scss +8 -0
  130. package/src/chart/chart-container/gridlines/gridlines.component.spec.ts +25 -0
  131. package/src/chart/chart-container/gridlines/gridlines.component.ts +55 -0
  132. package/src/chart/chart-container/plotband/plotband.component.html +58 -0
  133. package/src/chart/chart-container/plotband/plotband.component.scss +13 -0
  134. package/src/chart/chart-container/plotband/plotband.component.spec.ts +25 -0
  135. package/src/chart/chart-container/plotband/plotband.component.ts +206 -0
  136. package/src/chart/chart-container/plotline/plotline.component.html +22 -0
  137. package/src/chart/chart-container/plotline/plotline.component.scss +6 -0
  138. package/src/chart/chart-container/plotline/plotline.component.spec.ts +25 -0
  139. package/src/chart/chart-container/plotline/plotline.component.ts +113 -0
  140. package/src/chart/chart-container/series/bar/bar-series.component.html +3 -0
  141. package/src/chart/chart-container/series/bar/bar-series.component.scss +0 -0
  142. package/src/chart/chart-container/series/bar/bar-series.component.ts +71 -0
  143. package/src/chart/chart-container/series/line/line-series.component.html +38 -0
  144. package/src/chart/chart-container/series/line/line-series.component.scss +9 -0
  145. package/src/chart/chart-container/series/line/line-series.component.spec.ts +25 -0
  146. package/src/chart/chart-container/series/line/line-series.component.ts +245 -0
  147. package/src/chart/chart-container/series-host/series-host.component.ts +80 -0
  148. package/src/chart/chart-container/tooltip/tooltip.component.html +14 -0
  149. package/src/chart/chart-container/tooltip/tooltip.component.scss +7 -0
  150. package/src/chart/chart-container/tooltip/tooltip.component.spec.ts +25 -0
  151. package/src/chart/chart-container/tooltip/tooltip.component.ts +134 -0
  152. package/src/chart/chart-container/x-axis/x-axis.component.html +1 -0
  153. package/src/chart/chart-container/x-axis/x-axis.component.scss +3 -0
  154. package/src/chart/chart-container/x-axis/x-axis.component.spec.ts +25 -0
  155. package/src/chart/chart-container/x-axis/x-axis.component.ts +80 -0
  156. package/src/chart/chart-container/y-axis/y-axis.component.html +4 -0
  157. package/src/chart/chart-container/y-axis/y-axis.component.scss +13 -0
  158. package/src/chart/chart-container/y-axis/y-axis.component.spec.ts +25 -0
  159. package/src/chart/chart-container/y-axis/y-axis.component.ts +90 -0
  160. package/src/chart/chart.module.ts +40 -0
  161. package/src/chart/core/axis/axis.ts +132 -0
  162. package/src/chart/core/axis/builders/axis-size-builder.ts +37 -0
  163. package/src/chart/core/axis/builders/extremes-builder.ts +45 -0
  164. package/src/chart/core/axis/builders/public-api.ts +2 -0
  165. package/src/chart/core/utils/generate-ticks.ts +14 -0
  166. package/src/chart/core/utils/get-text-width.ts +10 -0
  167. package/src/chart/core/utils/public-api.ts +2 -0
  168. package/src/chart/default/default-chart-config.ts +12 -0
  169. package/src/chart/directives/brushable.directive.ts +30 -0
  170. package/src/chart/directives/zoomable.directive.ts +31 -0
  171. package/src/chart/legend/legend.component.html +6 -0
  172. package/src/chart/legend/legend.component.scss +20 -0
  173. package/src/chart/legend/legend.component.spec.ts +25 -0
  174. package/src/chart/legend/legend.component.ts +35 -0
  175. package/src/chart/model/axis-options.ts +18 -0
  176. package/src/chart/model/base-point.ts +10 -0
  177. package/src/chart/model/chart-bounds.ts +18 -0
  178. package/src/chart/model/enum/axis-orientation.ts +4 -0
  179. package/src/chart/model/enum/axis-type.ts +7 -0
  180. package/src/chart/model/enum/brush-type.ts +5 -0
  181. package/src/chart/model/enum/drag-point-type.ts +5 -0
  182. package/src/chart/model/enum/public-api.ts +7 -0
  183. package/src/chart/model/enum/series-type.ts +4 -0
  184. package/src/chart/model/enum/tooltip-tracking.ts +4 -0
  185. package/src/chart/model/enum/zoom-type.ts +5 -0
  186. package/src/chart/model/i-broadcast-message.ts +5 -0
  187. package/src/chart/model/i-builder.ts +3 -0
  188. package/src/chart/model/i-chart-config.ts +33 -0
  189. package/src/chart/model/i-chart-event.ts +4 -0
  190. package/src/chart/model/i-display-tooltip.ts +7 -0
  191. package/src/chart/model/i-drag-event.ts +5 -0
  192. package/src/chart/model/i-point-move.ts +7 -0
  193. package/src/chart/model/marker-options.ts +8 -0
  194. package/src/chart/model/plotband.ts +45 -0
  195. package/src/chart/model/plotline.ts +29 -0
  196. package/src/chart/model/public-api.ts +0 -0
  197. package/src/chart/model/series.ts +18 -0
  198. package/src/chart/model/svg-attributes.ts +14 -0
  199. package/src/chart/model/tooltip-options.ts +37 -0
  200. package/src/chart/service/axes.service.spec.ts +16 -0
  201. package/src/chart/service/axes.service.ts +27 -0
  202. package/src/chart/service/broadcast.service.spec.ts +16 -0
  203. package/src/chart/service/broadcast.service.ts +24 -0
  204. package/src/chart/service/brush.service.spec.ts +16 -0
  205. package/src/chart/service/brush.service.ts +87 -0
  206. package/src/chart/service/chart.service.spec.ts +16 -0
  207. package/src/chart/service/chart.service.ts +100 -0
  208. package/src/chart/service/scale.service.spec.ts +16 -0
  209. package/src/chart/service/scale.service.ts +74 -0
  210. package/src/chart/service/zoom.service.spec.ts +16 -0
  211. package/src/chart/service/zoom.service.ts +153 -0
  212. package/src/public-api.ts +7 -0
  213. package/src/test.ts +27 -0
  214. package/tsconfig.lib.json +15 -0
  215. package/tsconfig.lib.prod.json +10 -0
  216. package/tsconfig.spec.json +17 -0
@@ -0,0 +1,87 @@
1
+ import { ElementRef, Injectable } from '@angular/core';
2
+ import { BrushType } from '../model/enum/brush-type';
3
+ import * as d3 from 'd3';
4
+ import { map, Subscription } from 'rxjs';
5
+ import { BroadcastService } from './broadcast.service';
6
+ import { IChartConfig } from '../model/i-chart-config';
7
+ import { ScaleService } from './scale.service';
8
+
9
+ @Injectable({
10
+ providedIn: 'root',
11
+ })
12
+ export class BrushService {
13
+ broadcastSubscribtion: Subscription;
14
+
15
+ private brushMap = new Map<BrushType, d3.BrushBehavior<any>>()
16
+ .set(BrushType.x, d3.brushX())
17
+ .set(BrushType.y, d3.brushY());
18
+
19
+ private scaleMap = new Map<BrushType, string>()
20
+ .set(BrushType.x, 'xScales')
21
+ .set(BrushType.y, 'yScales');
22
+
23
+ constructor(
24
+ private broadcastService: BroadcastService,
25
+ private scaleService: ScaleService
26
+ ) {}
27
+
28
+ applyBrush(svgElement: ElementRef, config: IChartConfig, size: DOMRect) {
29
+ this.broadcastSubscribtion?.unsubscribe();
30
+
31
+ if (config.brush?.enable) {
32
+ const s = this.scaleService[
33
+ this.scaleMap.get(config?.brush?.type ?? BrushType.x)
34
+ ].get(config?.brush?.axisIndex ?? 0);
35
+
36
+ const brush = this.brushMap.get(config?.brush?.type ?? BrushType.x);
37
+
38
+ const container = d3.select(svgElement.nativeElement);
39
+
40
+ const brushBehavior = brush.on(
41
+ 'start brush end',
42
+ (_: d3.D3BrushEvent<any>) => {
43
+ if (_.sourceEvent) {
44
+ const [from, to] = _.selection as number[];
45
+
46
+ if (to - from < 5) {
47
+ container.call(brush.move, [from, to]);
48
+ return;
49
+ }
50
+
51
+ this.broadcastService.broadcast({
52
+ channel: config?.zoom?.syncChannel,
53
+ message: {
54
+ ..._,
55
+ selection: [s.invert(from), s.invert(to)],
56
+ brushType: config?.brush?.type ?? BrushType.x,
57
+ },
58
+ });
59
+ }
60
+ }
61
+ );
62
+
63
+ container.call(brushBehavior);
64
+
65
+ setTimeout(() => {
66
+ container.call(brush.move, s.domain().map(s), {});
67
+ });
68
+
69
+ this.broadcastSubscribtion = this.broadcastService
70
+ .subscribeToChannel(config?.zoom?.syncChannel)
71
+ .pipe(
72
+ map((_) => {
73
+ if (_.message?.transform) {
74
+ const s = this.scaleService[
75
+ this.scaleMap.get(config?.brush?.type ?? BrushType.x)
76
+ ].get(config?.brush?.axisIndex ?? 0);
77
+
78
+ const domain = _.domain;
79
+
80
+ container.call(brush.move, [s(domain[0]), s(domain[1])]);
81
+ }
82
+ })
83
+ )
84
+ .subscribe();
85
+ }
86
+ }
87
+ }
@@ -0,0 +1,16 @@
1
+ import { TestBed } from '@angular/core/testing';
2
+
3
+ import { ChartService } from './chart.service';
4
+
5
+ describe('ChartService', () => {
6
+ let service: ChartService;
7
+
8
+ beforeEach(() => {
9
+ TestBed.configureTestingModule({});
10
+ service = TestBed.inject(ChartService);
11
+ });
12
+
13
+ it('should be created', () => {
14
+ expect(service).toBeTruthy();
15
+ });
16
+ });
@@ -0,0 +1,100 @@
1
+ import { Injectable } from '@angular/core';
2
+ import { IChartConfig } from '../model/i-chart-config';
3
+ import { AxesService } from './axes.service';
4
+ import { map, Observable, Subject } from 'rxjs';
5
+ import { ScaleService } from './scale.service';
6
+ import { IChartEvent } from '../model/i-chart-event';
7
+ import { IDisplayTooltip } from '../model/i-display-tooltip';
8
+ import { Plotband } from '../model/plotband';
9
+ import { PlotLine } from '../model/plotline';
10
+ import { IPointMove } from '../model/i-point-move';
11
+
12
+ @Injectable({
13
+ providedIn: 'root',
14
+ })
15
+ export class ChartService {
16
+ public size: Observable<DOMRect>;
17
+ public pointerMove: Observable<any>;
18
+ public tooltips: Observable<IDisplayTooltip>;
19
+ public plotbandMove: Observable<IChartEvent<Plotband>>;
20
+ public plotlineMove: Observable<IChartEvent<PlotLine>>;
21
+ public pointMove: Observable<IChartEvent<IPointMove>>;
22
+
23
+ private size$ = new Subject<DOMRect>();
24
+ private pointerMove$ = new Subject<any>();
25
+ private tooltips$ = new Subject<IDisplayTooltip>();
26
+ private plotbandMove$ = new Subject<IChartEvent<Plotband>>();
27
+ private plotlineMove$ = new Subject<IChartEvent<PlotLine>>();
28
+ private pointMove$ = new Subject<IChartEvent<IPointMove>>();
29
+
30
+ private _config: IChartConfig;
31
+
32
+ constructor(
33
+ private axesService: AxesService,
34
+ private scaleService: ScaleService
35
+ ) {
36
+ this.size = this.size$.asObservable();
37
+ this.pointerMove = this.pointerMove$.asObservable();
38
+ this.tooltips = this.tooltips$.asObservable();
39
+ this.plotbandMove = this.plotbandMove$.asObservable();
40
+ this.plotlineMove = this.plotlineMove$.asObservable();
41
+ this.pointMove = this.pointMove$.asObservable();
42
+
43
+ this.size
44
+ .pipe(
45
+ map((size) => {
46
+ this.scaleService.createScales(size, this._config);
47
+ })
48
+ )
49
+ .subscribe();
50
+ }
51
+
52
+ public init(config: IChartConfig) {
53
+ this._config = config;
54
+
55
+ if (config.inverted) {
56
+ this._config.series = this._config?.series?.map((serie) => {
57
+ return {
58
+ ...serie,
59
+ data: serie?.data?.map((point) => {
60
+ return {
61
+ ...point,
62
+ x: point?.y,
63
+ y: point?.x,
64
+ };
65
+ }),
66
+ };
67
+ });
68
+ }
69
+
70
+ this.axesService.init(this._config);
71
+ }
72
+
73
+ public setSize(size: DOMRect) {
74
+ this.size$.next(size);
75
+ }
76
+
77
+ public setPointerMove(event: any) {
78
+ this.pointerMove$.next({ event });
79
+ }
80
+
81
+ public setTooltip(tooltip: IDisplayTooltip) {
82
+ this.tooltips$.next(tooltip);
83
+ }
84
+
85
+ public emitPlotband(event: IChartEvent<Plotband>) {
86
+ this.plotbandMove$.next(event);
87
+ }
88
+
89
+ public emitPlotline(event: IChartEvent<PlotLine>) {
90
+ this.plotlineMove$.next(event);
91
+ }
92
+
93
+ public emitPoint(event: IChartEvent<IPointMove>) {
94
+ this.pointMove$.next(event);
95
+ }
96
+
97
+ get config(): IChartConfig {
98
+ return this._config;
99
+ }
100
+ }
@@ -0,0 +1,16 @@
1
+ import { TestBed } from '@angular/core/testing';
2
+
3
+ import { ScaleService } from './scale.service';
4
+
5
+ describe('ScaleService', () => {
6
+ let service: ScaleService;
7
+
8
+ beforeEach(() => {
9
+ TestBed.configureTestingModule({});
10
+ service = TestBed.inject(ScaleService);
11
+ });
12
+
13
+ it('should be created', () => {
14
+ expect(service).toBeTruthy();
15
+ });
16
+ });
@@ -0,0 +1,74 @@
1
+ import { Injectable } from '@angular/core';
2
+
3
+ import { AxesService } from './axes.service';
4
+ import * as d3 from 'd3';
5
+ import { AxisType } from '../model/enum/axis-type';
6
+ import { Axis } from '../core/axis/axis';
7
+ import { AxisOrientation } from '../model/enum/axis-orientation';
8
+
9
+ import { IChartConfig } from '../model/i-chart-config';
10
+
11
+ @Injectable({
12
+ providedIn: 'root',
13
+ })
14
+ export class ScaleService {
15
+ public yScales: Map<number | string, any> = new Map<number | string, any>();
16
+ public xScales: Map<number | string, any> = new Map<number | string, any>();
17
+
18
+ private scaleMapping = new Map<AxisType, any>()
19
+ .set(AxisType.number, d3.scaleLinear)
20
+ .set(AxisType.time, d3.scaleTime)
21
+ .set(AxisType.category, d3.scaleOrdinal)
22
+ .set(AxisType.log, d3.scaleLog);
23
+
24
+ constructor(private axesService: AxesService) {}
25
+
26
+ public createScales(size: DOMRect, config?: IChartConfig) {
27
+ this.yScales.clear();
28
+ this.xScales.clear();
29
+
30
+ const topBound = [...this.axesService.xAxis.values()]
31
+ .filter((_) => _.options?.visible && _.options?.opposite)
32
+ .reduce((acc, cur) => acc + cur.selfSize, 0);
33
+
34
+ const bottomBound = [...this.axesService.xAxis.values()]
35
+ .filter((_) => _.options?.visible && _.options?.opposite !== true)
36
+ .reduce((acc, cur) => acc + cur.selfSize, 0);
37
+
38
+ const leftBound = [...this.axesService.yAxis.values()]
39
+ .filter((_) => _.options?.visible && _.options.opposite !== true)
40
+ .reduce((acc, cur) => acc + cur.selfSize, 0);
41
+
42
+ const rightBound = [...this.axesService.yAxis.values()]
43
+ .filter((_) => _.options?.visible && _.options.opposite)
44
+ .reduce((acc, cur) => acc + cur.selfSize, 0);
45
+
46
+ this.axesService.yAxis.forEach((axis: Axis) => {
47
+ const scale = this.getScale(axis).range([
48
+ 0,
49
+ size.height - topBound - bottomBound,
50
+ ]);
51
+
52
+ this.yScales.set(axis.index, scale);
53
+ });
54
+
55
+ this.axesService.xAxis.forEach((axis: Axis) => {
56
+ const scale = this.getScale(axis).range([
57
+ 0,
58
+ size.width - leftBound - rightBound,
59
+ ]);
60
+
61
+ this.xScales.set(axis.index, scale);
62
+ });
63
+ }
64
+
65
+ private getScale(axis: Axis) {
66
+ return this.scaleMapping
67
+ .get(axis.options?.type)()
68
+ .domain(
69
+ axis.orientation === AxisOrientation.y
70
+ ? [...axis.extremes].reverse()
71
+ : axis.extremes
72
+ );
73
+ }
74
+ }
@@ -0,0 +1,16 @@
1
+ import { TestBed } from '@angular/core/testing';
2
+
3
+ import { ZoomService } from './zoom.service';
4
+
5
+ describe('ZoomService', () => {
6
+ let service: ZoomService;
7
+
8
+ beforeEach(() => {
9
+ TestBed.configureTestingModule({});
10
+ service = TestBed.inject(ZoomService);
11
+ });
12
+
13
+ it('should be created', () => {
14
+ expect(service).toBeTruthy();
15
+ });
16
+ });
@@ -0,0 +1,153 @@
1
+ import { ElementRef, Injectable } from '@angular/core';
2
+ import * as d3 from 'd3';
3
+ import { D3ZoomEvent, zoomIdentity } from 'd3';
4
+ import { ScaleService } from './scale.service';
5
+ import { map, merge, Observable, of, Subject, Subscription } from 'rxjs';
6
+ import { IChartEvent } from '../model/i-chart-event';
7
+ import { ZoomType } from '../model/enum/zoom-type';
8
+ import { IChartConfig } from '../model/i-chart-config';
9
+ import { BroadcastService } from './broadcast.service';
10
+ import { ChartService } from './chart.service';
11
+ import { BrushType } from '../model/enum/brush-type';
12
+
13
+ @Injectable({
14
+ providedIn: 'root',
15
+ })
16
+ export class ZoomService {
17
+ zoomed: Observable<any>;
18
+ private zoomed$ = new Subject<any>();
19
+
20
+ broadcastSubscribtion: Subscription;
21
+
22
+ private x = new Map<number | string, any>();
23
+ private y = new Map<number | string, any>();
24
+
25
+ private zoom;
26
+ private svg;
27
+ private initialZoom = zoomIdentity;
28
+
29
+ constructor(
30
+ private scaleService: ScaleService,
31
+ private broadcastService: BroadcastService,
32
+ private chartService: ChartService
33
+ ) {
34
+ this.zoomed = this.zoomed$.asObservable();
35
+
36
+ merge(of(1), this.chartService.size)
37
+ .pipe(
38
+ map((_) => {
39
+ this.x = new Map(this.scaleService.xScales);
40
+ this.y = new Map(this.scaleService.yScales);
41
+
42
+ if (this.svg) {
43
+ const currentTransform = d3.zoomTransform(this.svg.node());
44
+ this.setZoom(currentTransform);
45
+ }
46
+ })
47
+ )
48
+ .subscribe();
49
+ }
50
+
51
+ applyZoom(svgElement: ElementRef, config: IChartConfig, size: DOMRect) {
52
+ this.broadcastSubscribtion?.unsubscribe();
53
+
54
+ this.svg = d3.select(svgElement.nativeElement);
55
+
56
+ const zoomType = config?.zoom?.type;
57
+ const enable = config?.zoom?.enable;
58
+
59
+ const zoomed = (event: D3ZoomEvent<any, any>) => {
60
+ const { transform } = event;
61
+
62
+ if (zoomType === ZoomType.x || zoomType === ZoomType.xy) {
63
+ for (let [index, scale] of this.x.entries()) {
64
+ this.scaleService.xScales.set(index, transform.rescaleX(scale));
65
+ }
66
+ }
67
+
68
+ if (zoomType === ZoomType.y || zoomType === ZoomType.xy) {
69
+ for (let [index, scale] of this.y.entries()) {
70
+ this.scaleService.yScales.set(index, transform.rescaleY(scale));
71
+ }
72
+ }
73
+
74
+ if (enable) {
75
+ this.zoomed$.next({ event });
76
+
77
+ if (event.sourceEvent) {
78
+ this.broadcastService.broadcast({
79
+ channel: config?.zoom?.syncChannel,
80
+ message: event,
81
+ domain: this.scaleService[
82
+ config?.zoom?.type === ZoomType.x ? 'xScales' : 'yScales'
83
+ ]
84
+ .get(config.brush?.axisIndex ?? 0)
85
+ .domain(),
86
+ });
87
+ }
88
+ }
89
+ };
90
+
91
+ if (enable) {
92
+ this.zoom = d3
93
+ .zoom()
94
+ .scaleExtent([1, Infinity])
95
+ .extent([
96
+ [0, 0],
97
+ [size.width, size.height],
98
+ ]);
99
+
100
+ this.zoom.on('start zoom end', zoomed);
101
+ this.svg.call(this.zoom);
102
+ this.svg.call(this.zoom.transform, this.initialZoom);
103
+
104
+ const sc =
105
+ config?.zoom?.type === ZoomType.x
106
+ ? this.x.get(config.brush?.axisIndex ?? 0)
107
+ : this.y.get(config.brush?.axisIndex ?? 0);
108
+
109
+ this.broadcastSubscribtion = this.broadcastService
110
+ .subscribeToChannel(config?.zoom?.syncChannel)
111
+ .pipe(
112
+ map((_) => {
113
+ const currentTransform = d3.zoomTransform(this.svg.node());
114
+
115
+ const { message } = _;
116
+ if (currentTransform !== message?.transform) {
117
+ if (message.selection) {
118
+ const s = message.selection;
119
+
120
+ const domain = sc.domain();
121
+
122
+ const scale = (domain[1] - domain[0]) / (s[1] - s[0]);
123
+
124
+ let transform = zoomIdentity.scale(scale);
125
+
126
+ if (message?.brushType === BrushType.x) {
127
+ transform = transform.translate(-sc(s[0]), 0);
128
+ }
129
+ if (message?.brushType === BrushType.y) {
130
+ transform = transform.translate(0, -sc(s[0]));
131
+ }
132
+
133
+ this.setZoom(transform);
134
+
135
+ return;
136
+ }
137
+
138
+ this.setZoom(message?.transform);
139
+ }
140
+ })
141
+ )
142
+ .subscribe();
143
+ }
144
+ }
145
+
146
+ setZoom(transform: any) {
147
+ // requestAnimationFrame(() => {
148
+ //
149
+ // });
150
+
151
+ this.svg?.call(this.zoom.transform, transform);
152
+ }
153
+ }
@@ -0,0 +1,7 @@
1
+ /*
2
+ * Public API Surface of chart
3
+ */
4
+
5
+ export * from './chart/chart.module';
6
+ export * from './chart/service/chart.service';
7
+ export * from './chart/chart/chart.component';
package/src/test.ts ADDED
@@ -0,0 +1,27 @@
1
+ // This file is required by karma.conf.js and loads recursively all the .spec and framework files
2
+
3
+ import 'zone.js';
4
+ import 'zone.js/testing';
5
+ import { getTestBed } from '@angular/core/testing';
6
+ import {
7
+ BrowserDynamicTestingModule,
8
+ platformBrowserDynamicTesting
9
+ } from '@angular/platform-browser-dynamic/testing';
10
+
11
+ declare const require: {
12
+ context(path: string, deep?: boolean, filter?: RegExp): {
13
+ keys(): string[];
14
+ <T>(id: string): T;
15
+ };
16
+ };
17
+
18
+ // First, initialize the Angular testing environment.
19
+ getTestBed().initTestEnvironment(
20
+ BrowserDynamicTestingModule,
21
+ platformBrowserDynamicTesting(),
22
+ );
23
+
24
+ // Then we find all the tests.
25
+ const context = require.context('./', true, /\.spec\.ts$/);
26
+ // And load the modules.
27
+ context.keys().map(context);
@@ -0,0 +1,15 @@
1
+ /* To learn more about this file see: https://angular.io/config/tsconfig. */
2
+ {
3
+ "extends": "../../tsconfig.json",
4
+ "compilerOptions": {
5
+ "outDir": "../../out-tsc/lib",
6
+ "declaration": true,
7
+ "declarationMap": true,
8
+ "inlineSources": true,
9
+ "types": []
10
+ },
11
+ "exclude": [
12
+ "src/test.ts",
13
+ "**/*.spec.ts"
14
+ ]
15
+ }
@@ -0,0 +1,10 @@
1
+ /* To learn more about this file see: https://angular.io/config/tsconfig. */
2
+ {
3
+ "extends": "./tsconfig.lib.json",
4
+ "compilerOptions": {
5
+ "declarationMap": false
6
+ },
7
+ "angularCompilerOptions": {
8
+ "compilationMode": "partial"
9
+ }
10
+ }
@@ -0,0 +1,17 @@
1
+ /* To learn more about this file see: https://angular.io/config/tsconfig. */
2
+ {
3
+ "extends": "../../tsconfig.json",
4
+ "compilerOptions": {
5
+ "outDir": "../../out-tsc/spec",
6
+ "types": [
7
+ "jasmine"
8
+ ]
9
+ },
10
+ "files": [
11
+ "src/test.ts"
12
+ ],
13
+ "include": [
14
+ "**/*.spec.ts",
15
+ "**/*.d.ts"
16
+ ]
17
+ }