@tetacom/ng-threejs-chart 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 (62) hide show
  1. package/.eslintrc.json +43 -0
  2. package/README.md +7 -0
  3. package/common/model/base-3d-point.d.ts +5 -0
  4. package/component/three/custom-series/custom-series.component.d.ts +20 -0
  5. package/component/three/public-api.d.ts +11 -0
  6. package/component/three/three-chart/area-3d/area-3d.component.d.ts +13 -0
  7. package/component/three/three-chart/axes-3d/axes-3d.component.d.ts +28 -0
  8. package/component/three/three-chart/base-3d-series/base3d-series.component.d.ts +15 -0
  9. package/component/three/three-chart/block-3d/block-3d.component.d.ts +28 -0
  10. package/component/three/three-chart/canvas/canvas.component.d.ts +11 -0
  11. package/component/three/three-chart/directive/canvas-3d-host.d.ts +19 -0
  12. package/component/three/three-chart/directive/public-api.d.ts +2 -0
  13. package/component/three/three-chart/directive/series-3d-host.d.ts +16 -0
  14. package/component/three/three-chart/line-3d/line-3d.component.d.ts +19 -0
  15. package/component/three/three-chart/model/axes-3d-min-max.d.ts +5 -0
  16. package/component/three/three-chart/model/axis-3d-point.d.ts +4 -0
  17. package/component/three/three-chart/model/base-3d-series.d.ts +11 -0
  18. package/component/three/three-chart/model/base-3d-three-point.d.ts +8 -0
  19. package/component/three/three-chart/model/block-3d-series.d.ts +6 -0
  20. package/component/three/three-chart/model/block3d-point.d.ts +5 -0
  21. package/component/three/three-chart/model/enum/public-api.d.ts +1 -0
  22. package/component/three/three-chart/model/enum/series-3d-type.d.ts +4 -0
  23. package/component/three/three-chart/model/i-3d-chart-config.d.ts +14 -0
  24. package/component/three/three-chart/model/line-3d-point.d.ts +5 -0
  25. package/component/three/three-chart/model/line-3d-series.d.ts +6 -0
  26. package/component/three/three-chart/model/public-api.d.ts +10 -0
  27. package/component/three/three-chart/scene/scene.component.d.ts +20 -0
  28. package/component/three/three-chart/service/chart-3d.service.d.ts +21 -0
  29. package/component/three/three-chart/three-chart.component.d.ts +19 -0
  30. package/esm2022/common/model/base-3d-point.mjs +2 -0
  31. package/esm2022/component/three/custom-series/custom-series.component.mjs +32 -0
  32. package/esm2022/component/three/public-api.mjs +12 -0
  33. package/esm2022/component/three/three-chart/area-3d/area-3d.component.mjs +54 -0
  34. package/esm2022/component/three/three-chart/axes-3d/axes-3d.component.mjs +59 -0
  35. package/esm2022/component/three/three-chart/base-3d-series/base3d-series.component.mjs +28 -0
  36. package/esm2022/component/three/three-chart/block-3d/block-3d.component.mjs +74 -0
  37. package/esm2022/component/three/three-chart/canvas/canvas.component.mjs +22 -0
  38. package/esm2022/component/three/three-chart/directive/canvas-3d-host.mjs +45 -0
  39. package/esm2022/component/three/three-chart/directive/public-api.mjs +3 -0
  40. package/esm2022/component/three/three-chart/directive/series-3d-host.mjs +45 -0
  41. package/esm2022/component/three/three-chart/line-3d/line-3d.component.mjs +40 -0
  42. package/esm2022/component/three/three-chart/model/axes-3d-min-max.mjs +2 -0
  43. package/esm2022/component/three/three-chart/model/axis-3d-point.mjs +2 -0
  44. package/esm2022/component/three/three-chart/model/base-3d-series.mjs +2 -0
  45. package/esm2022/component/three/three-chart/model/base-3d-three-point.mjs +2 -0
  46. package/esm2022/component/three/three-chart/model/block-3d-series.mjs +2 -0
  47. package/esm2022/component/three/three-chart/model/block3d-point.mjs +2 -0
  48. package/esm2022/component/three/three-chart/model/enum/public-api.mjs +2 -0
  49. package/esm2022/component/three/three-chart/model/enum/series-3d-type.mjs +6 -0
  50. package/esm2022/component/three/three-chart/model/i-3d-chart-config.mjs +2 -0
  51. package/esm2022/component/three/three-chart/model/line-3d-point.mjs +2 -0
  52. package/esm2022/component/three/three-chart/model/line-3d-series.mjs +2 -0
  53. package/esm2022/component/three/three-chart/model/public-api.mjs +11 -0
  54. package/esm2022/component/three/three-chart/scene/scene.component.mjs +45 -0
  55. package/esm2022/component/three/three-chart/service/chart-3d.service.mjs +83 -0
  56. package/esm2022/component/three/three-chart/three-chart.component.mjs +45 -0
  57. package/esm2022/index.mjs +2 -0
  58. package/esm2022/tetacom-ng-threejs-chart.mjs +5 -0
  59. package/fesm2022/tetacom-ng-threejs-chart.mjs +496 -0
  60. package/fesm2022/tetacom-ng-threejs-chart.mjs.map +1 -0
  61. package/index.d.ts +1 -0
  62. package/package.json +29 -0
