@qispace/vue3-player 0.0.5

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 (160) hide show
  1. package/README.md +18 -0
  2. package/dist/components/apartmentChooser/QiApartmentChooser.vue.d.ts +4 -0
  3. package/dist/components/apartmentChooser/QiApartmentChooser.vue.d.ts.map +1 -0
  4. package/dist/components/apartmentChooser/QiApartmentChooserNavigation.vue.d.ts +4 -0
  5. package/dist/components/apartmentChooser/QiApartmentChooserNavigation.vue.d.ts.map +1 -0
  6. package/dist/components/apartmentChooser/QiApartmentChooserRaster.vue.d.ts +4 -0
  7. package/dist/components/apartmentChooser/QiApartmentChooserRaster.vue.d.ts.map +1 -0
  8. package/dist/components/apartmentChooser/QiApartmentChooserRotator.vue.d.ts +4 -0
  9. package/dist/components/apartmentChooser/QiApartmentChooserRotator.vue.d.ts.map +1 -0
  10. package/dist/components/apartmentChooser/QiApartmentChooserSvg.vue.d.ts +4 -0
  11. package/dist/components/apartmentChooser/QiApartmentChooserSvg.vue.d.ts.map +1 -0
  12. package/dist/components/buildingPicker/QiBuildingChooser.vue.d.ts +3 -0
  13. package/dist/components/buildingPicker/QiBuildingChooser.vue.d.ts.map +1 -0
  14. package/dist/components/buildingPicker/QiBuildingChooserRaster.vue.d.ts +4 -0
  15. package/dist/components/buildingPicker/QiBuildingChooserRaster.vue.d.ts.map +1 -0
  16. package/dist/components/buildingPicker/QiBuildingChooserRasterOverlay.vue.d.ts +4 -0
  17. package/dist/components/buildingPicker/QiBuildingChooserRasterOverlay.vue.d.ts.map +1 -0
  18. package/dist/components/buildingPicker/QiBuildingChooserSceneImageStack.vue.d.ts +4 -0
  19. package/dist/components/buildingPicker/QiBuildingChooserSceneImageStack.vue.d.ts.map +1 -0
  20. package/dist/components/buildingPicker/QiBuildingChooserSunSimControl.vue.d.ts +5 -0
  21. package/dist/components/buildingPicker/QiBuildingChooserSunSimControl.vue.d.ts.map +1 -0
  22. package/dist/components/buildingPicker/QiBuildingChooserSvg.vue.d.ts +4 -0
  23. package/dist/components/buildingPicker/QiBuildingChooserSvg.vue.d.ts.map +1 -0
  24. package/dist/components/index.d.ts +4 -0
  25. package/dist/components/shared/QiFloatingCard.vue.d.ts +4 -0
  26. package/dist/components/shared/QiFloatingCard.vue.d.ts.map +1 -0
  27. package/dist/components/shared/QiHoverProbe.vue.d.ts +4 -0
  28. package/dist/components/shared/QiHoverProbe.vue.d.ts.map +1 -0
  29. package/dist/components/shared/QiNorthDirection.vue.d.ts +3 -0
  30. package/dist/components/shared/QiNorthDirection.vue.d.ts.map +1 -0
  31. package/dist/components/shared/QiZoomBox.vue.d.ts +4 -0
  32. package/dist/components/shared/QiZoomBox.vue.d.ts.map +1 -0
  33. package/dist/components/virtualTourV2/Disclaimer.vue.d.ts +4 -0
  34. package/dist/components/virtualTourV2/Disclaimer.vue.d.ts.map +1 -0
  35. package/dist/components/virtualTourV2/FullScreenButton.vue.d.ts +3 -0
  36. package/dist/components/virtualTourV2/FullScreenButton.vue.d.ts.map +1 -0
  37. package/dist/components/virtualTourV2/ManualSlideShow.vue.d.ts +4 -0
  38. package/dist/components/virtualTourV2/ManualSlideShow.vue.d.ts.map +1 -0
  39. package/dist/components/virtualTourV2/ManualSlideShowPlayer.vue.d.ts +4 -0
  40. package/dist/components/virtualTourV2/ManualSlideShowPlayer.vue.d.ts.map +1 -0
  41. package/dist/components/virtualTourV2/SingleImage.vue.d.ts +4 -0
  42. package/dist/components/virtualTourV2/SingleImage.vue.d.ts.map +1 -0
  43. package/dist/components/virtualTourV2/SocialShare.vue.d.ts +4 -0
  44. package/dist/components/virtualTourV2/SocialShare.vue.d.ts.map +1 -0
  45. package/dist/components/virtualTourV2/WaypointCarousel.vue.d.ts +4 -0
  46. package/dist/components/virtualTourV2/WaypointCarousel.vue.d.ts.map +1 -0
  47. package/dist/lib/virtualTour__/ApartmentConfig.d.ts +27 -0
  48. package/dist/lib/virtualTour__/ApartmentFiles.d.ts +7 -0
  49. package/dist/lib/virtualTour__/MinimapConfig.d.ts +23 -0
  50. package/dist/lib/virtualTour__/impl/HttpApartmentFiles.d.ts +19 -0
  51. package/dist/vue3-player.cjs.js +2 -0
  52. package/dist/vue3-player.esm.js +2992 -0
  53. package/dist/vue3-player.iife.js +3 -0
  54. package/dist/vue3-player.umd.js +3 -0
  55. package/package.json +65 -0
  56. package/src/components/apartmentChooser/QiApartmentChooser.vue +319 -0
  57. package/src/components/apartmentChooser/QiApartmentChooserNavigation.vue +88 -0
  58. package/src/components/apartmentChooser/QiApartmentChooserRaster.vue +408 -0
  59. package/src/components/apartmentChooser/QiApartmentChooserRotator.vue +202 -0
  60. package/src/components/apartmentChooser/QiApartmentChooserSvg.vue +257 -0
  61. package/src/components/apartmentChooser/index.js +5 -0
  62. package/src/components/buildingPicker/QiBuildingChooser.vue +61 -0
  63. package/src/components/buildingPicker/QiBuildingChooserRaster.vue +312 -0
  64. package/src/components/buildingPicker/QiBuildingChooserRasterOverlay.vue +96 -0
  65. package/src/components/buildingPicker/QiBuildingChooserSceneImageStack.vue +89 -0
  66. package/src/components/buildingPicker/QiBuildingChooserSunSimControl.vue +257 -0
  67. package/src/components/buildingPicker/QiBuildingChooserSvg.vue +414 -0
  68. package/src/components/buildingPicker/index.js +6 -0
  69. package/src/components/index.ts +4 -0
  70. package/src/components/shared/QiFloatingCard.vue +76 -0
  71. package/src/components/shared/QiHoverProbe.vue +22 -0
  72. package/src/components/shared/QiNorthDirection.vue +27 -0
  73. package/src/components/shared/QiZoomBox.vue +322 -0
  74. package/src/components/shared/index.js +4 -0
  75. package/src/components/virtualTourV2/Compass.vue +37 -0
  76. package/src/components/virtualTourV2/Disclaimer.vue +41 -0
  77. package/src/components/virtualTourV2/FloorLevel.vue +73 -0
  78. package/src/components/virtualTourV2/FullScreenButton.vue +23 -0
  79. package/src/components/virtualTourV2/InteriorSelector.vue +90 -0
  80. package/src/components/virtualTourV2/ManualSlideShow.vue +198 -0
  81. package/src/components/virtualTourV2/ManualSlideShowPlayer.vue +159 -0
  82. package/src/components/virtualTourV2/PlayerV2.vue +300 -0
  83. package/src/components/virtualTourV2/ScrollHelper.vue +74 -0
  84. package/src/components/virtualTourV2/SettingsUI.vue +355 -0
  85. package/src/components/virtualTourV2/SingleImage.vue +36 -0
  86. package/src/components/virtualTourV2/SocialShare.vue +163 -0
  87. package/src/components/virtualTourV2/TimeOfDay.vue +50 -0
  88. package/src/components/virtualTourV2/Tutorial.vue +690 -0
  89. package/src/components/virtualTourV2/ViewModeToggle.vue +24 -0
  90. package/src/components/virtualTourV2/VirtualTourV2.vue +876 -0
  91. package/src/components/virtualTourV2/WaypointCarousel.vue +162 -0
  92. package/src/components/virtualTourV2/index.js +1 -0
  93. package/src/components/virtualTourV2/minimapv2/MiniMapMap.vue +262 -0
  94. package/src/components/virtualTourV2/minimapv2/MiniMapV2.vue +110 -0
  95. package/src/components/virtualTourV2/minimapv2/MinimapCompass.vue +39 -0
  96. package/src/components/virtualTourV2/minimapv2/Moveable.vue +208 -0
  97. package/src/components/virtualTourV2/minimapv2/RotationMarkerV2.vue +79 -0
  98. package/src/components/virtualTourV2/minimapv2/SunsimulationSlider.vue +203 -0
  99. package/src/components/virtualTourV2/minimapv2/index.js +1 -0
  100. package/src/entry.esm.js +17 -0
  101. package/src/entry.js +13 -0
  102. package/src/entry.ts_ +17 -0
  103. package/src/lib/apartmentChooser/BuildingViewerModel.js +60 -0
  104. package/src/lib/apartmentChooser/CircularSlideshow.js +66 -0
  105. package/src/lib/apartmentChooser/RotationStep.js +31 -0
  106. package/src/lib/apartmentChooser/SceneRotator.js +25 -0
  107. package/src/lib/apartmentChooser/index.js +3 -0
  108. package/src/lib/apartmentChooser/throttle.js +15 -0
  109. package/src/lib/buildingPicker/BuildingMap.js +24 -0
  110. package/src/lib/buildingPicker/BuildingPickerResourceProvider.js +97 -0
  111. package/src/lib/buildingPicker/CanvasRaster.js +29 -0
  112. package/src/lib/buildingPicker/DayOfYearSelector.js +36 -0
  113. package/src/lib/buildingPicker/SampleRaster.js +14 -0
  114. package/src/lib/buildingPicker/index.js +5 -0
  115. package/src/lib/index.js +4 -0
  116. package/src/lib/shared/BatchLoadTracker.js +52 -0
  117. package/src/lib/shared/I18N.js +65 -0
  118. package/src/lib/shared/ResourceLoader.js +33 -0
  119. package/src/lib/shared/index.js +3 -0
  120. package/src/lib/virtualTour/CameraSnapshot.js +42 -0
  121. package/src/lib/virtualTour/FullscreenModel.js +69 -0
  122. package/src/lib/virtualTour/textures/arrow.png +0 -0
  123. package/src/lib/virtualTour/textures/compass-bg.png +0 -0
  124. package/src/lib/virtualTour/textures/compass-needle.png +0 -0
  125. package/src/lib/virtualTour/textures/compass-north.png +0 -0
  126. package/src/lib/virtualTour/textures/floor-1.svg +4 -0
  127. package/src/lib/virtualTour/textures/floor-2.svg +4 -0
  128. package/src/lib/virtualTour/textures/marker.png +0 -0
  129. package/src/lib/virtualTour/textures/tod-sun.png +0 -0
  130. package/src/lib/virtualTour__/ApartmentConfig.ts +80 -0
  131. package/src/lib/virtualTour__/ApartmentFiles.ts +8 -0
  132. package/src/lib/virtualTour__/CameraNavigator.js_ +74 -0
  133. package/src/lib/virtualTour__/CameraSnapshot.js +42 -0
  134. package/src/lib/virtualTour__/CoordConversions.js +43 -0
  135. package/src/lib/virtualTour__/FullscreenModel.js +69 -0
  136. package/src/lib/virtualTour__/MinimapConfig.ts +46 -0
  137. package/src/lib/virtualTour__/PlayerViewModel.js +423 -0
  138. package/src/lib/virtualTour__/config/ApartmentConfig.js +92 -0
  139. package/src/lib/virtualTour__/config/CameraConfig.js +97 -0
  140. package/src/lib/virtualTour__/config/Interaction.js +393 -0
  141. package/src/lib/virtualTour__/config/Panorama.js +78 -0
  142. package/src/lib/virtualTour__/config/PlayerConfig.js +812 -0
  143. package/src/lib/virtualTour__/config/rawinflate.export.js +833 -0
  144. package/src/lib/virtualTour__/config/shaders.js +24 -0
  145. package/src/lib/virtualTour__/impl/HttpApartmentFiles.ts +57 -0
  146. package/src/lib/virtualTour__/index.js +1 -0
  147. package/src/lib/virtualTour__/textures/arrow.png +0 -0
  148. package/src/lib/virtualTour__/textures/compass-bg.png +0 -0
  149. package/src/lib/virtualTour__/textures/compass-needle.png +0 -0
  150. package/src/lib/virtualTour__/textures/compass-north.png +0 -0
  151. package/src/lib/virtualTour__/textures/floor-1.svg +4 -0
  152. package/src/lib/virtualTour__/textures/floor-2.svg +4 -0
  153. package/src/lib/virtualTour__/textures/marker.png +0 -0
  154. package/src/lib/virtualTour__/textures/tod-sun.png +0 -0
  155. package/src/main.ts_ +24 -0
  156. package/src/shims-png.d.ts +4 -0
  157. package/src/shims-tsx.d.ts +11 -0
  158. package/src/shims-vue.d.ts +4 -0
  159. package/src/style.css +0 -0
  160. package/src/vite-env.d.ts +5 -0
