@avs/go 0.12.71730

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.
@@ -0,0 +1,1982 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2018 Advanced Visual Systems Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ *
17
+ * This product includes software developed at
18
+ * Advanced Visual Systems Inc. (http://www.avs.com)
19
+ */
20
+
21
+ import {PolymerElement, html} from '@polymer/polymer/polymer-element.js';
22
+ import {mixinBehaviors} from '@polymer/polymer/lib/legacy/class.js';
23
+ import {IronResizableBehavior} from '@polymer/iron-resizable-behavior/iron-resizable-behavior.js';
24
+ import {afterNextRender} from '@polymer/polymer/lib/utils/render-status.js';
25
+ import {AvsRenderer} from './avs-renderer.js';
26
+ import {Viewer, TransformInteractor, PanInteractor, ZoomRectangleInteractor, PickDepthEnum, Animator} from '../lib/avs-three.module.min.js';
27
+ import {AvsHttpMixin} from './avs-http-mixin.js';
28
+ import {AvsStreamMixin} from './avs-stream-mixin.js';
29
+ import {AvsDataSourceMixin} from './avs-data-source-mixin.js';
30
+ import {LOGO} from './logo.js';
31
+ import {Euler, Vector3, Quaternion} from 'three';
32
+
33
+ /**
34
+ * `avs-go-dataviz` is a Polymer 3.0 element which requests a data visualization
35
+ * from either the `sceneName` class on the AVS/Go server application running at `url`,
36
+ * or from a JSON file at `url` when `urlLoadJsonFile` is set.
37
+ *
38
+ * The request occurs upon:
39
+ * * An explicit call to `updateViewer()`
40
+ * * A change in `renderer`
41
+ * * Additionally if `manualUpdate` is false:
42
+ * * * Initialization of this element has completed
43
+ * * * This element is resized outside of the `resizeThresold` percentage
44
+ *
45
+ * @customElement
46
+ * @polymer
47
+ * @appliesMixin AvsDataSourceMixin
48
+ * @appliesMixin AvsStreamMixin
49
+ * @appliesMixin AvsHttpMixin
50
+ */
51
+ export class AvsGoDataViz extends AvsDataSourceMixin(AvsStreamMixin(AvsHttpMixin(mixinBehaviors([IronResizableBehavior], PolymerElement)))) {
52
+
53
+ static get template() {
54
+ return html`
55
+ <style>
56
+ :host {
57
+ display:block;
58
+ width:100%;
59
+ height:100%;
60
+ overflow:hidden;
61
+ }
62
+ #container {
63
+ position:relative;
64
+ width:100%;
65
+ height:100%;
66
+ letter-spacing:normal;
67
+ word-spacing:normal;
68
+ line-height:normal;
69
+ text-indent:0;
70
+ text-transform:none;
71
+ direction:ltr;
72
+ }
73
+ #dataVizDiv {
74
+ position:relative;
75
+ width:100%;
76
+ height:100%;
77
+ }
78
+ #sceneImage {
79
+ width:100%;
80
+ height:100%;
81
+ position:absolute;
82
+ outline:none;
83
+ }
84
+ #rectCanvas {
85
+ position:absolute;
86
+ top:0px;
87
+ left:0px;
88
+ }
89
+ #zoomOverlay {
90
+ position:absolute;
91
+ opacity:0;
92
+ transition:opacity ease 0.3s;
93
+ pointer-events:none;
94
+ background:var(--avs-zoom-overlay-background, rgba(80,80,80,0.75));
95
+ color:var(--avs-zoom-overlay-color, #ffffff);
96
+ border-radius:5px;
97
+ padding:5px;
98
+ transform:translate(-50%, -100%);
99
+ font-size:var(--avs-zoom-overlay-font-size, 10pt);
100
+ font-family:var(--avs-zoom-overlay-font-family);
101
+ font-weight:var(--avs-zoom-overlay-font-weight, bold);
102
+ font-style:var(--avs-zoom-overlay-font-style);
103
+ }
104
+ #tooltip {
105
+ position:absolute;
106
+ opacity:0;
107
+ transition:opacity ease 0.3s;
108
+ pointer-events:none;
109
+ padding:5px;
110
+ border-radius:5px;
111
+ background:var(--avs-tooltip-background, rgb(80,80,80));
112
+ color:var(--avs-tooltip-color, #ffffff);
113
+ box-shadow: 0px 5px 5px -3px rgba(0, 0, 0, 0.2), 0px 8px 10px 1px rgba(0, 0, 0, 0.14), 0px 3px 14px 2px rgba(0, 0, 0, 0.12);
114
+ font-size:var(--avs-tooltip-font-size, 10pt);
115
+ font-family:var(--avs-tooltip-font-family);
116
+ font-weight:var(--avs-tooltip-font-weight);
117
+ font-style:var(--avs-tooltip-font-style);
118
+ }
119
+ #spinnerDiv {
120
+ position:absolute;
121
+ left:var(--avs-spinner-left, 50%);
122
+ top:var(--avs-spinner-top, 50%);
123
+ transform:var(--avs-spinner-transform, translate(-50%,-50%));
124
+ }
125
+ #spinner {
126
+ display:none;
127
+ }
128
+ .spin {
129
+ -webkit-animation:spin 2s ease-in-out infinite;
130
+ -moz-animation:spin 2s ease-in-out infinite;
131
+ animation:spin 2s ease-in-out infinite;
132
+ }
133
+ .spinnerBackground {
134
+ fill:var(--avs-spinner-background-color, rgb(0,0,0,0));
135
+ stroke-width:0.0160303
136
+ }
137
+ @-moz-keyframes spin { 100% { -moz-transform: rotate(360deg); } }
138
+ @-webkit-keyframes spin { 100% { -webkit-transform: rotate(360deg); } }
139
+ @keyframes spin { 100% { -webkit-transform: rotate(360deg); transform:rotate(360deg); } }
140
+ </style>
141
+ <div id="container">
142
+ <div id="dataVizDiv"></div>
143
+ <div id="zoomOverlay"></div>
144
+ <div id="spinnerDiv">
145
+ <div id="spinner"></div>
146
+ </div>
147
+ <div id="tooltip"></div>
148
+ </div>
149
+ `;
150
+ }
151
+
152
+ static get properties() {
153
+ return {
154
+
155
+ /**
156
+ * Don't request a new scene upon initialization or resize.
157
+ */
158
+ manualUpdate: {
159
+ type: Boolean
160
+ },
161
+ /**
162
+ * Highlight canvas elements when using the `THREEJS` renderer.
163
+ */
164
+ displayCanvas: {
165
+ type: Boolean,
166
+ observer: "_displayCanvasChanged"
167
+ },
168
+ /**
169
+ * The URL to an instance of AVS/Go server application or file.
170
+ */
171
+ url: {
172
+ type: String
173
+ },
174
+ /**
175
+ * Enables loading JSON from a file.
176
+ */
177
+ urlLoadJsonFile: {
178
+ type: Boolean
179
+ },
180
+ /**
181
+ * The name of the scene registered in the library map on the server.
182
+ */
183
+ sceneName: {
184
+ type: String
185
+ },
186
+ /**
187
+ * User properties for the scene passed directly to the server.
188
+ */
189
+ sceneUserProperties: {
190
+ type: Object,
191
+ value: {}
192
+ },
193
+ /**
194
+ * The name of the renderer registered in the library map on the server.
195
+ */
196
+ rendererName: {
197
+ type: String
198
+ },
199
+ /**
200
+ * User properties for the renderer passed directly to the server.
201
+ */
202
+ rendererUserProperties: {
203
+ type: Object,
204
+ value: {}
205
+ },
206
+ /**
207
+ * The type of renderer to be used to display a scene: `IMAGE`, `SVG` or `THREEJS`
208
+ */
209
+ renderer: {
210
+ type: String,
211
+ value: "IMAGE",
212
+ observer: "_rendererChanged"
213
+ },
214
+ /**
215
+ * The name of the theme registered in the library map on the server, or undefined to use CSS, or one of the branded themes: `DEFAULT`, `AVS_LIGHT`, `AVS_DARK` or `AVS_BLACK`
216
+ */
217
+ themeName: {
218
+ type: String
219
+ },
220
+ /**
221
+ * Hide the data visualization.
222
+ */
223
+ hidden: {
224
+ type: Boolean,
225
+ observer: "_hiddenChanged"
226
+ },
227
+ /**
228
+ * Resize threshold (percent) to determine when the update is performed on the client or the server.
229
+ * Default is 10%. Set to zero to disable resize on the server.
230
+ */
231
+ resizeThreshold: {
232
+ type: Number,
233
+ value: 10
234
+ },
235
+ /**
236
+ * Aspect ratio (w/h) of the viewer if it is unable to determine the height of its parent element.
237
+ */
238
+ aspectRatio: {
239
+ type: Number,
240
+ value: 1.777777
241
+ },
242
+ /**
243
+ * Number of seconds between pointer moves before an `avs-pointer-timeout` event is dispatched.
244
+ */
245
+ pointerTimeout: {
246
+ type: Number,
247
+ value: 600
248
+ },
249
+ /**
250
+ * Enables the `avs-tap` event.
251
+ */
252
+ tapEnable: {
253
+ type: Boolean
254
+ },
255
+ /**
256
+ * The level of geometry within the scene to be modified by the tap event: `CELL`, `CELL_SET` or `SCENE_NODE`
257
+ */
258
+ tapLevel: {
259
+ type: String
260
+ },
261
+ /**
262
+ * The depth at which an object is selected: `ALL` or `CLOSEST`
263
+ */
264
+ tapDepth: {
265
+ type: String
266
+ },
267
+ /**
268
+ * Enables highlight of selected geometry in the scene.
269
+ */
270
+ tapHighlightEnable: {
271
+ type: Boolean
272
+ },
273
+ /**
274
+ * The color to used to highlight the selected objects in the scene.
275
+ */
276
+ tapHighlightColor: {
277
+ type: String
278
+ },
279
+ /**
280
+ * Enables drawing highlighted objects in front of all objects in the scene. This results in faster rendering in a 2D viewport when using the `THREEJS` renderer.
281
+ */
282
+ tapHighlightLayerEnable: {
283
+ type: Boolean
284
+ },
285
+ /**
286
+ * Enables the processing of tap events on the client. `THREEJS` only.
287
+ */
288
+ tapProcessEventOnClient: {
289
+ type: Boolean
290
+ },
291
+ /**
292
+ * Enables the `avs-track` event.
293
+ */
294
+ trackEnable: {
295
+ type: Boolean,
296
+ observer: "_trackEnableChanged"
297
+ },
298
+ /**
299
+ * The level of geometry within the scene to be modified by the track event: `CELL`, `CELL_SET` or `SCENE_NODE`
300
+ */
301
+ trackLevel: {
302
+ type: String
303
+ },
304
+ /**
305
+ * The depth at which an object is selected: `ALL` or `CLOSEST`
306
+ */
307
+ trackDepth: {
308
+ type: String
309
+ },
310
+ /**
311
+ * Enables highlight of selected geometry in the scene.
312
+ */
313
+ trackHighlightEnable: {
314
+ type: Boolean
315
+ },
316
+ /**
317
+ * The color to used to highlight the selected objects in the scene.
318
+ */
319
+ trackHighlightColor: {
320
+ type: String
321
+ },
322
+ /**
323
+ * Enables drawing highlighted objects in front of all objects in the scene. This results in faster rendering in a 2D viewport when using the `THREEJS` renderer.
324
+ */
325
+ trackHighlightLayerEnable: {
326
+ type: Boolean
327
+ },
328
+ /**
329
+ * Enables the processing of track events on the client. `THREEJS` only.
330
+ */
331
+ trackProcessEventOnClient: {
332
+ type: Boolean
333
+ },
334
+ /**
335
+ * Enables the `avs-hover` event.
336
+ */
337
+ hoverEnable: {
338
+ type: Boolean
339
+ },
340
+ /**
341
+ * The level of geometry within the scene to be modified by the hover event: `CELL`, `CELL_SET` or `SCENE_NODE`
342
+ */
343
+ hoverLevel: {
344
+ type: String
345
+ },
346
+ /**
347
+ * The depth at which an object is selected: `ALL` or `CLOSEST`
348
+ */
349
+ hoverDepth: {
350
+ type: String
351
+ },
352
+ /**
353
+ * Enables highlight of selected geometry in the scene.
354
+ */
355
+ hoverHighlightEnable: {
356
+ type: Boolean
357
+ },
358
+ /**
359
+ * The color to used to highlight the selected objects in the scene.
360
+ */
361
+ hoverHighlightColor: {
362
+ type: String
363
+ },
364
+ /**
365
+ * Enables drawing highlighted objects in front of all objects in the scene. This results in faster rendering in a 2D viewport when using the `THREEJS` renderer.
366
+ */
367
+ hoverHighlightLayerEnable: {
368
+ type: Boolean
369
+ },
370
+ /**
371
+ * Enable the transform interactor. Only available when `renderer` is `THREEJS`
372
+ *
373
+ * Create an interactor for transforming a particular scene object on the client.
374
+ * Use the IGoRenderer.addInteractor() method on the server to select which object to transform.
375
+ */
376
+ transformEnable: {
377
+ type: Boolean,
378
+ observer: "_transformEnableChanged"
379
+ },
380
+ /**
381
+ * Transform on the client only, do not update the transform matrix on the server.
382
+ */
383
+ transformClientOnly: {
384
+ type: Boolean,
385
+ observer: "_transformClientOnlyChanged"
386
+ },
387
+ /**
388
+ * Disables rotation of the object.
389
+ */
390
+ transformRotateDisable: {
391
+ type: Boolean,
392
+ observer: "_transformRotateDisableChanged"
393
+ },
394
+ /**
395
+ * Disables zooming of the object.
396
+ */
397
+ transformZoomDisable: {
398
+ type: Boolean,
399
+ observer: "_transformZoomDisableChanged"
400
+ },
401
+ /**
402
+ * Disables panning of the object.
403
+ */
404
+ transformPanDisable: {
405
+ type: Boolean,
406
+ observer: "_transformPanDisableChanged"
407
+ },
408
+ /**
409
+ * The twist angle of the object in degrees.
410
+ */
411
+ transformTwistAngle: {
412
+ type: Number,
413
+ observer: "_transformValueChanged"
414
+ },
415
+ /**
416
+ * The tilt angle of the object in degrees.
417
+ */
418
+ transformTiltAngle: {
419
+ type: Number,
420
+ observer: "_transformValueChanged"
421
+ },
422
+ /**
423
+ * The scale of the object in percent.
424
+ */
425
+ transformScale: {
426
+ type: Number,
427
+ observer: "_transformValueChanged"
428
+ },
429
+ /**
430
+ * Enable the zoom rectangle interactor. Only available when `renderer` is `THREEJS`
431
+ *
432
+ * Create an interactor for scaling an object by drawing a rectangle.
433
+ * Use the IGoRenderer.addInteractor() method on the server to select which object to transform.
434
+ */
435
+ zoomRectangleEnable: {
436
+ type: Boolean,
437
+ observer: "_zoomRectangleEnableChanged"
438
+ },
439
+ /**
440
+ * Enable the pan interactor. Only available when `renderer` is `THREEJS`
441
+ *
442
+ * Create an interactor for panning an OpenViz domain (axes and charts) on the client.
443
+ */
444
+ panEnable: {
445
+ type: Boolean,
446
+ observer: "_panEnableChanged"
447
+ },
448
+ /**
449
+ * Use mousewheel or pinch zoom to adjust the pan interactor's zoom level.
450
+ * Otherwise the zoom level must be set using `pan-width-zoom-level` and `pan-height-zoom-level`.
451
+ */
452
+ panZoomEnable: {
453
+ type: Boolean,
454
+ observer: "_panZoomEnableChanged"
455
+ },
456
+ /**
457
+ * The width zoom level in percent of the original scene greater than 100%
458
+ */
459
+ panWidthZoomLevel: {
460
+ type: Number,
461
+ observer: "_panWidthZoomLevelChanged"
462
+ },
463
+ /**
464
+ * The height zoom level in percent of the original scene greater than 100%
465
+ */
466
+ panHeightZoomLevel: {
467
+ type: Number,
468
+ observer: "_panHeightZoomLevelChanged"
469
+ },
470
+ /**
471
+ * The maximum zoom level in percent of the original scene greater than 100%
472
+ * Default is 1000%
473
+ */
474
+ panMaximumZoomLevel: {
475
+ type: Number,
476
+ observer: "_panMaximumZoomLevelChanged",
477
+ value: 1000
478
+ },
479
+ /**
480
+ * Show animated glyphs. Only available when `renderer` is `THREEJS`
481
+ */
482
+ animatedGlyphsVisible: {
483
+ type: Boolean,
484
+ observer: "_animatedGlyphsVisibleChanged"
485
+ },
486
+ /**
487
+ * Enable animated glyphs. Only available when `renderer` is `THREEJS`
488
+ */
489
+ animatedGlyphsEnable: {
490
+ type: Boolean,
491
+ observer: "_animatedGlyphsEnableChanged"
492
+ }
493
+ }
494
+ }
495
+
496
+ /**
497
+ * Default line style and color
498
+ */
499
+ _rectangleStyle() {
500
+ this.rectCtx.setLineDash([3]);
501
+ this.rectCtx.strokeStyle="#ff0000";
502
+ }
503
+
504
+ /**
505
+ * Assemble the model from our properties to send to the server.
506
+ */
507
+ _assembleModel(fullReset) {
508
+ if (this.sceneName === undefined) {
509
+ this._logError( JSON.stringify( {"GoType":1, "error":"\'scene-name\' property must be set to the name of the scene registered in the library map on the server."} ) );
510
+ return undefined;
511
+ }
512
+
513
+ var model = {};
514
+
515
+ // Scene Properties
516
+ var sceneProperties = {name:this.sceneName};
517
+ if (this.sceneUserProperties !== undefined) {
518
+ sceneProperties.userProperties = this.sceneUserProperties;
519
+ }
520
+ model.sceneProperties = sceneProperties;
521
+
522
+ // Renderer Properties
523
+ var rendererProperties = {width:this.width, height:this.height, name:this.rendererName, type:this.renderer};
524
+ if (this.rendererUserProperties !== undefined) {
525
+ rendererProperties.userProperties = this.rendererUserProperties;
526
+ }
527
+ model.rendererProperties = rendererProperties;
528
+
529
+ // Transform Properties
530
+ if (this.transformInteractor !== undefined) {
531
+ // Update the local transform matrix from the transform interactor, we may have transformed since the last request
532
+ this.transformMatrix = this.transformInteractor.object.matrix.elements.slice();
533
+ this.transformClientOnly = this.transformInteractor.clientOnly;
534
+ }
535
+ if (this.transformMatrix !== undefined && !this.transformClientOnly) {
536
+ rendererProperties.transformMatrix = this.transformMatrix;
537
+ }
538
+ if (fullReset !== undefined) {
539
+ if (this.transformClientOnly && this.transformInteractor !== undefined) {
540
+ this.transformInteractor.fullReset = fullReset;
541
+ }
542
+ else {
543
+ rendererProperties.fullReset = true;
544
+ }
545
+ }
546
+
547
+ // PanInteractor
548
+ if (this.panEnable) {
549
+ rendererProperties.panProperties = {widthZoomLevel: this.panWidthZoomLevel, heightZoomLevel: this.panHeightZoomLevel};
550
+ }
551
+
552
+ // Base theme to use from themeName property
553
+ rendererProperties.themeName = this.themeName;
554
+
555
+ var style = window.getComputedStyle(this, null);
556
+
557
+ // Theme Properties from page CSS
558
+ var cssBackgroundColor = style.getPropertyValue("background-color").trim();
559
+ var cssColor = style.getPropertyValue("color").trim();
560
+ var cssFontFamily = style.getPropertyValue("font-family").trim().replace(/['"]+/g, '');
561
+ rendererProperties.cssProperties = {
562
+ sceneBackgroundType: "Solid",
563
+ sceneBackgroundColor: cssBackgroundColor,
564
+ sceneLineColor: cssColor,
565
+ sceneTextColor: cssColor,
566
+ sceneFontFamily: cssFontFamily,
567
+ sceneSurfaceColor: cssColor
568
+ };
569
+
570
+ // Theme Properties from custom CSS
571
+ this._applyCustomCssProperties(rendererProperties.cssProperties, style,
572
+ {
573
+ // Scene
574
+ "sceneBackgroundType": "--avs-scene-background-type",
575
+ "sceneBackgroundColor": "--avs-scene-background-color",
576
+ "sceneBackgroundStartColor": "--avs-scene-background-start-color",
577
+ "sceneBackgroundEndColor": "--avs-scene-background-end-color",
578
+ "sceneBackgroundGradientStyle": "--avs-scene-background-gradient-style",
579
+ "sceneBackgroundGradientInterpolation": "--avs-scene-background-gradient-interpolation",
580
+ "sceneBackgroundGradientColorRepeat": "--avs-scene-background-gradient-color-repeat",
581
+ "sceneHighlightColor": "--avs-scene-highlight-color",
582
+ "sceneSurfaceColor": "--avs-scene-surface-color",
583
+ "scenePointColor": "--avs-scene-point-color",
584
+ "sceneLineColor": "--avs-scene-line-color",
585
+ "sceneLineWidth": "--avs-scene-line-width",
586
+ "sceneLineOpacity": "--avs-scene-line-opacity",
587
+ "sceneTextColor": "--avs-scene-text-color",
588
+ "sceneTextRotation": "--avs-scene-text-rotation",
589
+ "sceneFontFamily": "--avs-scene-font-family",
590
+ "sceneFontStyle": "--avs-scene-font-style",
591
+ "sceneFontWeight": "--avs-scene-font-weight",
592
+ "sceneFontSize": "--avs-scene-font-size",
593
+ // Scene title
594
+ "sceneTitleTextColor": "--avs-scene-title-text-color",
595
+ "sceneTitleTextRotation": "--avs-scene-title-text-rotation",
596
+ "sceneTitleFontFamily": "--avs-scene-title-font-family",
597
+ "sceneTitleFontStyle": "--avs-scene-title-font-style",
598
+ "sceneTitleFontWeight": "--avs-scene-title-font-weight",
599
+ "sceneTitleFontSize": "--avs-scene-title-font-size",
600
+ // Chart
601
+ "chartBackgroundType": "--avs-chart-background-type",
602
+ "chartBackgroundColor": "--avs-chart-background-color",
603
+ "chartBackgroundStartColor": "--avs-chart-background-start-color",
604
+ "chartBackgroundEndColor": "--avs-chart-background-end-color",
605
+ "chartBackgroundGradientStyle": "--avs-chart-background-gradient-style",
606
+ "chartBackgroundGradientInterpolation": "--avs-chart-background-gradient-interpolation",
607
+ "chartBackgroundGradientColorRepeat": "--avs-chart-background-gradient-color-repeat",
608
+ "chartHighlightColor": "--avs-chart-highlight-color",
609
+ "chartSurfaceColor": "--avs-chart-surface-color",
610
+ "chartPointColor": "--avs-chart-point-color",
611
+ "chartLineColor": "--avs-chart-line-color",
612
+ "chartLineWidth": "--avs-chart-line-width",
613
+ "chartLinePattern": "--avs-chart-line-pattern",
614
+ "chartLineOpacity": "--avs-chart-line-opacity",
615
+ "chartTextColor": "--avs-chart-text-color",
616
+ "chartTextRotation": "--avs-chart-text-rotation",
617
+ "chartFontFamily": "--avs-chart-font-family",
618
+ "chartFontStyle": "--avs-chart-font-style",
619
+ "chartFontWeight": "--avs-chart-font-weight",
620
+ "chartFontSize": "--avs-chart-font-size",
621
+ // Chart title
622
+ "chartTitleTextColor": "--avs-chart-title-text-color",
623
+ "chartTitleTextRotation": "--avs-chart-title-text-rotation",
624
+ "chartTitleFontFamily": "--avs-chart-title-font-family",
625
+ "chartTitleFontStyle": "--avs-chart-title-font-style",
626
+ "chartTitleFontWeight": "--avs-chart-title-font-weight",
627
+ "chartTitleFontSize": "--avs-chart-title-font-size",
628
+ // Axis
629
+ "axisLineColor": "--avs-axis-line-color",
630
+ "axisLineWidth": "--avs-axis-line-width",
631
+ "axisLineOpacity": "--avs-axis-line-opacity",
632
+ "axisTextColor": "--avs-axis-text-color",
633
+ "axisTextRotation": "--avs-axis-text-rotation",
634
+ "axisFontFamily": "--avs-axis-font-family",
635
+ "axisFontStyle": "--avs-axis-font-style",
636
+ "axisFontWeight": "--avs-axis-font-weight",
637
+ "axisFontSize": "--avs-axis-font-size",
638
+ // Axis axle
639
+ "axisAxleColor": "--avs-axis-axle-color",
640
+ "axisAxleWidth": "--avs-axis-axle-width",
641
+ // Axis tick mark
642
+ "axisTickMarkColor": "--avs-axis-tick-mark-color",
643
+ "axisTickMarkWidth": "--avs-axis-tick-mark-width",
644
+ // Axis tick line
645
+ "axisTickLineColor": "--avs-axis-tick-line-color",
646
+ "axisTickLineWidth": "--avs-axis-tick-line-width",
647
+ "axisTickLineStyle": "--avs-axis-tick-line-style",
648
+ // Axis title
649
+ "axisTitleTextColor": "--avs-axis-title-text-color",
650
+ "axisTitleTextRotation": "--avs-axis-title-text-rotation",
651
+ "axisTitleFontFamily": "--avs-axis-title-font-family",
652
+ "axisTitleFontStyle": "--avs-axis-title-font-style",
653
+ "axisTitleFontWeight": "--avs-axis-title-font-weight",
654
+ "axisTitleFontSize": "--avs-axis-title-font-size",
655
+ // Axis unit
656
+ "axisUnitTextColor": "--avs-axis-unit-text-color",
657
+ "axisUnitTextRotation": "--avs-axis-unit-text-rotation",
658
+ "axisUnitFontFamily": "--avs-axis-unit-font-family",
659
+ "axisUnitFontStyle": "--avs-axis-unit-font-style",
660
+ "axisUnitFontWeight": "--avs-axis-unit-font-weight",
661
+ "axisUnitFontSize": "--avs-axis-unit-font-size",
662
+ // Axis labels
663
+ "axisLabelTextColor": "--avs-axis-label-text-color",
664
+ "axisLabelTextRotation": "--avs-axis-label-text-rotation",
665
+ "axisLabelFontFamily": "--avs-axis-label-font-family",
666
+ "axisLabelFontStyle": "--avs-axis-label-font-style",
667
+ "axisLabelFontWeight": "--avs-axis-label-font-weight",
668
+ "axisLabelFontSize": "--avs-axis-label-font-size",
669
+ // Legend
670
+ "legendBackgroundColor": "--avs-legend-background-color",
671
+ "legendTextColor": "--avs-legend-text-color",
672
+ "legendTextRotation": "--avs-legend-text-rotation",
673
+ "legendFontFamily": "--avs-legend-font-family",
674
+ "legendFontStyle": "--avs-legend-font-style",
675
+ "legendFontWeight": "--avs-legend-font-weight",
676
+ "legendFontSize": "--avs-legend-font-size",
677
+ // Legend title
678
+ "legendTitleTextColor": "--avs-legend-title-text-color",
679
+ "legendTitleTextRotation": "--avs-legend-title-text-rotation",
680
+ "legendTitleFontFamily": "--avs-legend-title-font-family",
681
+ "legendTitleFontStyle": "--avs-legend-title-font-style",
682
+ "legendTitleFontWeight": "--avs-legend-title-font-weight",
683
+ "legendTitleFontSize": "--avs-legend-title-font-size",
684
+ // Defaults
685
+ "defaultPointSize": "--avs-default-point-size",
686
+ "defaultGlyphSize": "--avs-default-glyph-size",
687
+ "minGlyphSize": "--avs-min-glyph-size",
688
+ "maxGlyphSize": "--avs-max-glyph-size"
689
+ } );
690
+
691
+ this._addDataSourceProperties(model);
692
+
693
+ if (this.renderer === 'THREEJS') {
694
+ this._addStreamProperties(rendererProperties);
695
+
696
+ var styleMap = {};
697
+ this._applyCustomCssProperties(styleMap, style,
698
+ {
699
+ "scene": "--avs-scene-animations",
700
+ "sceneTitle": "--avs-scene-title-animations",
701
+ "chart": "--avs-chart-animations",
702
+ "chartTitle": "--avs-chart-title-animations",
703
+ "axis": "--avs-axis-animations",
704
+ "legend": "--avs-legend-animations",
705
+ "legendTitle": "--avs-legend-title-animations",
706
+ "glyph": "--avs-glyph-animations",
707
+ "transform": "--avs-transform-animation"
708
+ } );
709
+ this.animator.setStyleMap(styleMap);
710
+ }
711
+
712
+ return model;
713
+ }
714
+
715
+ /**
716
+ *
717
+ */
718
+ _applyCustomCssProperties(cssProperties, style, values) {
719
+ for (var key in values) {
720
+ if (values.hasOwnProperty(key)) {
721
+ var css = style.getPropertyValue(values[key]).trim();
722
+ if (css.length > 0) {
723
+ cssProperties[key] = css;
724
+ }
725
+ }
726
+ }
727
+ }
728
+
729
+ /**
730
+ *
731
+ */
732
+ _onResize() {
733
+ if (!this.urlLoadJsonFile &&
734
+ !this.manualUpdate &&
735
+ this.resizeThreshold > 0 &&
736
+ (this.clientWidth < this.lowResizeWidth ||
737
+ this.clientWidth > this.highResizeWidth ||
738
+ this.clientHeight < this.lowResizeHeight ||
739
+ this.clientHeight > this.highResizeHeight)) {
740
+
741
+ this.updateViewer();
742
+ }
743
+ else {
744
+ this._updateViewerClient();
745
+ }
746
+ }
747
+
748
+ /**
749
+ *
750
+ */
751
+ _updateSize() {
752
+ // Get the width provided by our container
753
+ this.width = this.clientWidth;
754
+ if (this.width <= 0) {
755
+ this.width = 200; // fallback if clientWidth fails
756
+ this.$.container.style.width = this.width + "px";
757
+ }
758
+ else {
759
+ this.$.container.style.width = "100%";
760
+ }
761
+
762
+ // Get the height provided by our container
763
+ this.height = this.clientHeight;
764
+ if (this.height <= 0) {
765
+ if (this.aspectRatio > 0.1) {
766
+ // Use the aspect ratio if one is set
767
+ this.height = this.width / this.aspectRatio;
768
+ }
769
+ else {
770
+ this.height = 200; // fallback if clientHeight fails
771
+ }
772
+ this.$.container.style.height = this.height + "px";
773
+ }
774
+ else {
775
+ this.$.container.style.height = "100%";
776
+ }
777
+
778
+ if (this.rectCanvas) {
779
+ this.rectCanvas.width = this.width;
780
+ this.rectCanvas.height = this.height;
781
+ }
782
+ }
783
+
784
+ showSpinner() {
785
+ var spinner = window.getComputedStyle(this, null).getPropertyValue("--avs-spinner").trim().replace(/['"]+/g, '');
786
+ if (spinner.length > 0) {
787
+ fetch(spinner)
788
+ .then((response) => {
789
+ if (!response.ok) {
790
+ throw new Error(response);
791
+ }
792
+ return response.text();
793
+ })
794
+ .then((html) => {
795
+ this.$.spinner.innerHTML = html;
796
+ })
797
+ .catch((error) => {
798
+ this.$.spinner.innerHTML = '';
799
+ });
800
+ }
801
+ else {
802
+ this.$.spinner.innerHTML = LOGO;
803
+ }
804
+
805
+ this.$.spinner.style.display = 'block';
806
+ }
807
+
808
+ hideSpinner() {
809
+ this.$.spinner.style.display = 'none';
810
+ }
811
+
812
+ startSpinner() {
813
+ this.$.spinner.className = 'spin';
814
+ }
815
+
816
+ stopSpinner() {
817
+ this.$.spinner.className = '';
818
+ }
819
+
820
+ /**
821
+ * Send the request to the server.
822
+ */
823
+ updateViewer(fullReset) {
824
+ this._updateSize();
825
+
826
+ this.lowResizeWidth = (100 - this.resizeThreshold) / 100 * this.width;
827
+ this.highResizeWidth = (100 + this.resizeThreshold) / 100 * this.width;
828
+ this.lowResizeHeight = (100 - this.resizeThreshold) / 100 * this.height;
829
+ this.highResizeHeight = (100 + this.resizeThreshold) / 100 * this.height;
830
+
831
+ this.showSpinner();
832
+ if (this.url !== undefined && this.url !== null) {
833
+ this.startSpinner();
834
+
835
+ // Use avs-http-mixin to send the model to the server
836
+ if (this.urlLoadJsonFile) {
837
+ this.chunkFile = 0;
838
+ this._httpRequest(this.url, this._handleHttpResponse.bind(this), undefined, this._handleHttpError.bind(this));
839
+ }
840
+ else {
841
+ var model = this._assembleModel(fullReset);
842
+ if (model !== undefined) {
843
+ this._httpRequest(this.url, this._handleHttpResponse.bind(this), undefined, this._handleHttpError.bind(this), model);
844
+ }
845
+ }
846
+ }
847
+ }
848
+
849
+ /**
850
+ * HTTP error handler.
851
+ * @param event
852
+ */
853
+ _handleHttpError(event) {
854
+ this.hideSpinner();
855
+ }
856
+
857
+ /**
858
+ *
859
+ */
860
+ _updateViewerClient() {
861
+ this._updateSize();
862
+ if (this.renderer === 'THREEJS') {
863
+ this.threeViewer.render(true);
864
+ }
865
+ }
866
+
867
+ /**
868
+ *
869
+ */
870
+ clear() {
871
+ if (this.renderer === 'THREEJS') {
872
+ this.threeViewer.clearGeometry();
873
+ this.threeViewer.render();
874
+ }
875
+ else if (this.renderer === 'SVG') {
876
+ var el = this.svgDiv;
877
+ while (el.firstChild) el.removeChild(el.firstChild);
878
+ }
879
+ else {
880
+ this.sceneImage.src = 'data:,';
881
+ }
882
+
883
+ this.showSpinner();
884
+ }
885
+
886
+ /**
887
+ * HTTP response handler.
888
+ * @param json JSON parsed from HTTP response.
889
+ */
890
+ _handleHttpResponse(json) {
891
+ var loadComplete = true;
892
+
893
+ if (json !== undefined) {
894
+
895
+ if (json.selectionInfo !== undefined) {
896
+ this._dispatchPickEvents(json.selectionInfo);
897
+ }
898
+
899
+ if (json.sceneInfo !== undefined) {
900
+ var sceneEvent = {detail: json.sceneInfo};
901
+ /**
902
+ * Scene info from the server.
903
+ * @event avs-scene-info
904
+ */
905
+ this.dispatchEvent(new CustomEvent('avs-scene-info', sceneEvent));
906
+
907
+ // Set tooltip and zoom overlay style to reversed theme
908
+ if (json.sceneInfo.backgroundColor !== undefined) {
909
+ var col = json.sceneInfo.backgroundColor.match(/[0-9.]+/gi);
910
+ var bgCol = window.getComputedStyle(this.parentNode, null).getPropertyValue("background-color").trim().match(/[0-9.]+/gi);
911
+ var blendedR = (col[0] * col[3]);
912
+ var blendedG = (col[1] * col[3]);
913
+ var blendedB = (col[2] * col[3]);
914
+ if (bgCol) {
915
+ // In case sceneInfo.backgroundColor is transparent, blend with our parent's background color
916
+ blendedR += (bgCol[0] * (1 - col[3]));
917
+ blendedG += (bgCol[1] * (1 - col[3]));
918
+ blendedB += (bgCol[2] * (1 - col[3]));
919
+ }
920
+ this.$.zoomOverlay.style.color = "var(--avs-zoom-overlay-color, rgb(" + blendedR + "," + blendedG + "," + blendedB + "))";
921
+ this.$.tooltip.style.color = "var(--avs-tooltip-color, rgb(" + blendedR + "," + blendedG + "," + blendedB + "))";
922
+ }
923
+ if (json.sceneInfo.color !== undefined) {
924
+ var col = json.sceneInfo.color.match(/[0-9.]+/gi);
925
+ this.$.zoomOverlay.style.background = "var(--avs-zoom-overlay-background, rgba(" + col[0] + "," + col[1] + "," + col[2] + "))";
926
+ this.$.tooltip.style.background = "var(--avs-tooltip-background, rgb(" + col[0] + "," + col[1] + "," + col[2] + "))";
927
+ }
928
+ if (json.sceneInfo.fontFamily !== undefined) {
929
+ this.$.zoomOverlay.style.fontFamily = "var(--avs-zoom-overlay-font-family, " + json.sceneInfo.fontFamily + ")";
930
+ this.$.tooltip.style.fontFamily = "var(--avs-tooltip-font-family, " + json.sceneInfo.fontFamily + ")";
931
+ }
932
+ }
933
+
934
+ if (json.image !== undefined) {
935
+
936
+ if (json.image.startsWith("?app=image")) {
937
+ this.sceneImage.src = this.url + json.image;
938
+ }
939
+ else {
940
+ this.sceneImage.src = json.image;
941
+ }
942
+
943
+ if (json.imagemap !== undefined) {
944
+ this.sceneImageMap.innerHTML = decodeURIComponent(json.imagemap.replace(/\+/g, '%20'));
945
+
946
+ this.imageMapData = Array.from(this.sceneImageMap.querySelectorAll('area')).map(area => {
947
+ return {
948
+ shape: area.getAttribute('shape'),
949
+ coords: area.getAttribute('coords').split(',').map(Number),
950
+ seriesIndex: area.getAttribute('series-index'),
951
+ itemIndex: area.getAttribute('item-index'),
952
+ componentInfo: area.getAttribute('component-info')
953
+ };
954
+ });
955
+ }
956
+ else {
957
+ this.sceneImageMap.innerHTML = "";
958
+ this.imageMapData = undefined;
959
+ }
960
+ }
961
+ else if (json.svg !== undefined) {
962
+ this.svgDiv.innerHTML = decodeURIComponent(json.svg.replace(/\+/g, '%20'));
963
+ }
964
+ else if (json.threejs !== undefined) {
965
+ this.threeViewer.loadGeometryAsJson(json.threejs);
966
+ }
967
+ else if (json.chunkId !== undefined) {
968
+ this.threeViewer.loadGeometryAsEvents(json);
969
+
970
+ if (json.moreChunks === true) {
971
+ if (this.urlLoadJsonFile) {
972
+ this.chunkFile++;
973
+ const urlBase = this.url.substring(0, this.url.lastIndexOf('.')) || this.url;
974
+ const ext = this.url.split('.').pop();
975
+ this._httpRequest(urlBase + '-' + this.chunkFile + '.' + ext, this._handleHttpResponse.bind(this), undefined, this._handleHttpError.bind(this));
976
+ }
977
+ else {
978
+ var model = this._assembleModel();
979
+ if (model !== undefined) {
980
+ model.rendererProperties.streamProperties.chunkId = json.chunkId;
981
+ this._httpRequest(this.url, this._handleHttpResponse.bind(this), undefined, this._handleHttpError.bind(this), model);
982
+ }
983
+ }
984
+ loadComplete = false;
985
+ }
986
+ }
987
+ else if (this.urlLoadJsonFile) {
988
+ this.threeViewer.loadGeometryAsJson(json);
989
+ }
990
+ }
991
+
992
+ if (loadComplete) {
993
+ // Hide the spinner and grab the scene background color for next time
994
+ // Disable background temporarily
995
+ this.hideSpinner();
996
+ this.stopSpinner();
997
+ /* if (json.backgroundColor !== undefined) {
998
+ this.updateStyles({'--avs-spinner-background-color': json.backgroundColor});
999
+ }*/
1000
+
1001
+ /**
1002
+ * Scene load has completed.
1003
+ * @event avs-load-complete
1004
+ */
1005
+ this.dispatchEvent(new CustomEvent('avs-load-complete'));
1006
+ }
1007
+ }
1008
+
1009
+ /**
1010
+ * @param e
1011
+ */
1012
+ _handleTap(e) {
1013
+ var adjustedCoords = this._getAdjustedCoords(e.detail.x, e.detail.y);
1014
+
1015
+ var pickProperties = {type:"TAP", x:adjustedCoords.x, y:adjustedCoords.y};
1016
+
1017
+ if (this.tapLevel !== undefined) pickProperties.level = this.tapLevel;
1018
+ if (this.tapDepth !== undefined) pickProperties.depth = this.tapDepth;
1019
+ if (this.tapHighlightEnable) pickProperties.highlight = true;
1020
+ if (this.tapHighlightColor !== undefined) pickProperties.highlightColor = this.tapHighlightColor;
1021
+ if (this.tapHighlightLayerEnable) pickProperties.highlightLayer = true;
1022
+
1023
+ this._processPick( pickProperties, this.tapProcessEventOnClient, e.originalTarget );
1024
+ }
1025
+
1026
+ /**
1027
+ * @param e
1028
+ */
1029
+ _handleTrack(e) {
1030
+ var adjustedCoords = this._getAdjustedRectangleCoords(e);
1031
+
1032
+ switch(e.detail.state) {
1033
+ case 'start':
1034
+ break;
1035
+
1036
+ case 'track':
1037
+ this.rectCtx.clearRect(0,0,this.width,this.height);
1038
+ this._rectangleStyle();
1039
+ this.rectCtx.strokeRect(adjustedCoords.left, adjustedCoords.top, adjustedCoords.right - adjustedCoords.left, adjustedCoords.bottom - adjustedCoords.top);
1040
+ break;
1041
+
1042
+ case 'end':
1043
+ this.rectCtx.clearRect(0,0,this.width,this.height);
1044
+
1045
+ var pickProperties = {type:"TRACK"};
1046
+ pickProperties.left = adjustedCoords.left;
1047
+ pickProperties.right = adjustedCoords.right;
1048
+ pickProperties.top = adjustedCoords.top;
1049
+ pickProperties.bottom = adjustedCoords.bottom;
1050
+
1051
+ if (this.trackLevel !== undefined) pickProperties.level = this.trackLevel;
1052
+ if (this.trackDepth !== undefined) pickProperties.depth = this.trackDepth;
1053
+ if (this.trackHighlightEnable) pickProperties.highlight = true;
1054
+ if (this.trackHighlightColor !== undefined) pickProperties.highlightColor = this.trackHighlightColor;
1055
+ if (this.trackHighlightLayerEnable) pickProperties.highlightLayer = true;
1056
+
1057
+ this._processPick( pickProperties, this.trackProcessEventOnClient );
1058
+ break;
1059
+ }
1060
+ }
1061
+
1062
+ /**
1063
+ * @param e
1064
+ */
1065
+ _handlePointerDown(e) {
1066
+ this.pointerDownX = e.clientX;
1067
+ this.pointerDownY = e.clientY;
1068
+
1069
+ this.pointerDown = true;
1070
+
1071
+ if (this.tapEnable && e.buttons & 1) {
1072
+ this.tapping = true;
1073
+ }
1074
+
1075
+ if (this.trackEnable && e.buttons & 2) {
1076
+ this.tracking = 1;
1077
+ }
1078
+ }
1079
+
1080
+ /**
1081
+ * @param e
1082
+ */
1083
+ _handlePointerMove(e) {
1084
+ if (this.tracking >= 1) {
1085
+ if (this.tracking === 1) {
1086
+ var dx = Math.abs(e.clientX - this.pointerDownX);
1087
+ var dy = Math.abs(e.clientY - this.pointerDownY);
1088
+ if (dx*dx + dy*dy >= 5) {
1089
+ this.tracking = 2;
1090
+ this._handleTrack({detail:{state:"start", x:e.clientX, y:e.clientY, dx:e.clientX-this.pointerDownX, dy:e.clientY-this.pointerDownY}});
1091
+ }
1092
+ }
1093
+ if (this.tracking === 2) {
1094
+ this._handleTrack({detail:{state:"track", x:e.clientX, y:e.clientY, dx:e.clientX-this.pointerDownX, dy:e.clientY-this.pointerDownY}});
1095
+ }
1096
+ }
1097
+
1098
+ if (this.hoverEnable) {
1099
+ var adjustedCoords = this._getAdjustedCoords(e.clientX, e.clientY);
1100
+ var pickProperties = {type:"HOVER", x:adjustedCoords.x, y:adjustedCoords.y};
1101
+
1102
+ if (this.pointerDown) {
1103
+ pickProperties.selected = {};
1104
+ this._dispatchPickEvents( pickProperties );
1105
+ }
1106
+ else {
1107
+ if (this.hoverLevel !== undefined) pickProperties.level = this.hoverLevel;
1108
+ if (this.hoverDepth !== undefined) pickProperties.depth = this.hoverDepth;
1109
+ if (this.hoverHighlightEnable) pickProperties.highlight = true;
1110
+ if (this.hoverHighlightColor !== undefined) pickProperties.highlightColor = this.hoverHighlightColor;
1111
+ if (this.hoverHighlightLayerEnable) pickProperties.highlightLayer = true;
1112
+
1113
+ this._processPick( pickProperties, true, e.originalTarget );
1114
+ }
1115
+ }
1116
+
1117
+ this._resetTimer();
1118
+ }
1119
+
1120
+ /**
1121
+ * @param e
1122
+ */
1123
+ _handlePointerUp(e) {
1124
+ this.pointerDown = false;
1125
+
1126
+ if (this.tapping) {
1127
+ this.tapping = false;
1128
+ var dx = Math.abs(e.clientX - this.pointerDownX);
1129
+ var dy = Math.abs(e.clientY - this.pointerDownY);
1130
+ if (dx*dx + dy*dy < 25) {
1131
+ this._handleTap({detail:{x:e.clientX, y:e.clientY}});
1132
+ }
1133
+ }
1134
+
1135
+ if (this.tracking > 1) {
1136
+ this.tracking = 0;
1137
+ this._handleTrack({detail:{state:"end", x:e.clientX, y:e.clientY, dx:e.clientX-this.pointerDownX, dy:e.clientY-this.pointerDownY}});
1138
+ }
1139
+ }
1140
+
1141
+ _getAdjustedCoords(x, y) {
1142
+ var rect = this.$.dataVizDiv.getBoundingClientRect();
1143
+ var x = Math.round(x - rect.left);
1144
+ var y = Math.round(y - rect.top);
1145
+ var clampX = Math.max(0, Math.min(x, this.width));
1146
+ var clampY = Math.max(0, Math.min(y, this.height));
1147
+
1148
+ return {x:clampX, y:clampY};
1149
+ }
1150
+
1151
+ _getAdjustedRectangleCoords(e) {
1152
+ var rect = this.$.dataVizDiv.getBoundingClientRect();
1153
+ var x = Math.round(e.detail.x - rect.left);
1154
+ var y = Math.round(e.detail.y - rect.top);
1155
+ var clampX = Math.max(0, Math.min(x, this.width));
1156
+ var clampY = Math.max(0, Math.min(y, this.height));
1157
+ var startX = x - e.detail.dx;
1158
+ var startY = y - e.detail.dy;
1159
+
1160
+ var left = Math.min(startX, clampX);
1161
+ var right = Math.max(startX, clampX);
1162
+ var top = Math.min(startY, clampY);
1163
+ var bottom = Math.max(startY, clampY);
1164
+
1165
+ return {left: left, right: right, top: top, bottom: bottom};
1166
+ }
1167
+
1168
+ _processPick( pickProperties, processEventOnClient, originalTarget ) {
1169
+ if (processEventOnClient) {
1170
+ if (this.renderer === 'THREEJS') {
1171
+ // ThreeJS client side pick processing
1172
+
1173
+ this.threeViewer.setPickDepth( this._getPickDepth(pickProperties.depth) );
1174
+ if (pickProperties.type === 'TRACK') {
1175
+ this.threeViewer.setPickRectangle( pickProperties.left, pickProperties.top, pickProperties.right, pickProperties.bottom );
1176
+ }
1177
+ else {
1178
+ this.threeViewer.setPickRay( pickProperties.x, pickProperties.y );
1179
+ }
1180
+ this.threeViewer.pick();
1181
+
1182
+ var selectionList = {};
1183
+ if (pickProperties.level === "CELL") {
1184
+ selectionList = this.threeViewer.getPickedCells();
1185
+ }
1186
+ else if (pickProperties.level === "CELL_SET") {
1187
+ selectionList = this.threeViewer.getPickedCellSets();
1188
+ }
1189
+ else {
1190
+ selectionList = this.threeViewer.getPickedSceneNodes();
1191
+ }
1192
+
1193
+ pickProperties.selected = this.threeViewer.getSelectionInfo(selectionList);
1194
+ this._dispatchPickEvents(pickProperties);
1195
+
1196
+ if (pickProperties.highlight) {
1197
+ this.threeViewer.highlightColor.set( pickProperties.highlightColor );
1198
+ this.threeViewer.highlightObjects( selectionList, pickProperties.highlightLayer );
1199
+ }
1200
+ }
1201
+ else if (this.renderer === 'SVG') {
1202
+ // Client side SVG pick processing
1203
+
1204
+ pickProperties.selected = [];
1205
+
1206
+ if (pickProperties.type !== 'TRACK' && (originalTarget.nodeName === "polygon" || originalTarget.nodeName === "circle")) {
1207
+ var selectedInfo = {};
1208
+
1209
+ var seriesIndex = null;
1210
+ var element = originalTarget.parentElement;
1211
+ while (element !== null && (seriesIndex = element.getAttribute("series-index")) === null) {
1212
+ element = element.parentElement;
1213
+ }
1214
+ if (seriesIndex !== null) {
1215
+ selectedInfo.seriesIndex = parseInt(seriesIndex);
1216
+ }
1217
+
1218
+ var itemIndex = null;
1219
+ element = originalTarget.parentElement;
1220
+ while (element !== null && (itemIndex = element.getAttribute("item-index")) === null) {
1221
+ element = element.parentElement;
1222
+ }
1223
+ if (itemIndex !== null) {
1224
+ selectedInfo.itemIndex = parseInt(itemIndex);
1225
+ }
1226
+
1227
+ var componentInfo = null;
1228
+ element = originalTarget.parentElement;
1229
+ while (element !== null && (componentInfo = element.getAttribute("component-info")) === null) {
1230
+ element = element.parentElement;
1231
+ }
1232
+ if (componentInfo !== null) {
1233
+ selectedInfo.componentInfo = decodeURIComponent(componentInfo);
1234
+ }
1235
+
1236
+ pickProperties.selected.push(selectedInfo);
1237
+ }
1238
+
1239
+ this._dispatchPickEvents(pickProperties);
1240
+
1241
+ if (pickProperties.highlight) {
1242
+ if (this.highlightSvg === undefined) {
1243
+ this.highlightSvg = [];
1244
+ }
1245
+
1246
+ for (var i = 0; i < this.highlightSvg.length; i++) {
1247
+ this.highlightSvg[i].setAttribute("fill", this.highlightSvg[i].getAttribute("saveFill"));
1248
+ }
1249
+ this.highlightSvg.length = 0;
1250
+
1251
+ if (pickProperties.type !== 'TRACK' && (originalTarget.nodeName === "polygon" || originalTarget.nodeName === "circle")) {
1252
+ this.highlightSvg.push(originalTarget);
1253
+ originalTarget.setAttribute("saveFill", originalTarget.getAttribute("fill"));
1254
+ originalTarget.setAttribute("fill", pickProperties.highlightColor);
1255
+ }
1256
+ }
1257
+ }
1258
+ else {
1259
+ // Client side imagemap pick processing
1260
+
1261
+ pickProperties.selected = [];
1262
+
1263
+ if (pickProperties.type !== 'TRACK' && this.imageMapData !== undefined) {
1264
+ for (var i = 0; i < this.imageMapData.length; i++) {
1265
+ var area = this.imageMapData[i];
1266
+ if (area.shape === "poly" && this._pointInPoly(pickProperties.x, pickProperties.y, area.coords) !== false) {
1267
+
1268
+ var selectedInfo = {};
1269
+ if (area.seriesIndex !== null) {
1270
+ selectedInfo.seriesIndex = parseInt(area.seriesIndex);
1271
+ }
1272
+ if (area.itemIndex !== null) {
1273
+ selectedInfo.itemIndex = parseInt(area.itemIndex);
1274
+ }
1275
+ if (area.componentInfo !== null) {
1276
+ selectedInfo.componentInfo = decodeURIComponent(area.componentInfo);
1277
+ }
1278
+ pickProperties.selected.push(selectedInfo);
1279
+ }
1280
+ }
1281
+ }
1282
+
1283
+ this._dispatchPickEvents(pickProperties);
1284
+ }
1285
+ }
1286
+ else if (!this.urlLoadJsonFile) {
1287
+ // Server side pick processing
1288
+
1289
+ this.showSpinner();
1290
+ if (this.url !== undefined && this.url !== null) {
1291
+ this.startSpinner();
1292
+
1293
+ // Use avs-http-mixin to send the model to the server
1294
+ var model = this._assembleModel();
1295
+ if (model !== undefined) {
1296
+ model.rendererProperties.pickProperties = pickProperties;
1297
+ this._httpRequest(this.url, this._handleHttpResponse.bind(this), undefined, this._handleHttpError.bind(this), model);
1298
+ }
1299
+ }
1300
+ }
1301
+ }
1302
+
1303
+ _pointInPoly(x, y, coords) {
1304
+ var dx1 = coords[0] - x;
1305
+ var dy1 = coords[1] - y;
1306
+ var dx2, dy2, f;
1307
+ var k = 0;
1308
+
1309
+ for (var i=2; i < coords.length; i+=2) {
1310
+
1311
+ dy2 = coords[i+1] - y;
1312
+
1313
+ if ((dy1 < 0 && dy2 < 0) || (dy1 > 0 && dy2 > 0)) {
1314
+ dy1 = dy2;
1315
+ dx1 = coords[i] - x;
1316
+ continue;
1317
+ }
1318
+
1319
+ dx2 = coords[i] - x;
1320
+
1321
+ if (dy2 > 0 && dy1 <= 0) {
1322
+ f = (dx1 * dy2) - (dx2 * dy1);
1323
+ if (f > 0) k++;
1324
+ else if (f === 0) return 0;
1325
+ }
1326
+ else if (dy1 > 0 && dy2 <= 0) {
1327
+ f = (dx1 * dy2) - (dx2 * dy1);
1328
+ if (f < 0) k++;
1329
+ else if (f === 0) return 0;
1330
+ }
1331
+ else if (dy2 === 0 && dy1 < 0) {
1332
+ f = (dx1 * dy2) - (dx2 * dy1);
1333
+ if (f === 0) return 0;
1334
+ }
1335
+ else if (dy1 === 0 && dy2 < 0) {
1336
+ f = dx1 * dy2 - dx2 * dy1;
1337
+ if (f === 0) return 0;
1338
+ }
1339
+ else if (dy1 === 0 && dy2 === 0) {
1340
+ if (dx2 <= 0 && dx1 >= 0) {
1341
+ return 0;
1342
+ }
1343
+ else if (dx1 <= 0 && dx2 >= 0) {
1344
+ return 0;
1345
+ }
1346
+ }
1347
+
1348
+ dy1 = dy2;
1349
+ dx1 = dx2;
1350
+ }
1351
+
1352
+ if (k % 2 === 0) return false;
1353
+ return true;
1354
+ }
1355
+
1356
+ /**
1357
+ * @param strValue
1358
+ */
1359
+ _getPickDepth( strValue ) {
1360
+ if (strValue == "ALL") {
1361
+ return PickDepthEnum.All;
1362
+ }
1363
+ else {
1364
+ return PickDepthEnum.Closest;
1365
+ }
1366
+ }
1367
+
1368
+ /**
1369
+ * Dispatch the appropriate tap, track or hover event.
1370
+ */
1371
+ _dispatchPickEvents(pickProperties) {
1372
+
1373
+ var pickEvent = {detail: {selected: pickProperties.selected}};
1374
+ if (pickProperties.type === 'TRACK') {
1375
+ pickEvent.detail.left = pickProperties.left;
1376
+ pickEvent.detail.top = pickProperties.top;
1377
+ pickEvent.detail.right = pickProperties.right;
1378
+ pickEvent.detail.bottom = pickProperties.bottom;
1379
+
1380
+ /**
1381
+ * A track event occurred.
1382
+ * @event avs-track
1383
+ */
1384
+ this.dispatchEvent(new CustomEvent('avs-track', pickEvent));
1385
+ }
1386
+ else {
1387
+ pickEvent.detail.x = pickProperties.x;
1388
+ pickEvent.detail.y = pickProperties.y;
1389
+
1390
+ if (pickProperties.type === 'HOVER') {
1391
+ /**
1392
+ * A hover event occurred.
1393
+ * @event avs-hover
1394
+ */
1395
+ this.dispatchEvent(new CustomEvent('avs-hover', pickEvent));
1396
+ }
1397
+ else {
1398
+ /**
1399
+ * A tap event occurred.
1400
+ * @event avs-tap
1401
+ */
1402
+ this.dispatchEvent(new CustomEvent('avs-tap', pickEvent));
1403
+ }
1404
+ }
1405
+ }
1406
+
1407
+ _resetTimer() {
1408
+ clearTimeout(this.timer);
1409
+ this.timer = setTimeout(function() {
1410
+ /**
1411
+ * A pointer timeout event occurred.
1412
+ * @event avs-pointer-timeout
1413
+ */
1414
+ this.dispatchEvent(new Event('avs-pointer-timeout'));
1415
+ }.bind(this), this.pointerTimeout * 1000);
1416
+ }
1417
+
1418
+ /**
1419
+ *
1420
+ */
1421
+ connectedCallback() {
1422
+ super.connectedCallback();
1423
+
1424
+ // Make sure all CSS and layout has been processed
1425
+ afterNextRender(this, function() {
1426
+ if (this.initialized !== true) {
1427
+
1428
+ this._updateSize();
1429
+ if (!this.manualUpdate) {
1430
+ this.updateViewer(true);
1431
+ }
1432
+
1433
+ this.addEventListener('iron-resize', this._onResize);
1434
+ this._updatePixelRatio();
1435
+
1436
+ this.addEventListener('pointerdown', this._handlePointerDown);
1437
+ this.addEventListener('pointerup', this._handlePointerUp);
1438
+ this.addEventListener('pointermove', this._handlePointerMove);
1439
+ this.addEventListener('pointerout', this._handlePointerMove);
1440
+
1441
+ var scope = this;
1442
+ this.addEventListener('contextmenu', function(e) {
1443
+ if (scope.trackEnable) {
1444
+ e.preventDefault();
1445
+ }
1446
+ });
1447
+
1448
+ this._resetTimer();
1449
+
1450
+ this.initialized = true;
1451
+ }
1452
+ });
1453
+ }
1454
+
1455
+ _updatePixelRatio(change) {
1456
+ const pr = window.devicePixelRatio;
1457
+ matchMedia( `(resolution: ${pr}dppx)` ).addEventListener('change', this._updatePixelRatio.bind(this, true), { once: true } );
1458
+ if (change) {
1459
+ this.updateViewer();
1460
+ }
1461
+ }
1462
+
1463
+ /**
1464
+ * Change in 'hidden' property.
1465
+ */
1466
+ _hiddenChanged(newValue, oldValue) {
1467
+ if (newValue) {
1468
+ this.$.dataVizDiv.style.display = 'none';
1469
+ }
1470
+ else {
1471
+ this.$.dataVizDiv.style.display = '';
1472
+ if (this.threeViewer) {
1473
+ this.threeViewer.render();
1474
+ }
1475
+ }
1476
+ }
1477
+
1478
+ /**
1479
+ * Change in 'transform-enable' property.
1480
+ */
1481
+ _transformEnableChanged(newValue, oldValue) {
1482
+ if (this.threeViewer) {
1483
+ if (newValue) {
1484
+ if (this.transformInteractor === undefined) {
1485
+ this.transformInteractor = new TransformInteractor( this );
1486
+ }
1487
+ this.threeViewer.addInteractor( this.transformInteractor );
1488
+
1489
+ if (this.transformRotateDisable) {
1490
+ this.transformInteractor.enableRotate = false;
1491
+ }
1492
+ if (this.transformZoomDisable) {
1493
+ this.transformInteractor.enableZoom = false;
1494
+ }
1495
+ if (this.transformPanDisable) {
1496
+ this.transformInteractor.enablePan = false;
1497
+ }
1498
+ if (this.transformClientOnly) {
1499
+ this.transformInteractor.clientOnly = true;
1500
+ }
1501
+ }
1502
+ else {
1503
+ this.threeViewer.removeInteractor( this.transformInteractor );
1504
+ }
1505
+ }
1506
+ }
1507
+
1508
+ /**
1509
+ * Change in the 'transform-client-only' property.
1510
+ */
1511
+ _transformClientOnlyChanged(newValue, oldValue) {
1512
+ if (this.transformInteractor) {
1513
+ this.transformInteractor.clientOnly = newValue;
1514
+ }
1515
+ if (this.zoomRectangleInteractor) {
1516
+ this.zoomRectangleInteractor.clientOnly = newValue;
1517
+ }
1518
+ }
1519
+
1520
+ /**
1521
+ * Change in 'transform-rotate-disable' property.
1522
+ */
1523
+ _transformRotateDisableChanged(newValue, oldValue) {
1524
+ if (this.transformInteractor) {
1525
+ this.transformInteractor.enableRotate = !newValue;
1526
+ }
1527
+ }
1528
+
1529
+ /**
1530
+ * Change in 'transform-zoom-disable' property.
1531
+ */
1532
+ _transformZoomDisableChanged(newValue, oldValue) {
1533
+ if (this.transformInteractor) {
1534
+ this.transformInteractor.enableZoom = !newValue;
1535
+ }
1536
+ }
1537
+
1538
+ /**
1539
+ * Change in 'transform-pan-disable' property.
1540
+ */
1541
+ _transformPanDisableChanged(newValue, oldValue) {
1542
+ if (this.transformInteractor) {
1543
+ this.transformInteractor.enablePan = !newValue;
1544
+ }
1545
+ }
1546
+
1547
+ /**
1548
+ * Reset the transform interactor.
1549
+ */
1550
+ resetTransform() {
1551
+ if (this.transformInteractor) {
1552
+ this.transformInteractor.reset();
1553
+ }
1554
+ }
1555
+
1556
+ /**
1557
+ * Perform a zoom in using the transform interactor.
1558
+ */
1559
+ zoomIn() {
1560
+ if (this.transformInteractor) {
1561
+ this.transformInteractor.zoomIn();
1562
+ }
1563
+ }
1564
+
1565
+ /**
1566
+ * Perform a zoom out using the transform interactor.
1567
+ */
1568
+ zoomOut() {
1569
+ if (this.transformInteractor) {
1570
+ this.transformInteractor.zoomOut();
1571
+ }
1572
+ }
1573
+
1574
+ /**
1575
+ * Perform a pan to center the specified coordinate of the transformed object in the center of the scene.
1576
+ */
1577
+ panTo(x, y, z) {
1578
+ if (this.transformInteractor) {
1579
+ this.transformInteractor.panTo(x, y, z);
1580
+ }
1581
+ }
1582
+
1583
+ getTransformComponents() {
1584
+ var pos = new Vector3();
1585
+ var quat = new Quaternion();
1586
+ var scale = new Vector3();
1587
+ var euler = new Euler();
1588
+ var mat;
1589
+ if (this.transformInteractor) {
1590
+ mat = this.transformInteractor.object.matrix;
1591
+ }
1592
+ mat.decompose(pos, quat, scale);
1593
+ euler.setFromQuaternion(quat);
1594
+ return {
1595
+ position: pos.toArray(),
1596
+ rotation: [euler.x * 180 / Math.PI, euler.y * 180 / Math.PI, euler.z * 180 / Math.PI, euler.order],
1597
+ scale: 100 * scale.x
1598
+ };
1599
+ }
1600
+
1601
+ getTransformMatrix() {
1602
+ if (this.transformInteractor) {
1603
+ return this.transformInteractor.object.matrix.elements.slice();
1604
+ }
1605
+ }
1606
+
1607
+ runAnimation() {
1608
+
1609
+ var style = window.getComputedStyle(this, null);
1610
+
1611
+ if (this.renderer === 'THREEJS') {
1612
+ var styleMap = {};
1613
+ this._applyCustomCssProperties(styleMap, style,
1614
+ {
1615
+ "scene": "--avs-scene-animations",
1616
+ "sceneTitle": "--avs-scene-title-animations",
1617
+ "chart": "--avs-chart-animations",
1618
+ "chartTitle": "--avs-chart-title-animations",
1619
+ "axis": "--avs-axis-animations",
1620
+ "legend": "--avs-legend-animations",
1621
+ "legendTitle": "--avs-legend-title-animations",
1622
+ "glyph": "--avs-glyph-animations",
1623
+ "transform": "--avs-transform-animation"
1624
+ } );
1625
+ this.animator.setStyleMap(styleMap);
1626
+ this.threeViewer.runAnimation();
1627
+ }
1628
+ }
1629
+
1630
+ /**
1631
+ * Change in 'animated-glyphs-visible' property.
1632
+ */
1633
+ _animatedGlyphsVisibleChanged(newValue, oldValue) {
1634
+ if (this.renderer === 'THREEJS') {
1635
+ this.threeViewer.setVisibleAnimatedGlyphs(newValue);
1636
+ }
1637
+ }
1638
+
1639
+ /**
1640
+ * Change in 'animated-glyphs-enable' property.
1641
+ */
1642
+ _animatedGlyphsEnableChanged(newValue, oldValue) {
1643
+ if (this.renderer === 'THREEJS') {
1644
+ this.threeViewer.setEnableAnimatedGlyphs(newValue);
1645
+ }
1646
+ }
1647
+
1648
+ /**
1649
+ * Change in 'transform-twist-angle', 'transform-tilt-angle' or 'transform-scale' properties.
1650
+ */
1651
+ _transformValueChanged(newValue, oldValue) {
1652
+ var twist = this.transformTwistAngle !== undefined ? this.transformTwistAngle * Math.PI / 180 : 0;
1653
+ var tilt = this.transformTiltAngle !== undefined ? this.transformTiltAngle * Math.PI / 180 : 0;
1654
+ var scale = this.transformScale !== undefined ? this.transformScale / 100.0 : 1.0;
1655
+
1656
+ var sinTW = Math.sin(twist);
1657
+ var cosTW = Math.cos(twist);
1658
+ var sinTI = Math.sin(tilt);
1659
+ var cosTI = Math.cos(tilt);
1660
+
1661
+ var matrix = [ cosTW * scale, 0, cosTI * sinTW * scale, 0,
1662
+ 0, cosTI * scale, -sinTI * scale, 0,
1663
+ -sinTW * scale, cosTW * sinTI * scale, cosTW * cosTI * scale, 0,
1664
+ 0, 0, 0, 1 ];
1665
+
1666
+ this.transformMatrix = matrix;
1667
+ if (this.transformInteractor) {
1668
+ this.transformInteractor.object.matrix.fromArray( matrix );
1669
+ }
1670
+ }
1671
+
1672
+ /**
1673
+ * Change in 'zoom-rectangle-enable' property.
1674
+ */
1675
+ _zoomRectangleEnableChanged(newValue, oldValue) {
1676
+ if (this.threeViewer) {
1677
+ if (newValue) {
1678
+ if (this.zoomRectangleInteractor === undefined) {
1679
+ this.zoomRectangleInteractor = new ZoomRectangleInteractor( this );
1680
+ }
1681
+ this.threeViewer.addInteractor( this.zoomRectangleInteractor );
1682
+
1683
+ if (this.transformClientOnly) {
1684
+ this.zoomRectangleInteractor.clientOnly = true;
1685
+ }
1686
+ }
1687
+ else {
1688
+ this.threeViewer.removeInteractor( this.zoomRectangleInteractor );
1689
+ }
1690
+ }
1691
+ }
1692
+
1693
+ /**
1694
+ * Change in 'pan-enable' property.
1695
+ */
1696
+ _panEnableChanged(newValue, oldValue) {
1697
+ if (this.threeViewer) {
1698
+ if (newValue) {
1699
+ if (this.panInteractor === undefined) {
1700
+ this.panInteractor = new PanInteractor( this );
1701
+ }
1702
+ this.threeViewer.addInteractor( this.panInteractor );
1703
+ if (this.panZoomEnable) {
1704
+ this.panInteractor.addEventListener('change', this._handlePanChanged.bind(this));
1705
+ this.panInteractor.addEventListener('zoom', this._handlePanZoom.bind(this));
1706
+ this.panInteractor.addEventListener('zoomEnd', this._handlePanZoomEnd.bind(this));
1707
+ }
1708
+ this.panInteractor.setWidthZoomLevel(this.panWidthZoomLevel);
1709
+ this.panInteractor.setHeightZoomLevel(this.panHeightZoomLevel);
1710
+ this.panInteractor.setMaximumZoomLevel(this.panMaximumZoomLevel);
1711
+ this.panInteractor.saveState();
1712
+ }
1713
+ else {
1714
+ this.threeViewer.removeInteractor( this.panInteractor );
1715
+ if (this.panZoomEnable) {
1716
+ this.panInteractor.removeEventListener('change', this._handlePanChanged.bind(this));
1717
+ this.panInteractor.removeEventListener('zoom', this._handlePanZoom.bind(this));
1718
+ this.panInteractor.removeEventListener('zoomEnd', this._handlePanZoomEnd.bind(this));
1719
+ }
1720
+ }
1721
+ }
1722
+ }
1723
+
1724
+ /**
1725
+ * Change in 'pan-zoom-enable' property.
1726
+ */
1727
+ _panZoomEnableChanged(newValue, oldValue) {
1728
+ if (this.threeViewer && this.panInteractor) {
1729
+ if (newValue) {
1730
+ this.panInteractor.addEventListener('change', this._handlePanChanged.bind(this));
1731
+ this.panInteractor.addEventListener('zoom', this._handlePanZoom.bind(this));
1732
+ this.panInteractor.addEventListener('zoomEnd', this._handlePanZoomEnd.bind(this));
1733
+ }
1734
+ else {
1735
+ this.panInteractor.removeEventListener('change', this._handlePanChanged.bind(this));
1736
+ this.panInteractor.removeEventListener('zoom', this._handlePanZoom.bind(this));
1737
+ this.panInteractor.removeEventListener('zoomEnd', this._handlePanZoomEnd.bind(this));
1738
+ }
1739
+ }
1740
+ }
1741
+
1742
+ _handlePanChanged(e) {
1743
+ /**
1744
+ * A pan info event occurred.
1745
+ * @event avs-pan-info
1746
+ */
1747
+ this.dispatchEvent(new CustomEvent('avs-pan-info', e));
1748
+ }
1749
+
1750
+ _zoomOverlayTimeout() {
1751
+ this.$.zoomOverlay.style.opacity = 0;
1752
+ this.pointerDown = false;
1753
+ }
1754
+
1755
+ _handlePanZoom(e) {
1756
+ clearTimeout(this.zoomOverlayTimeoutId);
1757
+
1758
+ var width = Math.round(e.detail.widthZoomLevel);
1759
+ var height = Math.round(e.detail.heightZoomLevel);
1760
+ if (width === height) {
1761
+ this.$.zoomOverlay.innerHTML = width + "%";
1762
+ }
1763
+ else {
1764
+ this.$.zoomOverlay.innerHTML = width + "%," + height + "%";
1765
+ }
1766
+
1767
+ var coords = this._getAdjustedCoords(e.detail.clientX, e.detail.clientY);
1768
+ this.$.zoomOverlay.style.left = coords.x + "px";
1769
+ this.$.zoomOverlay.style.top = coords.y + "px";
1770
+ this.$.zoomOverlay.style.opacity = 1;
1771
+
1772
+ this.pointerDown = true;
1773
+ this._dispatchPickEvents( {type:"HOVER",x:0,y:0,selected:{}} );
1774
+
1775
+ this.zoomOverlayTimeoutId = setTimeout(this._zoomOverlayTimeout.bind(this), 1000);
1776
+ }
1777
+
1778
+ _handlePanZoomEnd(e) {
1779
+ if (this.initialized) {
1780
+ this.panWidthZoomLevel = e.detail.widthZoomLevel;
1781
+ this.panHeightZoomLevel = e.detail.heightZoomLevel;
1782
+ this.updateViewer();
1783
+ }
1784
+ }
1785
+
1786
+ /**
1787
+ * Change in 'pan-width-zoom-level' property.
1788
+ */
1789
+ _panWidthZoomLevelChanged(newValue, oldValue) {
1790
+ if (this.panInteractor) {
1791
+ this.panInteractor.setWidthZoomLevel(newValue);
1792
+ }
1793
+ }
1794
+
1795
+ /**
1796
+ * Change in 'pan-height-zoom-level' property.
1797
+ */
1798
+ _panHeightZoomLevelChanged(newValue, oldValue) {
1799
+ if (this.panInteractor) {
1800
+ this.panInteractor.setHeightZoomLevel(newValue);
1801
+ }
1802
+ }
1803
+
1804
+ /**
1805
+ * Change in 'pan-maximum-zoom-level' property.
1806
+ */
1807
+ _panMaximumZoomLevelChanged(newValue, oldValue) {
1808
+ if (this.panInteractor) {
1809
+ this.panInteractor.setMaximumZoomLevel(newValue);
1810
+ }
1811
+ }
1812
+
1813
+ /**
1814
+ * Reset the pan interactor.
1815
+ */
1816
+ resetPan() {
1817
+ if (this.panInteractor) {
1818
+ this.panInteractor.reset();
1819
+ }
1820
+ }
1821
+
1822
+ /**
1823
+ * Change in 'renderer' property.
1824
+ */
1825
+ _rendererChanged(newValue, oldValue) {
1826
+ if (oldValue === 'IMAGE' || oldValue === 'IMAGEURL') {
1827
+ this.sceneImage.src = 'data:,';
1828
+ this.$.dataVizDiv.removeChild(this.sceneImage);
1829
+ this.$.dataVizDiv.removeChild(this.sceneImageMap);
1830
+ }
1831
+ else if (oldValue === 'SVG') {
1832
+ var el = this.svgDiv;
1833
+ while (el.firstChild) el.removeChild(el.firstChild);
1834
+ this.$.dataVizDiv.removeChild(this.svgDiv);
1835
+ }
1836
+ else if (oldValue === 'THREEJS') {
1837
+ this.threeViewer.clearGeometry();
1838
+ this.threeViewer.render();
1839
+ this.$.dataVizDiv.removeChild(this.threeViewer.domElement);
1840
+ }
1841
+
1842
+ if (newValue === 'IMAGE' || newValue === 'IMAGEURL') {
1843
+ if (this.sceneImage === undefined) {
1844
+ this.sceneImage = document.createElement("img");
1845
+ this.sceneImage.setAttribute("id", "sceneImage");
1846
+ this.sceneImage.setAttribute("usemap", "#sceneImageMap");
1847
+
1848
+ this.sceneImageMap = document.createElement("map");
1849
+ this.sceneImageMap.setAttribute("id", "sceneImageMap");
1850
+ this.sceneImageMap.setAttribute("name", "sceneImageMap");
1851
+ }
1852
+
1853
+ this.$.dataVizDiv.appendChild(this.sceneImage);
1854
+ this.$.dataVizDiv.appendChild(this.sceneImageMap);
1855
+ }
1856
+ else if (newValue === 'SVG') {
1857
+ if (this.svgDiv === undefined) {
1858
+ this.svgDiv = document.createElement("div");
1859
+ this.svgDiv.setAttribute("id", "svgDiv");
1860
+ }
1861
+
1862
+ this.$.dataVizDiv.appendChild(this.svgDiv);
1863
+ }
1864
+ else if (newValue === 'THREEJS') {
1865
+ if (this.threeViewer === undefined) {
1866
+ // Create ThreeJS viewer
1867
+ this.threeViewer = new Viewer();
1868
+
1869
+ // Check if the user has requested a specific renderer
1870
+ var rendererId = 'avsDefaultWebGLRenderer';
1871
+ // if (this.rendererProperties.webGLRendererId !== undefined) {
1872
+ // rendererId = this.rendererProperties.webGLRendererId;
1873
+ // }
1874
+
1875
+ // Search for renderer, if not found create one and save to the DOM
1876
+ var renderer = document.getElementById(rendererId);
1877
+ if (renderer === undefined || renderer === null) {
1878
+ renderer = new AvsRenderer();
1879
+ renderer.setAttribute('id', rendererId);
1880
+ document.body.appendChild(renderer);
1881
+ // console.log("create new webGL renderer = " + rendererId);
1882
+ }
1883
+ else {
1884
+ // console.log("reference existing webGL renderer = " + rendererId);
1885
+ }
1886
+ this.threeViewer.setWebGLRenderer(renderer.webGLRenderer);
1887
+
1888
+ this.animator = new Animator();
1889
+ this.threeViewer.setAnimator(this.animator);
1890
+ }
1891
+
1892
+ this.$.dataVizDiv.appendChild(this.threeViewer.domElement);
1893
+ }
1894
+
1895
+ if (this.initialized && !this.manualUpdate) {
1896
+ this.updateViewer();
1897
+ }
1898
+ }
1899
+
1900
+ /**
1901
+ * Change in 'track-enable' property.
1902
+ */
1903
+ _trackEnableChanged(newValue, oldValue) {
1904
+ if (newValue) {
1905
+ if (this.rectCanvas === undefined) {
1906
+ this.rectCanvas = document.createElement("canvas");
1907
+ this.rectCanvas.setAttribute("id", "rectCanvas");
1908
+ this.rectCtx = this.rectCanvas.getContext('2d');
1909
+ }
1910
+ this.$.container.appendChild(this.rectCanvas);
1911
+ }
1912
+ else {
1913
+ this.$.container.removeChild(this.rectCanvas);
1914
+ }
1915
+ }
1916
+
1917
+ /**
1918
+ * Change in 'display-canvas' property.
1919
+ */
1920
+ _displayCanvasChanged(newValue, oldValue) {
1921
+ if (this.threeViewer) {
1922
+ this.threeViewer.displayCanvas = newValue;
1923
+ }
1924
+ }
1925
+
1926
+ setTooltipHTML(html) {
1927
+ this.$.tooltip.innerHTML = html;
1928
+ }
1929
+
1930
+ showTooltip(clientX, clientY) {
1931
+ var pos = this._calcTooltipPosition(clientX, clientY);
1932
+ this.$.tooltip.style.left = pos.x + "px";
1933
+ this.$.tooltip.style.top = pos.y + "px";
1934
+ this.$.tooltip.style.opacity = 1;
1935
+ }
1936
+
1937
+ hideTooltip() {
1938
+ this.$.tooltip.style.opacity = 0;
1939
+ }
1940
+
1941
+ _calcTooltipPosition(clientX, clientY) {
1942
+
1943
+ // Calculate the tooltip location based on 4 quadrants of the visible portion
1944
+ // of the visualization window
1945
+
1946
+ var offset = this._getOffset();
1947
+ var deltaTop = -Math.min(0, offset.top - window.pageYOffset);
1948
+ var deltaLeft = -Math.min(0, offset.left - window.pageXOffset);
1949
+ var deltaBottom = -Math.min(0, window.innerHeight - (this.$.dataVizDiv.offsetHeight + offset.top - window.pageYOffset));
1950
+ var deltaRight = -Math.min(0, window.innerWidth - (this.$.dataVizDiv.offsetWidth + offset.left - window.pageXOffset));
1951
+ var vizHeight = this.$.dataVizDiv.offsetHeight - deltaTop - deltaBottom;
1952
+ var vizWidth = this.$.dataVizDiv.offsetWidth - deltaLeft - deltaRight;
1953
+ var vizHalfX = vizWidth / 2 + deltaLeft;
1954
+ var vizHalfY = vizHeight / 2 + deltaTop;
1955
+
1956
+ var toolPosition = { x: 0, y: 0 };
1957
+ if (clientX < vizHalfX) {
1958
+ var offset = (clientY < vizHalfY) ? 15 : 5;
1959
+ toolPosition.x = clientX + offset + this.$.dataVizDiv.offsetLeft;
1960
+ }
1961
+ else {
1962
+ toolPosition.x = clientX - 10 + this.$.dataVizDiv.offsetLeft - this.$.tooltip.offsetWidth;
1963
+ }
1964
+ if (clientY < vizHalfY) {
1965
+ toolPosition.y = clientY + 5 + this.$.dataVizDiv.offsetTop;
1966
+ }
1967
+ else {
1968
+ toolPosition.y = clientY - 10 + this.$.dataVizDiv.offsetTop - this.$.tooltip.offsetHeight;
1969
+ }
1970
+
1971
+ return toolPosition;
1972
+ }
1973
+
1974
+ _getOffset() {
1975
+ var rect = this.$.dataVizDiv.getBoundingClientRect(),
1976
+ scrollLeft = window.pageXOffset || document.documentElement.scrollLeft,
1977
+ scrollTop = window.pageYOffset || document.documentElement.scrollTop;
1978
+ return { top: rect.top + scrollTop, left: rect.left + scrollLeft }
1979
+ }
1980
+ }
1981
+
1982
+ window.customElements.define('avs-go-dataviz', AvsGoDataViz);