@@ -0,0 +1,496 @@
1
+ import * as i0 from '@angular/core';
2
+ import { Injectable, Component, Input, CUSTOM_ELEMENTS_SCHEMA, ChangeDetectionStrategy, inject, ChangeDetectorRef } from '@angular/core';
3
+ import * as i1 from '@angular/common';
4
+ import { CommonModule, NgIf, AsyncPipe, NgForOf } from '@angular/common';
5
+ import * as d3 from 'd3';
6
+ import { ReplaySubject, map, shareReplay, combineLatest, takeWhile } from 'rxjs';
7
+ import * as i2 from 'angular-three';
8
+ import { extend, NgtArgs, NgtStore, NgtCanvas } from 'angular-three';
9
+ import * as THREE from 'three';
10
+ import { GridHelper, OrthographicCamera } from 'three';
11
+ import { NgtsText, NgtsLine } from 'angular-three-soba/abstractions';
12
+ import { NgtsOrbitControls } from 'angular-three-soba/controls';
13
+
14
+ class Chart3dService {
15
+ constructor() {
16
+ this.data$ = new ReplaySubject(1);
17
+ this.data = this.data$.asObservable();
18
+ this.minMax = this.data.pipe(map(_ => {
19
+ return this.getAxesMinMax(_);
20
+ }));
21
+ this.scales = this.minMax.pipe(map(minMax => {
22
+ return this.getScales(minMax);
23
+ }), shareReplay(1));
24
+ }
25
+ setData(data) {
26
+ this.data$.next(data);
27
+ }
28
+ getAxesMinMax(data) {
29
+ const zArr = data.series
30
+ .map(_ => {
31
+ return _?.data?.map(d => d?.z);
32
+ })
33
+ .flat()
34
+ .filter(_ => {
35
+ return _ !== null && _ !== undefined;
36
+ });
37
+ const xArr = data.series
38
+ .map(_ => {
39
+ return _?.data?.map(d => d?.x);
40
+ })
41
+ .flat()
42
+ .filter(_ => {
43
+ return _ !== null && _ !== undefined;
44
+ });
45
+ const yArr = data.series
46
+ .map(_ => {
47
+ return _?.data?.map(d => d?.y);
48
+ })
49
+ .flat()
50
+ .filter(_ => {
51
+ return _ !== null && _ !== undefined;
52
+ });
53
+ const ZMinMaxVal = [Math.min(...zArr), Math.max(...zArr)];
54
+ const XMinMaxVal = [Math.min(...xArr), Math.max(...xArr)];
55
+ const YMinMaxVal = [Math.min(...yArr), Math.max(...yArr)];
56
+ return {
57
+ z: this.getMinMaxRange(ZMinMaxVal, data.zAxis?.min, data.zAxis?.max),
58
+ x: this.getMinMaxRange(XMinMaxVal, data.xAxis?.min, data.xAxis?.max),
59
+ y: this.getMinMaxRange(YMinMaxVal, data.yAxis?.min, data.yAxis?.max),
60
+ };
61
+ }
62
+ getMinMaxRange(minMax, axisMin, axisMax) {
63
+ const min = axisMin ||
64
+ (Math.abs(minMax[0] - minMax[1]) < 0.0000001
65
+ ? minMax[0] - Math.abs(minMax[0] - 1) * 0.1
66
+ : minMax[0]);
67
+ const max = axisMax ||
68
+ (Math.abs(minMax[0] - minMax[1]) < 0.0000001
69
+ ? minMax[1] + Math.abs(minMax[1] + 1) * 0.1
70
+ : minMax[1]);
71
+ return [min, max];
72
+ }
73
+ getScales(axesMinMax) {
74
+ const z = d3.scaleLinear().domain(axesMinMax.z).range([50, -50]);
75
+ const x = d3.scaleLinear().domain(axesMinMax.x).range([25, 0]);
76
+ const y = d3.scaleLinear().domain(axesMinMax.y).range([50, -50]);
77
+ return {
78
+ x,
79
+ y,
80
+ z,
81
+ };
82
+ }
83
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: Chart3dService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
84
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: Chart3dService, providedIn: 'root' }); }
85
+ }
86
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: Chart3dService, decorators: [{
87
+ type: Injectable,
88
+ args: [{
89
+ providedIn: 'root',
90
+ }]
91
+ }], ctorParameters: () => [] });
92
+
93
+ class Base3dSeriesComponent {
94
+ set series(series) {
95
+ this._series = series;
96
+ }
97
+ get series() {
98
+ return this._series;
99
+ }
100
+ constructor(svc, ngtStore) {
101
+ this.svc = svc;
102
+ this.ngtStore = ngtStore;
103
+ }
104
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: Base3dSeriesComponent, deps: [{ token: Chart3dService }, { token: i2.NgtStore }], target: i0.ɵɵFactoryTarget.Component }); }
105
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.1.3", type: Base3dSeriesComponent, isStandalone: true, selector: "teta-base3d-series", inputs: { series: "series" }, ngImport: i0, template: "<p>base3d-series works!</p>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }] }); }
106
+ }
107
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: Base3dSeriesComponent, decorators: [{
108
+ type: Component,
109
+ args: [{ selector: 'teta-base3d-series', standalone: true, imports: [CommonModule], template: "<p>base3d-series works!</p>\n" }]
110
+ }], ctorParameters: () => [{ type: Chart3dService }, { type: i2.NgtStore }], propDecorators: { series: [{
111
+ type: Input
112
+ }] } });
113
+
114
+ extend(THREE);
115
+ class CustomSeriesComponent extends Base3dSeriesComponent {
116
+ constructor(svc, ngtStore) {
117
+ super(svc, ngtStore);
118
+ this.svc = svc;
119
+ this.ngtStore = ngtStore;
120
+ this.scales = this.svc.scales;
121
+ }
122
+ ngOnInit() {
123
+ setTimeout(() => {
124
+ this.ngtStore.get('camera').zoom = 2;
125
+ this.ngtStore.get('camera').updateProjectionMatrix();
126
+ }, 1000);
127
+ }
128
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: CustomSeriesComponent, deps: [{ token: Chart3dService }, { token: i2.NgtStore }], target: i0.ɵɵFactoryTarget.Component }); }
129
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.1.3", type: CustomSeriesComponent, isStandalone: true, selector: "teta-custom-series", usesInheritance: true, ngImport: i0, template: "<ng-container *ngIf=\" {scales:scales|async} as scales\">\n <ngt-mesh [position]=\"[scales.scales.x(this.series.data[0].x),scales.scales.y(this.series.data[0].y),scales.scales.z(this.series.data[0].z) ]\">\n <ngt-box-geometry *args=\"[5,5,5]\"></ngt-box-geometry>\n <ngt-mesh-basic-material></ngt-mesh-basic-material>\n </ngt-mesh>\n</ng-container>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "directive", type: NgtArgs, selector: "[args]", inputs: ["args"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
130
+ }
131
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: CustomSeriesComponent, decorators: [{
132
+ type: Component,
133
+ args: [{ selector: 'teta-custom-series', standalone: true, imports: [CommonModule, NgtArgs], schemas: [CUSTOM_ELEMENTS_SCHEMA], changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-container *ngIf=\" {scales:scales|async} as scales\">\n <ngt-mesh [position]=\"[scales.scales.x(this.series.data[0].x),scales.scales.y(this.series.data[0].y),scales.scales.z(this.series.data[0].z) ]\">\n <ngt-box-geometry *args=\"[5,5,5]\"></ngt-box-geometry>\n <ngt-mesh-basic-material></ngt-mesh-basic-material>\n </ngt-mesh>\n</ng-container>\n" }]
134
+ }], ctorParameters: () => [{ type: Chart3dService }, { type: i2.NgtStore }] });
135
+
136
+ extend(THREE);
137
+ class Area3dComponent {
138
+ constructor() {
139
+ this.THREE = THREE;
140
+ }
141
+ createArea() {
142
+ const grids = [];
143
+ grids.push(this.getMainGrid());
144
+ grids.push(...this.createGrid(4, 25, 3, 'vertical'));
145
+ grids.push(...this.createGrid(4, 25, 3, 'horizontal'));
146
+ return grids;
147
+ }
148
+ getMainGrid() {
149
+ const mainGrid = new GridHelper(100, 12);
150
+ mainGrid.position.set(0, 0, 0);
151
+ mainGrid.rotateZ(Math.PI / 2);
152
+ return mainGrid;
153
+ }
154
+ createGrid(gridsCount, gridSize, rectsInGrid, direction) {
155
+ const plane = [];
156
+ for (let p = 0; p <= gridsCount - 1; p++) {
157
+ plane[p] = new THREE.GridHelper(gridSize, rectsInGrid, '#666', '#666');
158
+ plane[p].renderOrder = -1;
159
+ switch (direction) {
160
+ case 'horizontal':
161
+ plane[p].position.set(gridSize / 2, -50, gridSize * p + gridSize / 2 - 50);
162
+ break;
163
+ case 'vertical':
164
+ plane[p].position.set(gridSize / 2, gridSize * p + gridSize / 2 - 50, -50);
165
+ plane[p].rotateZ(Math.PI / 2);
166
+ plane[p].rotateX(Math.PI / 2);
167
+ break;
168
+ }
169
+ }
170
+ return plane;
171
+ }
172
+ ngOnInit() {
173
+ this.area = this.createArea();
174
+ }
175
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: Area3dComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
176
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.1.3", type: Area3dComponent, isStandalone: true, selector: "teta-area-3d", ngImport: i0, template: "<ngt-mesh>\n <ngt-mesh-basic-material [side]=\"THREE.DoubleSide\"></ngt-mesh-basic-material>\n <ng-container *ngFor=\"let rect of area\">\n <ngt-primitive *args=\"[rect]\"></ngt-primitive>\n </ng-container>\n</ngt-mesh>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: NgtArgs, selector: "[args]", inputs: ["args"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
177
+ }
178
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: Area3dComponent, decorators: [{
179
+ type: Component,
180
+ args: [{ selector: 'teta-area-3d', standalone: true, imports: [CommonModule, NgtArgs], changeDetection: ChangeDetectionStrategy.OnPush, schemas: [CUSTOM_ELEMENTS_SCHEMA], template: "<ngt-mesh>\n <ngt-mesh-basic-material [side]=\"THREE.DoubleSide\"></ngt-mesh-basic-material>\n <ng-container *ngFor=\"let rect of area\">\n <ngt-primitive *args=\"[rect]\"></ngt-primitive>\n </ng-container>\n</ngt-mesh>\n" }]
181
+ }] });
182
+
183
+ extend(THREE);
184
+ class Axes3dComponent {
185
+ constructor() {
186
+ this._alive = true;
187
+ this.chartService = inject(Chart3dService);
188
+ this.axes = combineLatest([
189
+ this.chartService.scales,
190
+ this.chartService.minMax,
191
+ ]).pipe(takeWhile(() => this._alive), map(([scales, minMax]) => {
192
+ return this.createAxes(scales, minMax);
193
+ }));
194
+ }
195
+ createAxes(scales, minMax) {
196
+ const axisZ = this.generateTicks(minMax.z, 12).map(_ => {
197
+ return { value: _.toFixed(1), position: scales.z(_) };
198
+ });
199
+ const axisY = this.generateTicks(minMax.y, 12).map(_ => {
200
+ return { value: _.toFixed(1), position: scales.y(_) };
201
+ });
202
+ const axisX = this.generateTicks(minMax.x, 4).map(_ => {
203
+ return { value: _.toFixed(1), position: scales.x(_) };
204
+ });
205
+ return { z: axisZ, y: axisY, x: axisX };
206
+ }
207
+ generateTicks(extremes, count = 10) {
208
+ const [min, max] = extremes;
209
+ const tickStep = (max - min) / count;
210
+ const ticks = d3
211
+ .range(min, max + tickStep, tickStep)
212
+ .filter(step => step <= max);
213
+ return ticks;
214
+ }
215
+ trackBy(i) {
216
+ return i;
217
+ }
218
+ ngOnDestroy() {
219
+ this._alive = false;
220
+ }
221
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: Axes3dComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
222
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.1.3", type: Axes3dComponent, isStandalone: true, selector: "teta-axes-3d", inputs: { rotation: "rotation" }, ngImport: i0, template: "<ng-container *ngIf='{axes:axes|async}as data'>\n <ngts-text *ngFor='let tick of data.axes?.x;let i=index; trackBy: trackBy' [text]=\"tick.value+'-'\"\n [color]=\"'var(--color-text-90)'\"\n [rotation]='rotation'\n [fontSize]='2.5'\n [position]='[tick.position, -50, 50]'\n [anchorX]=\"'right'\"\n [anchorY]=\"'middle'\"\n [textAlign]=\"'right'\"\n ></ngts-text>\n <ngts-text *ngFor='let tick of data.axes?.y;let i=index; trackBy: trackBy' [text]=\"tick.value+'-'\"\n [color]=\"'var(--color-text-90)'\"\n [rotation]='rotation'\n [fontSize]='2.5'\n [position]='[0,tick.position,50]'\n [anchorX]=\"'right'\"\n [anchorY]=\"'middle'\"\n [textAlign]=\"'right'\"\n ></ngts-text>\n <ngts-text *ngFor='let tick of data.axes?.z;let i=index; trackBy: trackBy' [text]='tick.value'\n [color]=\"'var(--color-text-90)'\"\n [rotation]='rotation'\n [fontSize]='2.5'\n [position]='[25,-50,tick.position]'\n ></ngts-text>\n</ng-container>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "component", type: NgtsText, selector: "ngts-text[text]", inputs: ["textRef", "text", "characters", "font", "anchorX", "anchorY"], outputs: ["sync"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
223
+ }
224
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: Axes3dComponent, decorators: [{
225
+ type: Component,
226
+ args: [{ selector: 'teta-axes-3d', standalone: true, imports: [CommonModule, NgtsText], schemas: [CUSTOM_ELEMENTS_SCHEMA], changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-container *ngIf='{axes:axes|async}as data'>\n <ngts-text *ngFor='let tick of data.axes?.x;let i=index; trackBy: trackBy' [text]=\"tick.value+'-'\"\n [color]=\"'var(--color-text-90)'\"\n [rotation]='rotation'\n [fontSize]='2.5'\n [position]='[tick.position, -50, 50]'\n [anchorX]=\"'right'\"\n [anchorY]=\"'middle'\"\n [textAlign]=\"'right'\"\n ></ngts-text>\n <ngts-text *ngFor='let tick of data.axes?.y;let i=index; trackBy: trackBy' [text]=\"tick.value+'-'\"\n [color]=\"'var(--color-text-90)'\"\n [rotation]='rotation'\n [fontSize]='2.5'\n [position]='[0,tick.position,50]'\n [anchorX]=\"'right'\"\n [anchorY]=\"'middle'\"\n [textAlign]=\"'right'\"\n ></ngts-text>\n <ngts-text *ngFor='let tick of data.axes?.z;let i=index; trackBy: trackBy' [text]='tick.value'\n [color]=\"'var(--color-text-90)'\"\n [rotation]='rotation'\n [fontSize]='2.5'\n [position]='[25,-50,tick.position]'\n ></ngts-text>\n</ng-container>\n" }]
227
+ }], ctorParameters: () => [], propDecorators: { rotation: [{
228
+ type: Input
229
+ }] } });
230
+
231
+ extend(THREE);
232
+ class Block3dComponent extends Base3dSeriesComponent {
233
+ constructor(svc, ngtStore) {
234
+ super(svc, ngtStore);
235
+ this.svc = svc;
236
+ this.ngtStore = ngtStore;
237
+ this._alive = true;
238
+ this.Math = Math;
239
+ this.blocks = this.svc.scales.pipe(takeWhile(() => this._alive), map(scales => {
240
+ return this.series?.data?.map(_ => {
241
+ return this.createSVGTexture(scales.y(_?.y), scales.y(_?.y1), _?.iconId);
242
+ });
243
+ }));
244
+ }
245
+ createSVGTexture(y, y1, iconId) {
246
+ const max = Math.max(y, y1);
247
+ const min = Math.min(y, y1);
248
+ const height = Math.abs(max - min);
249
+ const icon = iconId ? document.querySelector(`#${iconId}`) : null;
250
+ const svgString = icon ? `<svg width='100' height='100' viewBox='0 0 16 16' fill='none' xmlns='http://www.w3.org/2000/svg'>${icon?.innerHTML}</svg>` : null;
251
+ const loader = new THREE.TextureLoader();
252
+ const texture = loader.load(`data:image/svg+xml;charset=utf-8,${encodeURIComponent(svgString)}`);
253
+ const plane = this.createTexturedPlane(texture, 100, height, !!icon);
254
+ const plane1 = this.createTexturedPlane(texture, 25, height, !!icon);
255
+ plane.rotation.set(0, Math.PI / 2, 0);
256
+ plane.position.set(0.17, min + height / 2, 0);
257
+ plane1.position.set(25 / 2, min + height / 2, -50 + 0.17);
258
+ return [
259
+ { component: plane, position: min + height / 2 },
260
+ { component: plane1, position: min + height / 2 },
261
+ ];
262
+ }
263
+ createTexturedPlane(texture, width, height, visible) {
264
+ texture.wrapS = THREE.RepeatWrapping;
265
+ texture.wrapT = THREE.RepeatWrapping;
266
+ texture.repeat.set(10, height / 9);
267
+ const material = new THREE.MeshBasicMaterial({ map: texture, visible });
268
+ const geometry = new THREE.PlaneGeometry(width, height, 1, 1);
269
+ const uvs = geometry.attributes['uv'].array;
270
+ const newUvs = new Float32Array(uvs);
271
+ newUvs[0] = 0;
272
+ newUvs[1] = 1;
273
+ newUvs[2] = width / 100;
274
+ newUvs[3] = 1;
275
+ newUvs[4] = 0;
276
+ newUvs[5] = 0;
277
+ newUvs[6] = width / 100;
278
+ newUvs[7] = 0;
279
+ geometry.attributes['uv'].needsUpdate = true;
280
+ geometry.setAttribute('uv', new THREE.BufferAttribute(newUvs, 2));
281
+ return new THREE.Mesh(geometry, material);
282
+ }
283
+ ngOnDestroy() {
284
+ this._alive = false;
285
+ }
286
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: Block3dComponent, deps: [{ token: Chart3dService }, { token: i2.NgtStore }], target: i0.ɵɵFactoryTarget.Component }); }
287
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.1.3", type: Block3dComponent, isStandalone: true, selector: "teta-block-3d", usesInheritance: true, ngImport: i0, template: "<ng-container *ngIf='{\n blocks: blocks | async,\n scales: svc.scales | async\n } as data'>\n <ng-container *ngFor='let mesh of data.blocks; let i=index'>\n <ngt-primitive *args='[mesh[0].component]'></ngt-primitive>\n <ngts-text [text]='series.data[i].name'\n color='black'\n [fontSize]='2.5'\n [rotation]='[0,Math.PI/2,0]'\n [position]='[1,mesh[0].position,5]'\n [textAlign]=\"'left'\"\n [anchorX]=\"'center'\"\n [anchorY]=\"'middle'\"></ngts-text>\n <ngt-primitive *args='[mesh[1].component]'></ngt-primitive>\n </ng-container>\n</ng-container>\n\n", dependencies: [{ kind: "directive", type: NgtArgs, selector: "[args]", inputs: ["args"] }, { kind: "component", type: NgtsText, selector: "ngts-text[text]", inputs: ["textRef", "text", "characters", "font", "anchorX", "anchorY"], outputs: ["sync"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "directive", type: NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
288
+ }
289
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: Block3dComponent, decorators: [{
290
+ type: Component,
291
+ args: [{ selector: 'teta-block-3d', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [NgtArgs, NgtsText, NgIf, AsyncPipe, NgForOf], schemas: [CUSTOM_ELEMENTS_SCHEMA], template: "<ng-container *ngIf='{\n blocks: blocks | async,\n scales: svc.scales | async\n } as data'>\n <ng-container *ngFor='let mesh of data.blocks; let i=index'>\n <ngt-primitive *args='[mesh[0].component]'></ngt-primitive>\n <ngts-text [text]='series.data[i].name'\n color='black'\n [fontSize]='2.5'\n [rotation]='[0,Math.PI/2,0]'\n [position]='[1,mesh[0].position,5]'\n [textAlign]=\"'left'\"\n [anchorX]=\"'center'\"\n [anchorY]=\"'middle'\"></ngts-text>\n <ngt-primitive *args='[mesh[1].component]'></ngt-primitive>\n </ng-container>\n</ng-container>\n\n" }]
292
+ }], ctorParameters: () => [{ type: Chart3dService }, { type: i2.NgtStore }] });
293
+
294
+ extend(THREE);
295
+ class Line3dComponent extends Base3dSeriesComponent {
296
+ constructor(svc, ngtStore) {
297
+ super(svc, ngtStore);
298
+ this.svc = svc;
299
+ this.ngtStore = ngtStore;
300
+ this._alive = true;
301
+ this.Math = Math;
302
+ this.points = this.svc.scales.pipe(takeWhile(() => this._alive), map(scales => {
303
+ return this.getPoints(scales);
304
+ }));
305
+ }
306
+ getPoints(scales) {
307
+ return this.series?.data?.map(_ => {
308
+ return [scales.x(_?.x), scales.y(_?.y), scales.z(_?.z)];
309
+ }).flat();
310
+ }
311
+ ngOnDestroy() {
312
+ this._alive = false;
313
+ }
314
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: Line3dComponent, deps: [{ token: Chart3dService }, { token: i2.NgtStore }], target: i0.ɵɵFactoryTarget.Component }); }
315
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.1.3", type: Line3dComponent, isStandalone: true, selector: "teta-line-3d", usesInheritance: true, ngImport: i0, template: "<ng-container *ngIf=\"{points:points|async}as data\">\n <ngt-mesh *ngIf=\"data?.points?.length\">\n <ngts-line [color]=\"series.color\" [lineWidth]=\"2\" [points]=\"data.points\"></ngts-line>\n <ngt-line-basic-material></ngt-line-basic-material>\n </ngt-mesh>\n</ng-container>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "component", type: NgtsLine, selector: "ngts-line[points]", inputs: ["lineRef", "points", "segments"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
316
+ }
317
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: Line3dComponent, decorators: [{
318
+ type: Component,
319
+ args: [{ selector: 'teta-line-3d', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [CommonModule, NgtsLine, NgtArgs], schemas: [CUSTOM_ELEMENTS_SCHEMA], template: "<ng-container *ngIf=\"{points:points|async}as data\">\n <ngt-mesh *ngIf=\"data?.points?.length\">\n <ngts-line [color]=\"series.color\" [lineWidth]=\"2\" [points]=\"data.points\"></ngts-line>\n <ngt-line-basic-material></ngt-line-basic-material>\n </ngt-mesh>\n</ng-container>\n" }]
320
+ }], ctorParameters: () => [{ type: Chart3dService }, { type: i2.NgtStore }] });
321
+
322
+ var Series3dType;
323
+ (function (Series3dType) {
324
+ Series3dType[Series3dType["line"] = 0] = "line";
325
+ Series3dType[Series3dType["block"] = 1] = "block";
326
+ })(Series3dType || (Series3dType = {}));
327
+
328
+ class Series3dHost {
329
+ constructor(viewContainerRef) {
330
+ this.viewContainerRef = viewContainerRef;
331
+ this.seriesMap = new Map()
332
+ .set(Series3dType.line, Line3dComponent)
333
+ .set(Series3dType.block, Block3dComponent);
334
+ this._init = false;
335
+ }
336
+ ngOnInit() {
337
+ if (!Object.prototype.isPrototypeOf.call(Base3dSeriesComponent, this.series.component)) {
338
+ this.series.component = this.seriesMap.get(this.series.type);
339
+ }
340
+ this._componentRef = this.viewContainerRef.createComponent(this.series.component);
341
+ this._componentRef.instance.series = this.series;
342
+ this._init = true;
343
+ }
344
+ ngOnChanges(changes) {
345
+ if (this._init &&
346
+ (Object.prototype.hasOwnProperty.call(changes, 'series') ||
347
+ changes.hasOwnProperty('config'))) {
348
+ this._componentRef.instance.series = this.series;
349
+ this._componentRef.injector.get(ChangeDetectorRef).detectChanges();
350
+ }
351
+ }
352
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: Series3dHost, deps: [{ token: i0.ViewContainerRef }], target: i0.ɵɵFactoryTarget.Component }); }
353
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.1.3", type: Series3dHost, isStandalone: true, selector: "[teta-series-3d-host]", inputs: { series: "series" }, usesOnChanges: true, ngImport: i0, template: '', isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
354
+ }
355
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: Series3dHost, decorators: [{
356
+ type: Component,
357
+ args: [{
358
+ selector: '[teta-series-3d-host]',
359
+ template: '',
360
+ standalone: true,
361
+ changeDetection: ChangeDetectionStrategy.OnPush,
362
+ }]
363
+ }], ctorParameters: () => [{ type: i0.ViewContainerRef }], propDecorators: { series: [{
364
+ type: Input
365
+ }] } });
366
+
367
+ class SceneComponent {
368
+ constructor() {
369
+ this.store = inject(NgtStore);
370
+ this.Math = Math;
371
+ this.chartService = inject(Chart3dService);
372
+ this._cdr = inject(ChangeDetectorRef);
373
+ this.data = this.chartService.data;
374
+ }
375
+ setRotation() {
376
+ this.rotation = null;
377
+ this._cdr.detectChanges();
378
+ this.rotation = this.store.get('camera').rotation;
379
+ this._cdr.detectChanges();
380
+ }
381
+ ngOnInit() {
382
+ this.rotation = this.store.get('camera').rotation;
383
+ }
384
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: SceneComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
385
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.1.3", type: SceneComponent, isStandalone: true, selector: "teta-scene", ngImport: i0, template: "<ng-container *ngIf='{data:data|async} as config'>\n <ngt-scene>\n <ngts-orbit-controls [minAzimuthAngle]='0'\n [maxAzimuthAngle]='Math.PI/2'\n [maxZoom]='30'\n [minZoom]='2'\n (change)='setRotation()'></ngts-orbit-controls>\n </ngt-scene>\n <teta-area-3d></teta-area-3d>\n <ng-container *ngFor='let s of config.data?.series;'>\n <div teta-series-3d-host [series]='s'></div>\n </ng-container>\n <teta-axes-3d [rotation]='rotation'></teta-axes-3d>\n</ng-container>\n\n\n", dependencies: [{ kind: "component", type: NgtsOrbitControls, selector: "ngts-orbit-controls", inputs: ["controlsRef", "camera", "domElement", "makeDefault", "regress", "target", "enableDamping"], outputs: ["change", "start", "end"] }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "component", type: Area3dComponent, selector: "teta-area-3d" }, { kind: "component", type: Axes3dComponent, selector: "teta-axes-3d", inputs: ["rotation"] }, { kind: "component", type: Series3dHost, selector: "[teta-series-3d-host]", inputs: ["series"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
386
+ }
387
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: SceneComponent, decorators: [{
388
+ type: Component,
389
+ args: [{ standalone: true, selector: 'teta-scene', changeDetection: ChangeDetectionStrategy.OnPush, imports: [
390
+ NgtsOrbitControls,
391
+ CommonModule,
392
+ Area3dComponent,
393
+ Line3dComponent,
394
+ Axes3dComponent,
395
+ Block3dComponent,
396
+ Series3dHost,
397
+ ], schemas: [CUSTOM_ELEMENTS_SCHEMA], template: "<ng-container *ngIf='{data:data|async} as config'>\n <ngt-scene>\n <ngts-orbit-controls [minAzimuthAngle]='0'\n [maxAzimuthAngle]='Math.PI/2'\n [maxZoom]='30'\n [minZoom]='2'\n (change)='setRotation()'></ngts-orbit-controls>\n </ngt-scene>\n <teta-area-3d></teta-area-3d>\n <ng-container *ngFor='let s of config.data?.series;'>\n <div teta-series-3d-host [series]='s'></div>\n </ng-container>\n <teta-axes-3d [rotation]='rotation'></teta-axes-3d>\n</ng-container>\n\n\n" }]
398
+ }], ctorParameters: () => [] });
399
+
400
+ class CanvasComponent {
401
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: CanvasComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
402
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.1.3", type: CanvasComponent, isStandalone: true, selector: "teta-canvas", inputs: { scene: "scene", camera: "camera", data: "data" }, providers: [NgtStore], ngImport: i0, template: "<ngt-canvas *ngIf=\"data?.series?.length;else noData\" [sceneGraph]=\"scene\"\n [camera]=\"camera\">\n</ngt-canvas>\n<ng-template #noData>\n <p>{{data?.noDataText || 'no data'}}</p>\n</ng-template>\n", styles: [":host{width:100%;height:100%}\n"], dependencies: [{ kind: "component", type: NgtCanvas, selector: "ngt-canvas", inputs: ["sceneGraph", "sceneGraphInputs", "compoundPrefixes", "linear", "legacy", "flat", "orthographic", "frameloop", "dpr", "raycaster", "shadows", "camera", "gl", "eventSource", "eventPrefix", "lookAt", "performance"], outputs: ["created", "pointerMissed"] }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
403
+ }
404
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: CanvasComponent, decorators: [{
405
+ type: Component,
406
+ args: [{ selector: 'teta-canvas', standalone: true, schemas: [CUSTOM_ELEMENTS_SCHEMA], changeDetection: ChangeDetectionStrategy.OnPush, providers: [NgtStore], imports: [NgtCanvas, SceneComponent, CommonModule], template: "<ngt-canvas *ngIf=\"data?.series?.length;else noData\" [sceneGraph]=\"scene\"\n [camera]=\"camera\">\n</ngt-canvas>\n<ng-template #noData>\n <p>{{data?.noDataText || 'no data'}}</p>\n</ng-template>\n", styles: [":host{width:100%;height:100%}\n"] }]
407
+ }], propDecorators: { scene: [{
408
+ type: Input
409
+ }], camera: [{
410
+ type: Input
411
+ }], data: [{
412
+ type: Input
413
+ }] } });
414
+
415
+ class Canvas3dHost {
416
+ constructor(viewContainerRef) {
417
+ this.viewContainerRef = viewContainerRef;
418
+ this._init = false;
419
+ }
420
+ ngOnInit() {
421
+ this.createCanvas();
422
+ this._init = true;
423
+ }
424
+ ngOnChanges() {
425
+ if (this._init) {
426
+ this.createCanvas();
427
+ this._componentRef.injector.get(ChangeDetectorRef).detectChanges();
428
+ }
429
+ }
430
+ createCanvas() {
431
+ this.viewContainerRef.clear();
432
+ this._componentRef = this.viewContainerRef.createComponent(CanvasComponent);
433
+ this._componentRef.instance.scene = this.scene;
434
+ this._componentRef.instance.camera = this.camera;
435
+ this._componentRef.instance.data = this.data;
436
+ }
437
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: Canvas3dHost, deps: [{ token: i0.ViewContainerRef }], target: i0.ɵɵFactoryTarget.Component }); }
438
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.1.3", type: Canvas3dHost, isStandalone: true, selector: "[teta-canvas-3d-host]", inputs: { scene: "scene", camera: "camera", data: "data" }, usesOnChanges: true, ngImport: i0, template: '', isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
439
+ }
440
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: Canvas3dHost, decorators: [{
441
+ type: Component,
442
+ args: [{
443
+ selector: '[teta-canvas-3d-host]',
444
+ template: '',
445
+ standalone: true,
446
+ changeDetection: ChangeDetectionStrategy.OnPush,
447
+ }]
448
+ }], ctorParameters: () => [{ type: i0.ViewContainerRef }], propDecorators: { scene: [{
449
+ type: Input
450
+ }], camera: [{
451
+ type: Input
452
+ }], data: [{
453
+ type: Input
454
+ }] } });
455
+
456
+ extend(THREE);
457
+ class ThreeChartComponent {
458
+ constructor() {
459
+ this.chartService = inject(Chart3dService);
460
+ this.store = inject(NgtStore);
461
+ this.cdr = inject(ChangeDetectorRef);
462
+ }
463
+ ngOnInit() {
464
+ this.scene = SceneComponent;
465
+ this.camera = new OrthographicCamera(20, 20, 20, 20, 0.1, 1000);
466
+ this.camera.position.set(100, 20, 70);
467
+ this.camera.zoom = 4.5;
468
+ this.camera.updateProjectionMatrix();
469
+ }
470
+ ngOnChanges(changes) {
471
+ if (this.data?.series?.length) {
472
+ this.chartService.setData(this.data);
473
+ }
474
+ }
475
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: ThreeChartComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
476
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.1.3", type: ThreeChartComponent, isStandalone: true, selector: "teta-three-chart", inputs: { data: "data" }, providers: [NgtStore], usesOnChanges: true, ngImport: i0, template: "<div class=\"column_auto column justify-content-center align-center\" style=\"height: 100%;width: 100%;\">\n <div teta-canvas-3d-host [camera]=\"camera\" [data]=\"data\" [scene]=\"scene\"></div>\n</div>\n", styles: [":host{width:100%;height:100%}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: Canvas3dHost, selector: "[teta-canvas-3d-host]", inputs: ["scene", "camera", "data"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
477
+ }
478
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: ThreeChartComponent, decorators: [{
479
+ type: Component,
480
+ args: [{ selector: 'teta-three-chart', standalone: true, schemas: [CUSTOM_ELEMENTS_SCHEMA], changeDetection: ChangeDetectionStrategy.OnPush, providers: [NgtStore], imports: [
481
+ NgtCanvas,
482
+ SceneComponent,
483
+ CommonModule,
484
+ CanvasComponent,
485
+ Canvas3dHost,
486
+ ], template: "<div class=\"column_auto column justify-content-center align-center\" style=\"height: 100%;width: 100%;\">\n <div teta-canvas-3d-host [camera]=\"camera\" [data]=\"data\" [scene]=\"scene\"></div>\n</div>\n", styles: [":host{width:100%;height:100%}\n"] }]
487
+ }], propDecorators: { data: [{
488
+ type: Input
489
+ }] } });
490
+
491
+ /**
492
+ * Generated bundle index. Do not edit.
493
+ */
494
+
495
+ export { Area3dComponent, Axes3dComponent, Base3dSeriesComponent, Block3dComponent, Canvas3dHost, CanvasComponent, CustomSeriesComponent, Line3dComponent, SceneComponent, Series3dHost, Series3dType, ThreeChartComponent };
496
+ //# sourceMappingURL=tetacom-ng-threejs-chart.mjs.map