@@ -0,0 +1,876 @@
1
+ <template>
2
+ <div class="virtual-tour-v2-wrapper">
3
+ <div v-if="error" class="player-error">Error loading the player!!</div>
4
+ <div class="player-and-components-wrapper">
5
+ <mini-map-v-2
6
+ v-if="
7
+ !fullScreen.isActive &&
8
+ minimapJSON &&
9
+ playerCamera &&
10
+ minimapCamera &&
11
+ displayMinimap
12
+ "
13
+ :allCameras="allCameras"
14
+ :rootUrl="rootUrl"
15
+ :level="storey"
16
+ :backgroundImage="refinedMinimapBackgroundImage"
17
+ :minimapJSON="minimapJSON.storeys"
18
+ :rotation="rotation"
19
+ :currentCamera="playerCamera"
20
+ :minimapCamera="minimapCamera"
21
+ @close="displayMinimap = false"
22
+ @set-background-image="setMinimapBackgroundImage"
23
+ />
24
+ <div v-if="interiorId && currentCameraId">
25
+ <player-v-2
26
+ ref="player"
27
+ :file-loader="fileLoader"
28
+ :style="{ zIndex: showStaticImage ? 1 : 2 }"
29
+ :showStaticImage="showStaticImage"
30
+ :isFullScreen="fullScreen.isActive"
31
+ :rootUrl="rootUrl"
32
+ :currentCameraId="currentCameraId"
33
+ :mouse-sensitivity="mouseSensitivity"
34
+ :is-in-iframe="isInIframe"
35
+ @new-camera-callback="newCameraCallback"
36
+ @new-rotation-callback="newRotationCallback"
37
+ @new-floor-callback="newfloorCallback"
38
+ @new-fov-callback="newFoVCallback"
39
+ @new-size-callback="newSizeCallback"
40
+ @playerApi-callback="playerApiCallback"
41
+ >
42
+ <template v-slot:slideshow-image>
43
+ <single-image v-if="showStaticImage" :image="staticImage" />
44
+ </template>
45
+ <template v-slot:top-left>
46
+ <v-btn
47
+ v-show="showUI"
48
+ v-if="adminMode"
49
+ density="comfortable"
50
+ icon="mdi-cog-outline"
51
+ elevation="3"
52
+ class="mr-2"
53
+ @click="showSettings = !showSettings"
54
+ >
55
+ </v-btn>
56
+ <v-btn
57
+ v-if="minimapJSON && currentCameraId && minimapCamera"
58
+ v-show="showUI"
59
+ density="comfortable"
60
+ elevation="3"
61
+ icon="mdi-floor-plan"
62
+ class="mr-2"
63
+ @click="displayMinimap = !displayMinimap"
64
+ >
65
+ </v-btn>
66
+
67
+ <floor-level
68
+ v-if="showUI && showFloorLevel && floorLevels.length > 1"
69
+ :level="floorLevel"
70
+ :floor-levels="floorLevels"
71
+ />
72
+
73
+ <div
74
+ v-if="showUI && adminMode && showSettings"
75
+ class="settings-panel"
76
+ >
77
+ <settings-u-i
78
+ :project-slug="projectSlug"
79
+ :initialSettings="playerSettings"
80
+ @update-settings="updateSetting"
81
+ @save-settings="saveSettings"
82
+ />
83
+ </div>
84
+ </template>
85
+ <template v-slot:top-center>
86
+ <disclaimer v-if="showUI" :return-url="websiteUrl" />
87
+ </template>
88
+ <template v-slot:top-right>
89
+ <div
90
+ v-if="apartmentJSON && showCompass"
91
+ v-show="showUI"
92
+ class="compass-wrapper"
93
+ >
94
+ <compass :rotation="rotation" />
95
+ </div>
96
+
97
+ <time-of-day
98
+ v-if="showUI && apartmentJSON && hasTimeofDay && showTimeOfDay"
99
+ :hours="timeOfDay.hours"
100
+ :minutes="timeOfDay.minutes"
101
+ />
102
+ </template>
103
+ <template v-slot:center-left>
104
+ <transition name="slide-x-transition">
105
+ <v-btn
106
+ v-if="showStaticImage"
107
+ density="comfortable"
108
+ elevation="3"
109
+ icon="mdi-chevron-left"
110
+ @click="previousCamera"
111
+ >
112
+ </v-btn>
113
+ </transition>
114
+ </template>
115
+ <template v-slot:center-center>
116
+ <tutorial :project="projectRoot" @closeTutorial="showUI = true" />
117
+ <mini-map-v-2
118
+ v-if="
119
+ fullScreen.isActive &&
120
+ minimapJSON &&
121
+ playerCamera &&
122
+ minimapCamera &&
123
+ displayMinimap
124
+ "
125
+ :allCameras="allCameras"
126
+ :rootUrl="rootUrl"
127
+ :minimapJSON="minimapJSON.storeys"
128
+ :backgroundImage="refinedMinimapBackgroundImage"
129
+ :rotation="rotation"
130
+ :currentCamera="playerCamera"
131
+ :minimapCamera="minimapCamera"
132
+ :level="storey"
133
+ @close="displayMinimap = false"
134
+ @set-background-image="setMinimapBackgroundImage"
135
+ />
136
+ </template>
137
+ <template v-slot:center-right>
138
+ <transition name="slide-x-reverse-transition">
139
+ <v-btn
140
+ v-if="showStaticImage"
141
+ density="comfortable"
142
+ elevation="3"
143
+ icon="mdi-chevron-right"
144
+ @click="nextCamera"
145
+ >
146
+ </v-btn>
147
+ </transition>
148
+ </template>
149
+ <template v-slot:bottom-left>
150
+ <full-screen-button
151
+ v-if="showUI && showFullScreen"
152
+ :isFullScreen="fullScreen.isActive"
153
+ class="btn-fullscreen"
154
+ @toggle-fullscreen="toggleFullscreen"
155
+ />
156
+ <div v-if="showUI && showSnapshot" class="btn-placeholder mr-2">
157
+ <v-btn
158
+ density="comfortable"
159
+ elevation="3"
160
+ icon="mdi-camera"
161
+ @click="takeSnapshot"
162
+ >
163
+ </v-btn>
164
+ </div>
165
+ <div
166
+ v-if="showUI && showShare && !fullScreen.isActive"
167
+ class="btn-placeholder"
168
+ >
169
+ <social-share />
170
+ </div>
171
+ </template>
172
+ <template v-slot:bottom-center>
173
+ <div v-if="showUI && showCarousel">
174
+ <view-mode-toggle
175
+ v-if="displayViewModeSwitch"
176
+ :show-static-image="showStaticImage"
177
+ @toggle="toggleViewMode"
178
+ />
179
+ <waypoint-carousel
180
+ v-if="showUI && fullScreen.isActive"
181
+ :class="[fullScreen.isActive ? 'full-screen' : '']"
182
+ :thumbnails="thumbnails"
183
+ :active="currentThumbnailIndex"
184
+ @next="nextCamera"
185
+ @previous="previousCamera"
186
+ @goto="goToCamera"
187
+ />
188
+ </div>
189
+ </template>
190
+ <template v-slot:bottom-right>
191
+ <interior-selector
192
+ v-if="showUI && showInteriorOptions && interiorsWithImage"
193
+ :availableArchetypes="interiorsWithImage"
194
+ :selectedIndex="selectedInteriorIndex"
195
+ @select-interior="updateSelectedInterior"
196
+ />
197
+ </template>
198
+ </player-v-2>
199
+
200
+ <waypoint-carousel
201
+ v-if="showCarousel && thumbsJSON"
202
+ :thumbnails="thumbnails"
203
+ :active="currentThumbnailIndex"
204
+ @next="nextCamera"
205
+ @previous="previousCamera"
206
+ @goto="goToCamera"
207
+ />
208
+ </div>
209
+ </div>
210
+ </div>
211
+ </template>
212
+ <script>
213
+ import { defineComponent, ref } from "vue";
214
+ import axios from "axios";
215
+ import PlayerV2 from "./PlayerV2.vue";
216
+ import WaypointCarousel from "./WaypointCarousel.vue";
217
+ import FloorLevel from "./FloorLevel.vue";
218
+ import SocialShare from "./SocialShare.vue";
219
+ import InteriorSelector from "./InteriorSelector.vue";
220
+ import { I18N } from "@/lib/shared/I18N";
221
+ import Compass from "./Compass.vue";
222
+ import SingleImage from "./SingleImage.vue";
223
+ import TimeOfDay from "./TimeOfDay.vue";
224
+ import { FullscreenModel } from "@/lib/virtualTour/FullscreenModel";
225
+ import { CameraSnapshot } from "@/lib/virtualTour/CameraSnapshot";
226
+ import FullScreenButton from "./FullScreenButton.vue";
227
+ import ViewModeToggle from "./ViewModeToggle.vue";
228
+ import Disclaimer from "./Disclaimer.vue";
229
+ import Tutorial from "./Tutorial.vue";
230
+ import SettingsUI from "./SettingsUI.vue";
231
+ import MiniMapV2 from "./minimapv2/MiniMapV2.vue";
232
+
233
+ const DEFAULT_PLAYER_SETTINGS = {
234
+ temperature: 6500,
235
+ targetLuminance: 1,
236
+ exposureFovScale: 0.3,
237
+ UNREAL_BLOOM_ENABLED: true,
238
+ sharpenFilter_amount: 0.6,
239
+ UNREAL_BLOOOM_STRENGTH: 0.3,
240
+ TRANSITION_MOVEMENT_SCALE: 1.3,
241
+ whitePoint: [1, 1, 1],
242
+ };
243
+
244
+ export default defineComponent({
245
+ name: "VirtualTourV2",
246
+ emits: [
247
+ "on-snapshot",
248
+ "save-settings",
249
+ "on-interior-update",
250
+ "on-camera-update",
251
+ ],
252
+ components: {
253
+ PlayerV2,
254
+ WaypointCarousel,
255
+ InteriorSelector,
256
+ Compass,
257
+ SingleImage,
258
+ TimeOfDay,
259
+ FloorLevel,
260
+ SocialShare,
261
+ FullScreenButton,
262
+ ViewModeToggle,
263
+ MiniMapV2,
264
+ Disclaimer,
265
+ Tutorial,
266
+ SettingsUI,
267
+ },
268
+ props: {
269
+ fileLoader: {
270
+ type: Object,
271
+ default: undefined,
272
+ },
273
+ cdnRoot: {
274
+ type: String,
275
+ required: true,
276
+ },
277
+ projectSlug: {
278
+ type: String,
279
+ required: true,
280
+ },
281
+ apartmentId: {
282
+ type: String,
283
+ required: true,
284
+ },
285
+ defaultInteriorId: {
286
+ type: String,
287
+ default: () => undefined,
288
+ },
289
+ validInteriorIds: { type: Array, default: () => [] },
290
+ viewModes: { type: Array, default: () => ["virtualTour", "slideShow"] },
291
+ displayViewModeSwitch: { type: Boolean, default: () => true },
292
+ websiteUrl: { type: String, default: () => undefined },
293
+ i18n: { type: Object, default: undefined },
294
+ showCarousel: { type: Boolean, default: () => true },
295
+ showTimeOfDay: { type: Boolean, default: () => true },
296
+ showCompass: { type: Boolean, default: () => true },
297
+ showFullScreen: { type: Boolean, default: () => true },
298
+ showSnapshot: { type: Boolean, default: () => true },
299
+ showShare: { type: Boolean, default: () => true },
300
+ showInteriorOptions: { type: Boolean, default: () => true },
301
+ showMiniMap: { type: Boolean, default: () => true },
302
+ showFloorLevel: { type: Boolean, default: () => true },
303
+ defaultWaypointIndex: { type: Number, default: () => 0 },
304
+ defaultViewMode: { type: String, default: () => "virtualTour" },
305
+ mouseSensitivity: { type: Number, default: () => 1 },
306
+ isInIframe: { type: Boolean, default: () => false },
307
+ adminMode: { type: Boolean, default: () => false },
308
+ playerSettings: {
309
+ type: Object,
310
+ default: () => {
311
+ return DEFAULT_PLAYER_SETTINGS;
312
+ },
313
+ },
314
+ },
315
+ data() {
316
+ return {
317
+ showSettings: false,
318
+ loading: true,
319
+ error: false,
320
+ configJSON: undefined,
321
+ apartmentJSON: undefined,
322
+ thumbsJSON: undefined,
323
+ minimapJSON: undefined,
324
+ playerApi: undefined,
325
+ currentThumbnailIndex: 0,
326
+ selectedInteriorId: undefined,
327
+ currentCameraId: undefined,
328
+ playerCamera: undefined,
329
+ rotation: 0,
330
+ floorLevel: 0,
331
+ fov: 0,
332
+ showStaticImage: false,
333
+ displayMinimap: false,
334
+ minimapBackgroundImage: undefined,
335
+ showUI: false,
336
+ fullScreen: new FullscreenModel(document, "player-wrapper"),
337
+ };
338
+ },
339
+ provide() {
340
+ const localizer = this.i18n
341
+ ? new I18N(this.i18n.labels, this.i18n.language)
342
+ : new I18N();
343
+
344
+ return {
345
+ localMode: this.localMode,
346
+ fileLoader: this.fileLoader,
347
+ i18n: localizer,
348
+ };
349
+ },
350
+ computed: {
351
+ localMode() {
352
+ return !!this.fileLoader;
353
+ },
354
+ projectRoot() {
355
+ let pRoot = `${this.cdnRoot}/${this.projectSlug}`;
356
+ if (this.fileLoader) {
357
+ pRoot = "";
358
+ }
359
+ return removeTrailingSlashes(pRoot);
360
+ },
361
+ rootUrl() {
362
+ return `${this.projectRoot}/${this.interiorId}/${this.apartmentId}`;
363
+ },
364
+ interiorId() {
365
+ return this.selectedInteriorId;
366
+ },
367
+ allCameras() {
368
+ if (this.apartmentJSON) return this.apartmentJSON.cameras;
369
+ return [];
370
+ },
371
+ currentCamera() {
372
+ if (this.apartmentJSON && this.currentCameraId) {
373
+ return this.apartmentJSON.cameras.find(
374
+ (item) => item.id === this.cameraId
375
+ );
376
+ }
377
+ },
378
+ floorLevels() {
379
+ if (this.apartmentJSON) {
380
+ const allFloorLevels = this.apartmentJSON.cameras.map(
381
+ (item) => item.floorLevel
382
+ );
383
+
384
+ let uniqueFloorLevels = [...new Set(allFloorLevels)];
385
+ uniqueFloorLevels = uniqueFloorLevels.sort();
386
+ return uniqueFloorLevels;
387
+ } else {
388
+ return [];
389
+ }
390
+ },
391
+ storey() {
392
+ let storey = 0;
393
+ if (this.apartmentJSON) {
394
+ const allFloorLevels = this.apartmentJSON.cameras.map(
395
+ (item) => item.floorLevel
396
+ );
397
+
398
+ let uniqueFloorLevels = [...new Set(allFloorLevels)];
399
+ uniqueFloorLevels = uniqueFloorLevels.sort();
400
+
401
+ const index = uniqueFloorLevels.findIndex(
402
+ (item) => item === this.floorLevel
403
+ );
404
+ if (index !== -1) {
405
+ storey = index;
406
+ }
407
+ }
408
+
409
+ return storey;
410
+ },
411
+ selectedInteriorIndex() {
412
+ return this.interiors.findIndex(
413
+ (item) => item.archetypeID === this.selectedInteriorId
414
+ );
415
+ },
416
+ thumbnails() {
417
+ if (!this.thumbsJSON) {
418
+ return [];
419
+ }
420
+
421
+ return this.thumbsJSON.cameras.map((item) => {
422
+ return {
423
+ ...item,
424
+ thumbnailUrl: this.getURL(
425
+ `${this.projectRoot}/${this.interiorId}/${this.apartmentId}/thumbs/200/${item.id}.jpg`
426
+ ),
427
+ imageUrl: this.getURL(
428
+ `${this.projectRoot}/${this.interiorId}/${this.apartmentId}/images/1600/${item.id}.jpg`
429
+ ),
430
+ };
431
+ });
432
+ },
433
+ staticImage() {
434
+ if (!this.thumbnails) return "";
435
+ if (!this.thumbnails[this.currentThumbnailIndex]) return "";
436
+
437
+ return this.thumbnails[this.currentThumbnailIndex].imageUrl;
438
+ },
439
+ interiors() {
440
+ let interiors = [];
441
+
442
+ if (this.configJSON) {
443
+ interiors = this.configJSON.archetypes;
444
+ }
445
+
446
+ if (this.validInteriorIds.length) {
447
+ return interiors.filter((item) =>
448
+ this.validInteriorIds.includes(item.archetypeID)
449
+ );
450
+ }
451
+
452
+ return interiors;
453
+ },
454
+ interiorIds() {
455
+ return this.interiors.map((item) => item.archetypeID);
456
+ },
457
+ interiorsWithImage() {
458
+ if (!this.thumbsJSON) {
459
+ return [];
460
+ }
461
+ return this.interiors.map((item) => {
462
+ return {
463
+ ...item,
464
+ url: `${this.projectRoot}/${item.archetypeID}/${
465
+ this.apartmentId
466
+ }/thumbs/200/${this.thumbnails[this.currentThumbnailIndex].id}.jpg`,
467
+ };
468
+ });
469
+ },
470
+ minimapCamera() {
471
+ if (this.minimapJSON) {
472
+ return this.minimapJSON.storeys[this.storey];
473
+ }
474
+ return undefined;
475
+ },
476
+ hasTimeofDay() {
477
+ return this.apartmentJSON && this.apartmentJSON.timeInHours;
478
+ },
479
+ timeOfDay() {
480
+ if (
481
+ this.apartmentJSON &&
482
+ this.apartmentJSON.timeInHours &&
483
+ this.showTimeOfDay
484
+ )
485
+ return parseTimeOfDay(this.apartmentJSON.timeInHours);
486
+ },
487
+ refinedMinimapBackgroundImage() {
488
+ return this.minimapBackgroundImage
489
+ ? this.minimapBackgroundImage
490
+ : `${this.projectRoot}/${this.interiorId}/${this.apartmentId}/minimap/sunsim0_13.jpg`;
491
+ },
492
+ },
493
+ watch: {
494
+ async cdnRoot() {
495
+ await this.loadProjectFiles();
496
+ this.selectInititalInterior();
497
+ await this.loadUnitFiles();
498
+ },
499
+ async projectSlug() {
500
+ await this.loadProjectFiles();
501
+ this.selectInititalInterior();
502
+ await this.loadUnitFiles();
503
+ },
504
+ defaultViewMode: {
505
+ handler(viewMode) {
506
+ if (viewMode === "virtualTour") {
507
+ this.showStaticImage = false;
508
+ }
509
+
510
+ if (viewMode === "slideShow") {
511
+ this.showStaticImage = true;
512
+ this.showUI = true;
513
+ }
514
+ },
515
+ immediate: true,
516
+ },
517
+ minimapJSON(newMinimapJSON) {
518
+ if (newMinimapJSON.storeys[this.storey]) {
519
+ const defaultBackgroundImage =
520
+ newMinimapJSON.storeys[this.storey].defaultSunsimFile;
521
+
522
+ this.minimapBackgroundImage = `${this.projectRoot}/${this.interiorId}/${this.apartmentId}/minimap/${defaultBackgroundImage}`;
523
+ }
524
+ },
525
+ },
526
+ async mounted() {
527
+ try {
528
+ await this.loadProjectFiles();
529
+ this.selectInititalInterior();
530
+ await this.loadUnitFiles();
531
+ this.fullScreen.setup();
532
+ this.setupScrollevents();
533
+ } catch (e) {
534
+ this.error = true;
535
+ }
536
+ },
537
+ methods: {
538
+ async loadProjectFiles() {
539
+ this.configJSON = await this.loadConfigJSON(this.projectRoot);
540
+ },
541
+ async loadUnitFiles() {
542
+ this.apartmentJSON = await this.loadApartmentJSON(
543
+ this.projectRoot,
544
+ this.interiorId,
545
+ this.apartmentId
546
+ );
547
+ if (this.apartmentJSON) {
548
+ this.currentCameraId = this.apartmentJSON.cameras.find(() => true).id;
549
+ }
550
+
551
+ this.thumbsJSON = await this.loadThumbsJSON(
552
+ this.projectRoot,
553
+ this.interiorId,
554
+ this.apartmentId
555
+ );
556
+
557
+ if (this.thumbsJSON) {
558
+ let defaultWaypointIndex =
559
+ this.defaultWaypointIndex !== null ? this.defaultWaypointIndex : 0;
560
+
561
+ this.currentThumbnailIndex = defaultWaypointIndex;
562
+ this.currentCameraId = this.thumbsJSON.cameras[defaultWaypointIndex].id;
563
+ this.playerCamera = this.thumbsJSON.cameras[defaultWaypointIndex].id;
564
+ }
565
+
566
+ if (this.showMiniMap) {
567
+ this.minimapJSON = await this.loadminimapJSON(
568
+ this.projectRoot,
569
+ this.interiorId,
570
+ this.apartmentId
571
+ );
572
+ }
573
+ },
574
+ selectInititalInterior() {
575
+ let initialInteriorId = this.defaultInteriorId;
576
+
577
+ if (!initialInteriorId) {
578
+ initialInteriorId = this.configJSON.defaultArchetypeID;
579
+ }
580
+
581
+ if (
582
+ this.validInteriorIds.length &&
583
+ !this.validInteriorIds.includes(initialInteriorId)
584
+ ) {
585
+ initialInteriorId = this.validInteriorIds[0];
586
+ }
587
+
588
+ if (!initialInteriorId) {
589
+ initialInteriorId = this.configJSON.archetypes[0].archetypeID;
590
+ }
591
+
592
+ this.selectedInteriorId = initialInteriorId;
593
+ },
594
+ setupScrollevents() {
595
+ const canvas = document.getElementById("main-canvas");
596
+
597
+ canvas.addEventListener("touchmove", handleTouchMove, { passive: false });
598
+ function handleTouchMove(event) {
599
+ event.preventDefault();
600
+ window.scrollBy(0, 0);
601
+ }
602
+
603
+ canvas.addEventListener(
604
+ "mouseenter",
605
+ () => {
606
+ document.addEventListener("wheel", handleMouseWheel, {
607
+ passive: false,
608
+ });
609
+ },
610
+ { passive: false }
611
+ );
612
+
613
+ canvas.addEventListener(
614
+ "mouseleave",
615
+ () => {
616
+ document.removeEventListener("wheel", handleMouseWheel, {
617
+ passive: false,
618
+ });
619
+ },
620
+ { passive: false }
621
+ );
622
+
623
+ function handleMouseWheel(event) {
624
+ event.preventDefault();
625
+ window.scrollBy(0, 0);
626
+ }
627
+ },
628
+ async loadConfigJSON(projectRoot) {
629
+ try {
630
+ const config = await this.loadFile(`${projectRoot}/config.json`);
631
+ return config;
632
+ } catch (e) {
633
+ console.error(
634
+ "Error loading config.json - ",
635
+ `${projectRoot}/config.json`,
636
+ e
637
+ );
638
+ return undefined;
639
+ }
640
+ },
641
+ async loadApartmentJSON(projectRoot, interiorId, apartmentId) {
642
+ try {
643
+ const apartmentJSON = await this.loadFile(
644
+ `${projectRoot}/${interiorId}/${apartmentId}/apartment.json`
645
+ );
646
+ return apartmentJSON;
647
+ } catch (e) {
648
+ console.error(
649
+ "Error loading apartment.json - ",
650
+ `${projectRoot}/${interiorId}/${apartmentId}/apartment.json`,
651
+ e
652
+ );
653
+ return undefined;
654
+ }
655
+ },
656
+ async loadThumbsJSON(projectRoot, interiorId, apartmentId) {
657
+ try {
658
+ const thumbsJSON = await this.loadFile(
659
+ `${projectRoot}/${interiorId}/${apartmentId}/thumbs.json`
660
+ );
661
+ return thumbsJSON;
662
+ } catch (e) {
663
+ console.error(
664
+ "Error loading thumbs.json - ",
665
+ `${projectRoot}/${interiorId}/${apartmentId}/thumbs.json`
666
+ );
667
+ return undefined;
668
+ }
669
+ },
670
+ async loadminimapJSON(projectRoot, interiorId, apartmentId) {
671
+ try {
672
+ const minimapJSON = await this.loadFile(
673
+ `${projectRoot}/${interiorId}/${apartmentId}/minimap/minimap.json`
674
+ );
675
+ return minimapJSON;
676
+ } catch (e) {
677
+ console.error(
678
+ "Error loading minimap.json - ",
679
+ `${projectRoot}/${interiorId}/${apartmentId}/minimap/minimap.json`
680
+ );
681
+ return undefined;
682
+ }
683
+ },
684
+ selectInterior() {
685
+ if (this.defaultInteriorId) {
686
+ this.selectedInteriorId = this.defaultInteriorId;
687
+ } else {
688
+ this.selectedInteriorId = this.configJSON.defaultArchetypeID;
689
+ }
690
+ },
691
+ nextCamera() {
692
+ let newIndex = this.currentThumbnailIndex + 1;
693
+ if (newIndex >= this.thumbnails.length) newIndex = 0;
694
+ this.currentThumbnailIndex = newIndex;
695
+ this.setCurrentCamera(this.thumbnails[this.currentThumbnailIndex].id);
696
+ },
697
+ previousCamera() {
698
+ let newIndex = this.currentThumbnailIndex - 1;
699
+ if (newIndex < 0) newIndex = this.thumbnails.length - 1;
700
+ this.currentThumbnailIndex = newIndex;
701
+ this.setCurrentCamera(this.thumbnails[this.currentThumbnailIndex].id);
702
+ },
703
+ goToCamera(cameraId, updatePlayerCamera = true) {
704
+ let newIndex = this.thumbnails.findIndex((item) => item.id === cameraId);
705
+
706
+ if (newIndex != -1) {
707
+ this.currentThumbnailIndex = newIndex;
708
+ if (updatePlayerCamera) {
709
+ this.setCurrentCamera(cameraId);
710
+ }
711
+ }
712
+ },
713
+ setCurrentCamera(cameraId) {
714
+ this.currentCameraId = cameraId;
715
+ },
716
+ updateSelectedInterior(value) {
717
+ this.selectedInteriorId = value;
718
+ this.$emit("on-interior-update", value);
719
+ this.$emit("on-camera-update", this.playerCamera, this.apartmentJSON);
720
+ },
721
+ newCameraCallback(cameraId) {
722
+ this.goToCamera(cameraId, false);
723
+ this.playerCamera = cameraId;
724
+ this.$emit("on-camera-update", cameraId, this.apartmentJSON);
725
+ },
726
+ newRotationCallback(rotation) {
727
+ this.rotation = rotation;
728
+ },
729
+ newfloorCallback(floor) {
730
+ this.floorLevel = floor;
731
+ },
732
+ newFoVCallback(fov) {
733
+ this.fov = fov;
734
+ },
735
+ newSizeCallback(width, height) {
736
+ // console.log('new size - ', width, height)
737
+ },
738
+ playerApiCallback(api) {
739
+ this.playerApi = api;
740
+
741
+ if (this.playerSettings) {
742
+ this.playerApi.updateSettings(this.playerSettings);
743
+ }
744
+ },
745
+ toggleFullscreen() {
746
+ this.fullScreen.toggle();
747
+ window.scrollTo({ top: 150, behavior: "smooth" });
748
+ },
749
+ toggleViewMode() {
750
+ this.showStaticImage = !this.showStaticImage;
751
+ },
752
+ setMinimapBackgroundImage(image) {
753
+ this.minimapBackgroundImage = image;
754
+ },
755
+ async takeSnapshot() {
756
+ const radiansToDegrees = 180 / Math.PI;
757
+
758
+ const photo = await this.playerApi.takePhoto();
759
+ const rotationEuler = this.playerApi.getRotationEuler();
760
+ const currentCamera = this.playerApi.getCurrentCamera();
761
+ const snapshot = new CameraSnapshot(photo, currentCamera);
762
+ const rotation = [
763
+ rotationEuler.x * radiansToDegrees,
764
+ rotationEuler.y * radiansToDegrees,
765
+ rotationEuler.z * radiansToDegrees,
766
+ ];
767
+
768
+ this.$emit("on-snapshot", snapshot, rotation);
769
+ return snapshot;
770
+ },
771
+ getURL(url) {
772
+ let returnUrl = url;
773
+ if (this.localMode) {
774
+ returnUrl = `${this.fileLoader.getURL(url)}`;
775
+ } else {
776
+ if (this.adminMode) {
777
+ returnUrl = returnUrl + `?v=${Date.now()}`;
778
+ }
779
+ }
780
+
781
+ return returnUrl;
782
+ },
783
+ async loadFile(path) {
784
+ const url = this.getURL(path);
785
+ return await loadFile(url);
786
+ },
787
+ updateSetting(settings) {
788
+ this.playerApi.updateSettings(settings);
789
+ },
790
+ saveSettings(settings) {
791
+ this.$emit("save-settings", settings);
792
+ },
793
+ },
794
+ });
795
+
796
+ function parseTimeOfDay(floatValue) {
797
+ if (floatValue === undefined) return null;
798
+
799
+ const hours = Math.floor(floatValue);
800
+ const minutes = Math.floor((hours - floatValue) * 60);
801
+ return { hours, minutes };
802
+ }
803
+
804
+ async function loadFile(url) {
805
+ try {
806
+ const file = await axios.get(url);
807
+ return file.data;
808
+ } catch (e) {
809
+ console.error(e);
810
+ throw new Error(e);
811
+ }
812
+ }
813
+
814
+ function removeTrailingSlashes(site) {
815
+ return site.replace(/\/$/, "");
816
+ }
817
+ </script>
818
+ <style scoped>
819
+ .compass-wrapper {
820
+ width: 50px;
821
+ }
822
+
823
+ .player-and-components-wrapper {
824
+ position: relative;
825
+ }
826
+
827
+ .static-image {
828
+ position: absolute;
829
+ top: 0;
830
+ left: 0;
831
+ width: 100%;
832
+ height: auto;
833
+ }
834
+
835
+ button.v-btn {
836
+ background: #fff;
837
+ }
838
+
839
+ .waypoint-carousel.full-screen {
840
+ scale: 0.5;
841
+ }
842
+
843
+ div#controls-bottom-center > div {
844
+ display: flex;
845
+ flex-direction: column;
846
+ align-items: center;
847
+ }
848
+
849
+ .player-error {
850
+ min-height: 400px;
851
+ display: flex;
852
+ align-items: center;
853
+ justify-content: space-around;
854
+ background: #ededed;
855
+ }
856
+
857
+ @media only screen and (max-width: 600px) {
858
+ #btn-fullscreen {
859
+ display: none;
860
+ }
861
+ }
862
+ @media all and (orientation: landscape) and (max-height: 499px) {
863
+ #btn-fullscreen {
864
+ display: none;
865
+ }
866
+ }
867
+ .settings-panel {
868
+ position: absolute;
869
+ top: 0px;
870
+ left: 0px;
871
+ z-index: 10;
872
+ width: 500px;
873
+ transform: scale(0.8);
874
+ transform-origin: left;
875
+ }
876
+ </style>