@abi-software/scaffoldvuer 1.11.3 → 1.11.4-beta.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abi-software/scaffoldvuer",
3
- "version": "1.11.3",
3
+ "version": "1.11.4-beta.1",
4
4
  "license": "Apache-2.0",
5
5
  "repository": {
6
6
  "type": "git",
package/src/App.vue CHANGED
@@ -5,7 +5,7 @@
5
5
  <ScaffoldVuer
6
6
  v-if="url"
7
7
  ref="scaffold"
8
- class="vuer"
8
+ class="demo-vuer"
9
9
  :flatmapAPI="flatmapAPI"
10
10
  :display-u-i="displayUI"
11
11
  :url="url"
@@ -22,6 +22,7 @@
22
22
  :marker-cluster="markerCluster"
23
23
  :minimap-settings="minimapSettings"
24
24
  :show-colour-picker="showColourPicker"
25
+ :positionalRotation="positionalRotation"
25
26
  :render="render"
26
27
  :region="region"
27
28
  :view-u-r-l="viewURL"
@@ -48,10 +49,8 @@
48
49
  @show-next="onHelpModeShowNext"
49
50
  @finish-help-mode="onFinishHelpMode"
50
51
  />
51
-
52
52
  <el-popover popper-class="options-container" placement="bottom" trigger="click" width="500" :teleported="false">
53
53
  <div>
54
-
55
54
  <el-row :gutter="20">
56
55
  <el-col>
57
56
  <p>{{ selectedCoordinates }}</p>
@@ -191,18 +190,7 @@
191
190
  <el-col>
192
191
  <el-row :gutter="20" justify="center" align="middle">
193
192
  <el-col>
194
- <el-switch v-model="syncMode" active-text="Sync Mode" active-color="#8300bf" />
195
- </el-col>
196
- </el-row>
197
- <el-row :gutter="20" justify="center" align="middle" v-if="syncMode">
198
- <el-col :span="8">
199
- <el-input-number v-model="zoom" :min="1.0" :controls="false" placeholder="Please input" aria-label="zoom" />
200
- </el-col>
201
- <el-col :span="8">
202
- <el-input-number v-model="pos[0]" :min="-1.0" :max="1.0" :controls="false" placeholder="Please input" aria-label="x" />
203
- </el-col>
204
- <el-col :span="8">
205
- <el-input-number v-model="pos[1]" :min="-1.0" :max="1.0" :controls="false" aria-label="y" />
193
+ <el-switch v-model="positionalRotation" active-text="Rotation Helper" active-color="#8300bf" />
206
194
  </el-col>
207
195
  </el-row>
208
196
  </el-col>
@@ -312,12 +300,12 @@
312
300
  </Suspense>
313
301
  </template>
314
302
  <template #reference>
315
- <el-button class="models-button" :icon="ElIconFolderOpened">
303
+ <el-button class="models-button control-layer" :icon="ElIconFolderOpened">
316
304
  Models
317
305
  </el-button>
318
306
  </template>
319
307
  </el-popover>
320
- <el-autocomplete v-model="searchText" class="search-box" placeholder="Search" :fetch-suggestions="fetchSuggestions"
308
+ <el-autocomplete v-model="searchText" class="search-box control-layer" placeholder="Search" :fetch-suggestions="fetchSuggestions"
321
309
  :teleported="false" popper-class="autocomplete-popper" @keyup.enter="search(searchText)"
322
310
  @select="search(searchText)">
323
311
  <template #default="{ item }">
@@ -408,13 +396,13 @@ export default {
408
396
  displayMarkers: false,
409
397
  onClickMarkers: false,
410
398
  wireframe: false,
411
- syncMode: false,
412
399
  currentTime: 0,
413
400
  displayMinimap: false,
414
401
  tumbleOn: false,
415
402
  tumbleDirection: [1.0, 0.0],
416
403
  showColourPicker: true,
417
404
  markerCluster: false,
405
+ positionalRotation: true,
418
406
  minimapSettings: {
419
407
  x_offset: 16,
420
408
  y_offset: 50,
@@ -428,8 +416,6 @@ export default {
428
416
  viewURL: "",
429
417
  renderInfoOn: false,
430
418
  rendererInfo: undefined,
431
- zoom: 1,
432
- pos: [0, 0],
433
419
  format: "metadata",
434
420
  sceneSettings: [],
435
421
  searchInput: "",
@@ -488,9 +474,6 @@ export default {
488
474
  deep: true,
489
475
  immediate: true,
490
476
  },
491
- syncMode: function (val) {
492
- this.$refs.scaffold.toggleSyncControl(val);
493
- },
494
477
  helpMode: function (newVal) {
495
478
  if (!newVal) {
496
479
  this.helpModeActiveItem = 0;
@@ -879,7 +862,7 @@ body {
879
862
  }
880
863
  }
881
864
 
882
- .vuer {
865
+ .demo-vuer {
883
866
  position: absolute;
884
867
  width: 100%;
885
868
  height: 100%;
@@ -939,6 +922,10 @@ svg.map-icon {
939
922
  color: $app-primary-color;
940
923
  }
941
924
 
925
+ .control-layer {
926
+ z-index: 2;
927
+ }
928
+
942
929
  input[type="file"] {
943
930
  display: none;
944
931
  }
@@ -0,0 +1,259 @@
1
+ <template>
2
+ <div
3
+ ref="overlay"
4
+ >
5
+ <div
6
+ class="content-layer" ref="contentLayer"
7
+ @mouseleave.capture="skipWhenInBound"
8
+ @mousedown.capture="(event) => contentMouseActive(event, true)"
9
+ @mouseup.capture="(event) => contentMouseActive(event, false)"
10
+ @touchstart.capture="(event) => contentMouseActive(event, true)"
11
+ @touchend.capture="(event) => contentMouseActive(event, false)"
12
+ >
13
+ <slot />
14
+ </div>
15
+ <div v-if="positionalRotation" ref="topLayer"
16
+ @mousemove.capture="forwardEvent"
17
+ @mouseover.capture="forwardEvent"
18
+ @touchmove.capture="forwardTouchEvent"
19
+ @click.capture="forwardEvent"
20
+ >
21
+ <div
22
+ :class="['rotation-overlay', 'top', touchActive ? 'touch-active' : '']"
23
+ @mousedown="(event) => {setRotationMode(event, 'vertical'); forwardEvent(event)}"
24
+ @mouseup="forwardEvent"
25
+ @touchstart="(event) => {setRotationMode(event, 'vertical'); forwardTouchEvent(event)}"
26
+ @touchend="forwardTouchEvent"
27
+ >
28
+ <span>Begin interaction here to rotate on the x-axis</span>
29
+ </div>
30
+ <div
31
+ :class="['rotation-overlay', 'bottom', touchActive ? 'touch-active' : '']"
32
+ @mousedown="(event) => {setRotationMode(event, 'vertical'); forwardEvent(event)}"
33
+ @mouseup="forwardEvent"
34
+ @touchstart="(event) => {setRotationMode(event, 'vertical'); forwardTouchEvent(event)}"
35
+ @touchend="forwardTouchEvent"
36
+ >
37
+ <span>Begin interaction here to rotate on the x-axis</span>
38
+ </div>
39
+ <div
40
+ :class="['rotation-overlay', 'left', touchActive ? 'touch-active' : '']"
41
+ @mousedown="(event) => {setRotationMode(event, 'horizontal'); forwardEvent(event)}"
42
+ @mouseup="forwardEvent"
43
+ @touchstart="(event) => {setRotationMode(event, 'horizontal'); forwardTouchEvent(event)}"
44
+ @touchend="forwardTouchEvent"
45
+ >
46
+ <span>Begin interaction here to rotate on the y-axis</span>
47
+ </div>
48
+ <div
49
+ :class="['rotation-overlay', 'right', touchActive ? 'touch-active' : '']"
50
+ @mousedown="(event) => {setRotationMode(event, 'horizontal'); forwardEvent(event)}"
51
+ @mouseup="forwardEvent"
52
+ @touchstart="(event) => {setRotationMode(event, 'horizontal'); forwardTouchEvent(event)}"
53
+ @touchend="forwardTouchEvent"
54
+ >
55
+ <span>Begin interaction here to rotate on the y-axis</span>
56
+ </div>
57
+ </div>
58
+
59
+ </div>
60
+ </template>
61
+
62
+ <script>
63
+ /* eslint-disable no-alert, no-console */
64
+
65
+ export default {
66
+ name: "ScaffoldOverlay",
67
+ data: function () {
68
+ return {
69
+ lockRotationMode: false,
70
+ touchActive: false,
71
+ }
72
+ },
73
+ props: {
74
+ /**
75
+ * Experimental feature to restrict rotation at
76
+ * one-axis based on position of the initial click
77
+ */
78
+ positionalRotation: {
79
+ type: Boolean,
80
+ default: false,
81
+ },
82
+ },
83
+ methods: {
84
+ contentMouseActive: function(event, flag) {
85
+ if (this.positionalRotation) {
86
+ const topLayer = this.$refs.topLayer;
87
+ if (topLayer) {
88
+ if (!flag) {
89
+ this.lockRotationMode = false;
90
+ this.setRotationMode(undefined, "free");
91
+ topLayer.style.pointerEvents = 'auto';
92
+ if (event.type === "touchend") {
93
+ this.touchActive = false;
94
+ }
95
+ }
96
+ else {
97
+ this.lockRotationMode = true;
98
+ topLayer.style.pointerEvents = 'none';
99
+ if (event.type === "touchstart") {
100
+ this.touchActive = true;
101
+ }
102
+ }
103
+ }
104
+ }
105
+ },
106
+ setRotationMode: function(event, mode) {
107
+ if (!this.lockRotationMode) {
108
+ this.$emit('onRotationModeChange', mode);
109
+ }
110
+ if (event) {
111
+ event.preventDefault();
112
+ event.stopPropagation();
113
+ }
114
+ },
115
+ skipWhenInBound: function(event) {
116
+ if (this.positionalRotation) {
117
+ const topLayer = this.$refs.topLayer;
118
+ const contentLayer = this.$refs.contentLayer;
119
+ if (topLayer && contentLayer) {
120
+ const pointerEvents = topLayer.style.pointerEvents;
121
+ topLayer.style.pointerEvents = 'none';
122
+ const elementBelow = document.elementFromPoint(event.clientX, event.clientY);
123
+ topLayer.style.pointerEvents = pointerEvents;
124
+ if (contentLayer.contains(elementBelow)) {
125
+ event.stopPropagation();
126
+ }
127
+ }
128
+ }
129
+ },
130
+ forwardEvent: function(event) {
131
+ const topLayer = this.$refs.topLayer;
132
+ if (!topLayer) return;
133
+ // Find the element directly underneath the cursor
134
+ const pointerEvents = topLayer.style.pointerEvents;
135
+ topLayer.style.pointerEvents = 'none';
136
+ const elementBelow = document.elementFromPoint(event.clientX, event.clientY);
137
+ //const elementBelow = this.$el;
138
+ topLayer.style.pointerEvents = pointerEvents;
139
+ //const elementBelow = this.$refs.contentLayer;
140
+ // Hide the top layer from pointer events
141
+ // If there's an element below, dispatch a new event on it
142
+ if (elementBelow) {
143
+ // We create a new MouseEvent, copying the properties from the original event.
144
+ // This is more robust than dispatching the original event itself.
145
+ const newEvent = new MouseEvent(
146
+ event.type,
147
+ {
148
+ bubbles: event.bubbles,
149
+ cancelable: event.cancelable,
150
+ view: event.view,
151
+ clientX: event.clientX,
152
+ clientY: event.clientY,
153
+ button: event.button,
154
+ }
155
+ );
156
+ elementBelow.dispatchEvent(newEvent);
157
+ event.stopPropagation();
158
+ }
159
+ event.preventDefault();
160
+ },
161
+ forwardTouchEvent: function(event) {
162
+ const topLayer = this.$refs.topLayer;
163
+ if (!topLayer) return;
164
+ // Find the element directly underneath the cursor
165
+ const pointerEvents = topLayer.style.pointerEvents;
166
+ topLayer.style.pointerEvents = 'none';
167
+ const firstTouch = event.changedTouches[0];
168
+ const clientX = firstTouch.clientX;
169
+ const clientY = firstTouch.clientY;
170
+ const elementBelow = document.elementFromPoint(clientX, clientY);
171
+ topLayer.style.pointerEvents = pointerEvents;
172
+ if (elementBelow) {
173
+ const newTouch = new Touch({
174
+ identifier: firstTouch.identifier,
175
+ target: elementBelow,
176
+ clientX: firstTouch.clientX,
177
+ clientY: firstTouch.clientY,
178
+ pageX: firstTouch.pageX,
179
+ pageY: firstTouch.pageY,
180
+ screenX: firstTouch.screenX,
181
+ screenY: firstTouch.screenY,
182
+ radiusX: firstTouch.radiusX,
183
+ radiusY: firstTouch.radiusY,
184
+ rotationAngle: firstTouch.rotationAngle,
185
+ force: firstTouch.force,
186
+ });
187
+ const newEvent = new TouchEvent(
188
+ event.type,
189
+ {
190
+ bubbles: event.bubbles,
191
+ cancelable: event.cancelable,
192
+ composed: true,
193
+ view: event.view,
194
+ touches: [newTouch],
195
+ targetTouches: [newTouch],
196
+ changedTouches: [newTouch],
197
+ }
198
+ );
199
+ elementBelow.dispatchEvent(newEvent);
200
+ event.stopPropagation();
201
+ }
202
+ event.preventDefault();
203
+ }
204
+ }
205
+ }
206
+ </script>
207
+
208
+ <style scoped lang="scss">
209
+ .rotation-overlay {
210
+ z-index: 1;
211
+ background-color: transparent;
212
+ position:absolute;
213
+ opacity: 0;
214
+ &.touch-active {
215
+ opacity: 1;
216
+ background-color: rgba(173,216,230, 0.1)
217
+ }
218
+ &:hover {
219
+ opacity: 1;
220
+ background-color: rgba(173,216,230, 0.1)
221
+ }
222
+ &.top {
223
+ top:0%;
224
+ height:20%;
225
+ left: 35%;
226
+ width: 30%;
227
+ }
228
+ &.bottom {
229
+ bottom:0%;
230
+ height:20%;
231
+ left: 35%;
232
+ width: 30%;
233
+ }
234
+ &.left {
235
+ top:35%;
236
+ height:30%;
237
+ left: 0%;
238
+ width: 20%;
239
+ }
240
+ &.right {
241
+ top:35%;
242
+ height:30%;
243
+ right: 0%;
244
+ width: 20%;
245
+ }
246
+ span {
247
+ position: relative;
248
+ color:black;
249
+ opacity:0.5;
250
+ top: 50%;
251
+ }
252
+ }
253
+
254
+ .content-layer {
255
+ width: 100%;
256
+ height: 100%;
257
+ }
258
+
259
+ </style>
@@ -1,10 +1,12 @@
1
1
  <template>
2
- <div
2
+ <scaffold-overlay
3
3
  ref="scaffoldContainer"
4
4
  v-loading="loading"
5
5
  class="scaffold-container"
6
6
  element-loading-text="Loading..."
7
7
  element-loading-background="rgba(0, 0, 0, 0.3)"
8
+ :positionalRotation="positionalRotation"
9
+ @onRotationModeChange="setRotationMode"
8
10
  >
9
11
  <map-svg-sprite-color />
10
12
  <scaffold-tooltip
@@ -33,6 +35,7 @@
33
35
  <div v-show="displayUI && !isTransitioning">
34
36
  <DrawToolbar
35
37
  v-if="viewingMode === 'Annotation' && (authorisedUser || offlineAnnotationEnabled)"
38
+ class="control-layer"
36
39
  :toolbarOptions="toolbarOptions"
37
40
  :activeDrawTool="activeDrawTool"
38
41
  :activeDrawMode="activeDrawMode"
@@ -55,7 +58,7 @@
55
58
  <template #reference>
56
59
  <div
57
60
  v-if="displayWarning"
58
- class="message-icon warning-icon"
61
+ class="message-icon warning-icon control-layer"
59
62
  @mouseover="showHelpText(7)"
60
63
  @mouseout="hideHelpText(7)"
61
64
  >
@@ -77,7 +80,7 @@
77
80
  <template #reference>
78
81
  <div
79
82
  v-if="displayLatestChanges && latestChangesMessage"
80
- class="el-icon-warning message-icon latest-changesicon"
83
+ class="el-icon-warning message-icon latest-changesicon control-layer"
81
84
  @mouseover="showHelpText(8)"
82
85
  @mouseout="hideHelpText(8)"
83
86
  >
@@ -98,6 +101,7 @@
98
101
  >
99
102
  <template #reference>
100
103
  <ScaffoldTreeControls
104
+ class="control-layer"
101
105
  ref="scaffoldTreeControls"
102
106
  :isReady="isReady"
103
107
  :show-colour-picker="enableColourPicker"
@@ -109,6 +113,7 @@
109
113
  </el-popover>
110
114
  <div class="primitive-controls-box">
111
115
  <primitive-controls
116
+ class="control-layer"
112
117
  ref="primitiveControls"
113
118
  :createData="createData"
114
119
  :viewingMode="viewingMode"
@@ -130,7 +135,7 @@
130
135
  <template #reference>
131
136
  <div
132
137
  v-if="timeVarying"
133
- class="time-slider-container"
138
+ class="time-slider-container control-layer"
134
139
  :class="[minimisedSlider ? 'minimised' : '', sliderPosition]"
135
140
  >
136
141
  <el-tabs type="card">
@@ -199,7 +204,7 @@
199
204
  </div>
200
205
  </template>
201
206
  </el-popover>
202
- <div class="bottom-right-control">
207
+ <div class="bottom-right-control control-layer">
203
208
  <el-popover
204
209
  :visible="hoverVisibilities[0].value"
205
210
  content="Zoom in"
@@ -296,7 +301,7 @@
296
301
  popper-class="background-popper non-selectable h-auto"
297
302
  virtual-triggering
298
303
  >
299
- <div>
304
+ <div class="control-layer">
300
305
  <el-row class="backgroundText">Viewing Mode</el-row>
301
306
  <el-row class="backgroundControl">
302
307
  <div style="margin-bottom: 2px;">
@@ -360,7 +365,7 @@
360
365
  </div>
361
366
  </el-popover>
362
367
  <div
363
- class="settings-group"
368
+ class="settings-group control-layer"
364
369
  :class="{ open: drawerOpen, close: !drawerOpen }"
365
370
  >
366
371
  <el-row v-if="showOpenMapButton">
@@ -410,7 +415,7 @@
410
415
  </el-row>
411
416
  </div>
412
417
  </div>
413
- </div>
418
+ </scaffold-overlay>
414
419
  </template>
415
420
 
416
421
  <script>
@@ -422,6 +427,7 @@ import {
422
427
  ArrowLeft as ElIconArrowLeft,
423
428
  } from '@element-plus/icons-vue'
424
429
  import PrimitiveControls from "./PrimitiveControls.vue";
430
+ import ScaffoldOverlay from "./ScaffoldOverlay.vue";
425
431
  import ScaffoldTooltip from "./ScaffoldTooltip.vue";
426
432
  import ScaffoldTreeControls from "./ScaffoldTreeControls.vue";
427
433
  import { MapSvgIcon, MapSvgSpriteColor } from "@abi-software/svg-sprite";
@@ -489,6 +495,7 @@ export default {
489
495
  Radio,
490
496
  RadioGroup,
491
497
  Row,
498
+ ScaffoldOverlay,
492
499
  Select,
493
500
  Slider,
494
501
  TabPane,
@@ -684,6 +691,14 @@ export default {
684
691
  type: Boolean,
685
692
  default: false,
686
693
  },
694
+ /**
695
+ * Experimental feature to restrict rotation at
696
+ * one-axis based on position of the initial click
697
+ */
698
+ positionalRotation: {
699
+ type: Boolean,
700
+ default: false,
701
+ },
687
702
  /**
688
703
  * Define what is considered as nerves.
689
704
  */
@@ -1027,7 +1042,7 @@ export default {
1027
1042
  this.$module.initialiseRenderer(this.$refs.display);
1028
1043
  this.toggleRendering(this.render);
1029
1044
  this.ro = new ResizeObserver(this.adjustLayout).observe(
1030
- this.$refs.scaffoldContainer
1045
+ this.$refs.scaffoldContainer.$el
1031
1046
  );
1032
1047
  this.helpTextWait = [];
1033
1048
  this.helpTextWait.length = this.hoverVisibilities.length;
@@ -1567,6 +1582,13 @@ export default {
1567
1582
  }
1568
1583
  }
1569
1584
  },
1585
+ setRotationMode: function(mode) {
1586
+ if (this.$module.scene) {
1587
+ console.log("here", mode)
1588
+ const cameracontrol = this.$module.scene.getZincCameraControls();
1589
+ cameracontrol.setRotationMode(mode);
1590
+ }
1591
+ },
1570
1592
  updateViewURL: function (viewURL) {
1571
1593
  if (viewURL) {
1572
1594
  if (this.isReady) {
@@ -1819,7 +1841,7 @@ export default {
1819
1841
  if (event.identifiers.length > 0 && event.identifiers[0]) {
1820
1842
  if (event.identifiers[0].coords) {
1821
1843
  const offsets =
1822
- this.$refs.scaffoldContainer.getBoundingClientRect();
1844
+ this.$refs.scaffoldContainer.$el.getBoundingClientRect();
1823
1845
  this.tData.x = event.identifiers[0].coords.x - offsets.left;
1824
1846
  this.tData.y = event.identifiers[0].coords.y - offsets.top;
1825
1847
  }
@@ -2778,8 +2800,8 @@ export default {
2778
2800
  * Callback using ResizeObserver.
2779
2801
  */
2780
2802
  adjustLayout: function () {
2781
- if (this.$refs.scaffoldContainer) {
2782
- let width = this.$refs.scaffoldContainer.clientWidth;
2803
+ if (this.$refs.scaffoldContainer?.$el) {
2804
+ let width = this.$refs.scaffoldContainer.$el.clientWidth;
2783
2805
  this.minimisedSlider = width < 812;
2784
2806
  if (this.minimisedSlider) {
2785
2807
  this.sliderPosition = this.drawerOpen ? "right" : "left";
@@ -2892,6 +2914,10 @@ export default {
2892
2914
  }
2893
2915
  }
2894
2916
 
2917
+ .control-layer {
2918
+ z-index: 2;
2919
+ }
2920
+
2895
2921
  .time-slider-container {
2896
2922
  text-align: left;
2897
2923
  position: absolute;
@@ -36,6 +36,7 @@ declare module 'vue' {
36
36
  PrimitiveControls: typeof import('./components/PrimitiveControls.vue')['default']
37
37
  RouterLink: typeof import('vue-router')['RouterLink']
38
38
  RouterView: typeof import('vue-router')['RouterView']
39
+ ScaffoldOverlay: typeof import('./components/ScaffoldOverlay.vue')['default']
39
40
  ScaffoldTooltip: typeof import('./components/ScaffoldTooltip.vue')['default']
40
41
  ScaffoldTreeControls: typeof import('./components/ScaffoldTreeControls.vue')['default']
41
42
  ScaffoldVuer: typeof import('./components/ScaffoldVuer.vue')['default']