@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,25 @@
1
+ import { ComponentFixture, TestBed } from '@angular/core/testing';
2
+
3
+ import { PlotlineComponent } from './plotline.component';
4
+
5
+ describe('PlotlineComponent', () => {
6
+ let component: PlotlineComponent;
7
+ let fixture: ComponentFixture<PlotlineComponent>;
8
+
9
+ beforeEach(async () => {
10
+ await TestBed.configureTestingModule({
11
+ declarations: [ PlotlineComponent ]
12
+ })
13
+ .compileComponents();
14
+ });
15
+
16
+ beforeEach(() => {
17
+ fixture = TestBed.createComponent(PlotlineComponent);
18
+ component = fixture.componentInstance;
19
+ fixture.detectChanges();
20
+ });
21
+
22
+ it('should create', () => {
23
+ expect(component).toBeTruthy();
24
+ });
25
+ });
@@ -0,0 +1,113 @@
1
+ import {
2
+ ChangeDetectionStrategy,
3
+ ChangeDetectorRef,
4
+ Component,
5
+ ElementRef,
6
+ Input,
7
+ OnInit,
8
+ } from '@angular/core';
9
+ import { PlotLine } from '../../model/plotline';
10
+ import { Axis } from '../../core/axis/axis';
11
+ import { AxisOrientation } from '../../model/enum/axis-orientation';
12
+ import { ZoomService } from '../../service/zoom.service';
13
+ import { ScaleService } from '../../service/scale.service';
14
+ import * as d3 from 'd3';
15
+ import { IChartEvent } from '../../model/i-chart-event';
16
+ import { Plotband } from '../../model/plotband';
17
+ import { ChartService } from '../../service/chart.service';
18
+
19
+ @Component({
20
+ selector: '[teta-plot-line]',
21
+ templateUrl: './plotline.component.html',
22
+ styleUrls: ['./plotline.component.scss'],
23
+ changeDetection: ChangeDetectionStrategy.OnPush,
24
+ })
25
+ export class PlotlineComponent implements OnInit {
26
+ @Input() plotline: PlotLine;
27
+ @Input() size: DOMRect;
28
+ @Input() axis: Axis;
29
+ orientation = AxisOrientation;
30
+
31
+ private scale: any;
32
+ private domain: number[];
33
+
34
+ constructor(
35
+ private cdr: ChangeDetectorRef,
36
+ private zoomService: ZoomService,
37
+ private scaleService: ScaleService,
38
+ private chartService: ChartService,
39
+ private element: ElementRef
40
+ ) {
41
+ this.zoomService.zoomed.subscribe(() => {
42
+ this.scale = this.scaleService[
43
+ this.axis.orientation === AxisOrientation.x ? 'xScales' : 'yScales'
44
+ ].get(this.axis.index);
45
+ this.cdr.detectChanges();
46
+ });
47
+ }
48
+
49
+ ngOnInit(): void {
50
+ this.scale = this.scaleService[
51
+ this.axis.orientation === AxisOrientation.x ? 'xScales' : 'yScales'
52
+ ].get(this.axis.index);
53
+
54
+ this.domain = this.scale.domain();
55
+
56
+ const plotlineElement = d3
57
+ .select(this.element.nativeElement)
58
+ .select('.plotline');
59
+
60
+ const grabElement = d3
61
+ .select(this.element.nativeElement)
62
+ .selectAll('.grabber');
63
+
64
+ const drag = d3
65
+ .drag()
66
+ .subject(() => {
67
+ if (this.axis.orientation === AxisOrientation.y) {
68
+ return { y: plotlineElement.attr('y1') };
69
+ }
70
+ if (this.axis.orientation === AxisOrientation.x) {
71
+ return { x: plotlineElement.attr('x1') };
72
+ }
73
+ })
74
+ .on(
75
+ 'start drag end',
76
+ (event: d3.D3DragEvent<any, PlotLine, any>, d: PlotLine) => {
77
+ d.value = this.scale.invert(
78
+ event[AxisOrientation[this.axis.orientation]]
79
+ );
80
+
81
+ this.emit({
82
+ event,
83
+ target: d,
84
+ });
85
+
86
+ this.cdr.detectChanges();
87
+ }
88
+ );
89
+
90
+ plotlineElement.datum<PlotLine>(this.plotline);
91
+ grabElement.datum<PlotLine>(this.plotline);
92
+
93
+ if (this.plotline.draggable) {
94
+ grabElement.call(drag);
95
+ }
96
+ }
97
+
98
+ emit(event: IChartEvent<PlotLine>) {
99
+ this.chartService.emitPlotline(event);
100
+ }
101
+
102
+ get value() {
103
+ return this.scale(this.plotline.value);
104
+ }
105
+
106
+ get height(): number {
107
+ return this.size.height;
108
+ }
109
+
110
+ get width(): number {
111
+ return this.size.width;
112
+ }
113
+ }
@@ -0,0 +1,3 @@
1
+ <svg:rect *ngFor="let point of series.data" [attr.y]="getY(point)" [attr.x]="getX(point)" [attr.width]="width()"
2
+ [attr.height]="height(point)"
3
+ [attr.fill]="point.color"></svg:rect>
@@ -0,0 +1,71 @@
1
+ import {
2
+ ChangeDetectionStrategy,
3
+ ChangeDetectorRef,
4
+ Component,
5
+ ElementRef,
6
+ OnChanges,
7
+ OnInit,
8
+ SimpleChanges,
9
+ } from '@angular/core';
10
+ import * as d3 from 'd3';
11
+ import { SeriesBaseComponent } from '../../../base/series-base.component';
12
+ import { BasePoint } from '../../../model/base-point';
13
+ import { ChartService } from '../../../service/chart.service';
14
+ import { ScaleService } from '../../../service/scale.service';
15
+ import { ZoomService } from '../../../service/zoom.service';
16
+
17
+ @Component({
18
+ selector: 'svg:svg[teta-bar-series]',
19
+ templateUrl: './bar-series.component.html',
20
+ styleUrls: ['./bar-series.component.scss'],
21
+ changeDetection: ChangeDetectionStrategy.OnPush,
22
+ })
23
+ export class BarSeriesComponent<T extends BasePoint>
24
+ extends SeriesBaseComponent<T>
25
+ implements OnInit, OnChanges
26
+ {
27
+ private scaleBand: d3.ScaleBand<any>;
28
+ private y: any;
29
+
30
+ constructor(
31
+ protected override svc: ChartService,
32
+ protected override cdr: ChangeDetectorRef,
33
+ protected override scaleService: ScaleService,
34
+ protected override zoomService: ZoomService,
35
+ protected override element: ElementRef
36
+ ) {
37
+ super(svc, cdr, scaleService, zoomService, element);
38
+ }
39
+
40
+ override ngOnInit(): void {
41
+ const x = this.scaleService.xScales.get(this.series.xAxisIndex);
42
+ const y = this.scaleService.yScales.get(this.series.yAxisIndex);
43
+
44
+ const domain = this.series.data?.map((_: BasePoint) => _.x);
45
+ const range = [x(domain[0]), x(domain[domain?.length - 1])];
46
+
47
+ this.scaleBand = d3.scaleBand<number>().domain(domain).range(range);
48
+
49
+ this.y = y;
50
+ }
51
+
52
+ width() {
53
+ return this.scaleBand.bandwidth();
54
+ }
55
+
56
+ height(point: BasePoint) {
57
+ return Math.abs(this.y(0) - this.y(point.y));
58
+ }
59
+
60
+ getX(point: BasePoint) {
61
+ return this.scaleBand(point.x);
62
+ }
63
+
64
+ getY(point: BasePoint) {
65
+ return this.y(point.y);
66
+ }
67
+
68
+ ngOnChanges(changes: SimpleChanges) {
69
+ console.log(changes);
70
+ }
71
+ }
@@ -0,0 +1,38 @@
1
+ <svg:path
2
+ class="line"
3
+ [attr.d]="getPath()"
4
+ [attr.stroke]="series.color"
5
+ [attr.stroke-width]="series.style?.strokeWidth"
6
+ fill="none">
7
+ </svg:path>
8
+
9
+ <ng-container *ngIf="transform | async as t">
10
+ <svg:circle
11
+ r="3"
12
+ [attr.fill]="series.color"
13
+ [attr.transform]="'translate('+ t.x +', '+ t.y +')'"
14
+ [attr.opacity]="display | async">
15
+ </svg:circle>
16
+ </ng-container>
17
+
18
+ <ng-container *ngIf="getMarkers() as markers">
19
+
20
+ <svg:circle
21
+ class="marker"
22
+ *ngFor="let point of markers"
23
+ [class.draggable-marker]="point?.marker?.draggable"
24
+ [attr.r]="point.marker.style?.radius ?? 5"
25
+ [attr.fill]="point.marker.style?.fill ?? 'transparent'"
26
+ [attr.stroke]="point.marker.style?.stroke ?? 'none'"
27
+ [attr.stroke-width]="point.marker.style?.strokeWidth"
28
+ [attr.stroke-dasharray]="point.marker.style?.strokeDasharray"
29
+ [attr.cx]="x(point.x)"
30
+ [attr.cy]="y(point.y)"
31
+ >
32
+ </svg:circle>
33
+
34
+
35
+ </ng-container>
36
+
37
+
38
+
@@ -0,0 +1,9 @@
1
+ .draggable-marker {
2
+ cursor: move;
3
+ }
4
+ .active {
5
+ stroke-opacity: 0.5;
6
+ }
7
+ .marker-grab {
8
+ opacity: 0;
9
+ }
@@ -0,0 +1,25 @@
1
+ import { ComponentFixture, TestBed } from '@angular/core/testing';
2
+
3
+ import { LineSeriesComponent } from './line-series.component';
4
+ import { BasePoint } from '../../../model/base-point';
5
+
6
+ describe('LineSeriesComponent', () => {
7
+ let component: LineSeriesComponent<BasePoint>;
8
+ let fixture: ComponentFixture<LineSeriesComponent<BasePoint>>;
9
+
10
+ beforeEach(async () => {
11
+ await TestBed.configureTestingModule({
12
+ declarations: [LineSeriesComponent],
13
+ }).compileComponents();
14
+ });
15
+
16
+ beforeEach(() => {
17
+ fixture = TestBed.createComponent(LineSeriesComponent);
18
+ component = fixture.componentInstance;
19
+ fixture.detectChanges();
20
+ });
21
+
22
+ it('should create', () => {
23
+ expect(component).toBeTruthy();
24
+ });
25
+ });
@@ -0,0 +1,245 @@
1
+ import {
2
+ AfterViewInit,
3
+ ChangeDetectionStrategy,
4
+ ChangeDetectorRef,
5
+ Component,
6
+ ElementRef,
7
+ OnInit,
8
+ } from '@angular/core';
9
+ import * as d3 from 'd3';
10
+ import { SeriesBaseComponent } from '../../../base/series-base.component';
11
+ import { ChartService } from '../../../service/chart.service';
12
+ import { BasePoint } from '../../../model/base-point';
13
+ import { ScaleService } from '../../../service/scale.service';
14
+ import { filter, map, Observable, tap } from 'rxjs';
15
+
16
+ import { ZoomService } from '../../../service/zoom.service';
17
+ import { TooltipTracking } from '../../../model/enum/tooltip-tracking';
18
+ import { DragPointType } from '../../../model/enum/drag-point-type';
19
+
20
+ @Component({
21
+ selector: 'svg:svg[teta-line-series]',
22
+ templateUrl: './line-series.component.html',
23
+ styleUrls: ['./line-series.component.scss'],
24
+ changeDetection: ChangeDetectionStrategy.OnPush,
25
+ })
26
+ export class LineSeriesComponent<T extends BasePoint>
27
+ extends SeriesBaseComponent<T>
28
+ implements OnInit, AfterViewInit
29
+ {
30
+ transform: Observable<Pick<BasePoint, 'x' | 'y'>>;
31
+ display: Observable<number>;
32
+
33
+ svgElement: SVGGeometryElement;
34
+ x: any;
35
+ y: any;
36
+
37
+ constructor(
38
+ protected override svc: ChartService,
39
+ protected override cdr: ChangeDetectorRef,
40
+ protected override scaleService: ScaleService,
41
+ protected override zoomService: ZoomService,
42
+ protected override element: ElementRef
43
+ ) {
44
+ super(svc, cdr, scaleService, zoomService, element);
45
+ }
46
+
47
+ override ngOnInit(): void {
48
+ this.display = this.zoomService.zoomed.pipe(
49
+ map(({ event }) => {
50
+ return event?.type === 'end' ? 1 : 0;
51
+ })
52
+ );
53
+
54
+ this.transform = this.svc.pointerMove.pipe(
55
+ filter(({ event }) => event),
56
+ map(({ event }) => {
57
+ return this.getTransform(event);
58
+ }),
59
+ tap((_) => this.cdr.detectChanges())
60
+ );
61
+ }
62
+
63
+ ngAfterViewInit() {
64
+ const drag = (node, event: d3.D3DragEvent<any, any, any>, d: BasePoint) => {
65
+ if (
66
+ d.marker?.dragType === DragPointType.x ||
67
+ d.marker?.dragType === DragPointType.xy
68
+ ) {
69
+ d.x = this.x.invert(event.x);
70
+ }
71
+
72
+ if (
73
+ d.marker?.dragType === DragPointType.y ||
74
+ d.marker?.dragType === DragPointType.xy
75
+ ) {
76
+ d.y = this.y.invert(event.y);
77
+ }
78
+
79
+ this.svc.emitPoint({
80
+ target: {
81
+ series: this.series,
82
+ point: d,
83
+ },
84
+ event,
85
+ });
86
+
87
+ this.cdr.detectChanges();
88
+ };
89
+
90
+ const dragMarkers = d3
91
+ .drag()
92
+ .subject(function (event, d: BasePoint) {
93
+ const node = d3.select(this);
94
+ return { x: node.attr('cx'), y: node.attr('cy') };
95
+ })
96
+ .on(
97
+ 'start drag end',
98
+ function (event: d3.D3DragEvent<any, any, any>, d: BasePoint) {
99
+ const node = d3.select(this);
100
+
101
+ drag(node, event, d);
102
+ }
103
+ );
104
+
105
+ const draggableMarkers = this.series.data?.filter(
106
+ (_) => _?.marker && _?.marker?.draggable
107
+ );
108
+
109
+ const element = d3
110
+ .select(this.element.nativeElement)
111
+ .selectAll('.draggable-marker')
112
+ .data(draggableMarkers);
113
+
114
+ element.call(dragMarkers as any);
115
+
116
+ this.svgElement = d3
117
+ .select(this.element.nativeElement)
118
+ .select('.line')
119
+ .node() as SVGGeometryElement;
120
+ }
121
+
122
+ getPath() {
123
+ this.x = this.scaleService.xScales.get(this.series.xAxisIndex);
124
+ this.y = this.scaleService.yScales.get(this.series.yAxisIndex);
125
+
126
+ const line = d3
127
+ .line<BasePoint>()
128
+ .defined((point) => point.x !== null || point.y !== null)
129
+ .x((point) => this.x(point.x))
130
+ .y((point) => this.y(point.y));
131
+
132
+ const path = line(this.series.data);
133
+
134
+ return path;
135
+ }
136
+
137
+ getMarkers() {
138
+ return this.series.data?.filter((_) => _?.marker);
139
+ }
140
+
141
+ getTransform(event: any): Pick<BasePoint, 'x' | 'y'> {
142
+ const mouse = d3.pointer(event);
143
+
144
+ const foundX = this.scaleService.xScales.get(this.series.xAxisIndex);
145
+ const foundY = this.scaleService.yScales.get(this.series.yAxisIndex);
146
+
147
+ const tooltipTracking = this.svc.config?.tooltip?.tracking;
148
+
149
+ const lineIntersection = (
150
+ p0_x,
151
+ p0_y,
152
+ p1_x,
153
+ p1_y,
154
+ p2_x,
155
+ p2_y,
156
+ p3_x,
157
+ p3_y
158
+ ) => {
159
+ const rV = {} as any;
160
+ let s1_x, s1_y, s2_x, s2_y;
161
+ s1_x = p1_x - p0_x;
162
+ s1_y = p1_y - p0_y;
163
+ s2_x = p3_x - p2_x;
164
+ s2_y = p3_y - p2_y;
165
+
166
+ let s, t;
167
+ s =
168
+ (-s1_y * (p0_x - p2_x) + s1_x * (p0_y - p2_y)) /
169
+ (-s2_x * s1_y + s1_x * s2_y);
170
+ t =
171
+ (s2_x * (p0_y - p2_y) - s2_y * (p0_x - p2_x)) /
172
+ (-s2_x * s1_y + s1_x * s2_y);
173
+
174
+ if (s >= 0 && s <= 1 && t >= 0 && t <= 1) {
175
+ // Collision detected
176
+ rV.x = p0_x + t * s1_x;
177
+ rV.y = p0_y + t * s1_y;
178
+ }
179
+
180
+ return rV;
181
+ };
182
+
183
+ if (tooltipTracking === TooltipTracking.x) {
184
+ const bisect = d3.bisector((_: BasePoint) => _.x).right;
185
+
186
+ const x0 = foundX.invert(mouse[0]);
187
+ const rightId = bisect(this.series.data, x0);
188
+
189
+ const range = foundY.range();
190
+
191
+ const intersect = lineIntersection(
192
+ mouse[0],
193
+ range[0],
194
+ mouse[0],
195
+ range[1],
196
+ foundX(this.series.data[rightId - 1]?.x),
197
+ foundY(this.series.data[rightId - 1]?.y),
198
+ foundX(this.series.data[rightId]?.x),
199
+ foundY(this.series.data[rightId]?.y)
200
+ );
201
+
202
+ console.log(intersect);
203
+
204
+ this.svc.setTooltip({
205
+ point: { x: foundX.invert(intersect.x), y: foundY.invert(intersect.y) },
206
+ series: this.series,
207
+ });
208
+
209
+ return {
210
+ x: intersect.x,
211
+ y: intersect.y,
212
+ };
213
+ }
214
+
215
+ if (tooltipTracking === TooltipTracking.y) {
216
+ const bisect = d3.bisector((_: BasePoint) => _.y).right;
217
+
218
+ const y0 = foundY.invert(mouse[1]);
219
+
220
+ const rightId = bisect(this.series.data, y0);
221
+ const range = foundX.range();
222
+
223
+ const intersect = lineIntersection(
224
+ range[0],
225
+ mouse[1],
226
+ range[1],
227
+ mouse[1],
228
+ foundX(this.series.data[rightId - 1]?.x),
229
+ foundY(this.series.data[rightId - 1]?.y),
230
+ foundX(this.series.data[rightId]?.x),
231
+ foundY(this.series.data[rightId]?.y)
232
+ );
233
+
234
+ this.svc.setTooltip({
235
+ point: { x: foundX.invert(intersect.x), y: foundY.invert(intersect.y) },
236
+ series: this.series,
237
+ });
238
+
239
+ return {
240
+ x: intersect.x,
241
+ y: intersect.y,
242
+ };
243
+ }
244
+ }
245
+ }
@@ -0,0 +1,80 @@
1
+ import {
2
+ ChangeDetectionStrategy,
3
+ ChangeDetectorRef,
4
+ Component,
5
+ ComponentRef,
6
+ Input,
7
+ OnInit,
8
+ SimpleChanges,
9
+ ViewContainerRef,
10
+ } from '@angular/core';
11
+ import { SeriesBaseComponent } from '../../base/series-base.component';
12
+ import { LineSeriesComponent } from '../series/line/line-series.component';
13
+ import { BarSeriesComponent } from '../series/bar/bar-series.component';
14
+
15
+ import { Series } from '../../model/series';
16
+ import { BasePoint } from '../../model/base-point';
17
+ import { ChartService } from '../../service/chart.service';
18
+ import { tap } from 'rxjs';
19
+ import { throttleTime } from 'rxjs/operators';
20
+ import { SeriesType } from '../../model/enum/series-type';
21
+
22
+ @Component({
23
+ selector: '[teta-series-host]',
24
+ template: '',
25
+ changeDetection: ChangeDetectionStrategy.OnPush,
26
+ })
27
+ export class SeriesHostComponent<T extends BasePoint> implements OnInit {
28
+ @Input() series: Series<T>;
29
+ @Input() size: DOMRect;
30
+
31
+ private defaultSeriesTypeMapping = new Map<
32
+ SeriesType,
33
+ typeof SeriesBaseComponent
34
+ >()
35
+ .set(SeriesType.line, LineSeriesComponent)
36
+ .set(SeriesType.bar, BarSeriesComponent);
37
+
38
+ private _init = false;
39
+ private _componentRef: ComponentRef<any>;
40
+
41
+ constructor(
42
+ private viewContainerRef: ViewContainerRef,
43
+ private chartService: ChartService
44
+ ) {
45
+ this.chartService.size
46
+ .pipe(
47
+ throttleTime(100, null, { trailing: true }),
48
+ tap(() => {
49
+ this._componentRef?.injector.get(ChangeDetectorRef).detectChanges();
50
+ })
51
+ )
52
+ .subscribe();
53
+ }
54
+
55
+ ngOnInit(): void {
56
+ if (!SeriesBaseComponent.isPrototypeOf(this.series.component)) {
57
+ this.series.component =
58
+ this.defaultSeriesTypeMapping.get(this.series.type) ||
59
+ LineSeriesComponent;
60
+ }
61
+
62
+ this._componentRef = this.viewContainerRef.createComponent(
63
+ this.series.component
64
+ );
65
+ this._componentRef.instance.series = this.series;
66
+ this._componentRef.instance.size = this.size;
67
+ this._init = true;
68
+ }
69
+
70
+ ngOnDestroy(): void {}
71
+
72
+ ngOnChanges(changes: SimpleChanges): void {
73
+ if (this._init && changes.hasOwnProperty('series')) {
74
+ this._componentRef.instance.series = this.series;
75
+ this._componentRef.instance.size = this.size;
76
+ this._componentRef.injector.get(ChangeDetectorRef).markForCheck();
77
+ this._componentRef.injector.get(ChangeDetectorRef).detectChanges();
78
+ }
79
+ }
80
+ }
@@ -0,0 +1,14 @@
1
+ <ng-container *ngIf="position | async as p">
2
+
3
+ <div class="chart-tooltip color-text-90 bg-background-50 shadow-2 padding-2 border-radius-1"
4
+ [style.position]="'fixed'"
5
+ [style.opacity]="display | async"
6
+ style="pointer-events: none;"
7
+ [style.left]="p.left"
8
+ [style.top]="p.top"
9
+ [style.bottom]="p.bottom"
10
+ [style.right]="p.right"
11
+ [innerHTML]="displayTooltips | async">
12
+ </div>
13
+ </ng-container>
14
+
@@ -0,0 +1,7 @@
1
+ :host {
2
+ position: absolute;
3
+ }
4
+
5
+ .chart-tooltip {
6
+ transition: all 0.1s ease;
7
+ }
@@ -0,0 +1,25 @@
1
+ import { ComponentFixture, TestBed } from '@angular/core/testing';
2
+
3
+ import { TooltipComponent } from './tooltip.component';
4
+
5
+ describe('TooltipComponent', () => {
6
+ let component: TooltipComponent;
7
+ let fixture: ComponentFixture<TooltipComponent>;
8
+
9
+ beforeEach(async () => {
10
+ await TestBed.configureTestingModule({
11
+ declarations: [ TooltipComponent ]
12
+ })
13
+ .compileComponents();
14
+ });
15
+
16
+ beforeEach(() => {
17
+ fixture = TestBed.createComponent(TooltipComponent);
18
+ component = fixture.componentInstance;
19
+ fixture.detectChanges();
20
+ });
21
+
22
+ it('should create', () => {
23
+ expect(component).toBeTruthy();
24
+ });
25
+ });