locar 0.1.6 → 0.1.7
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/dist/locar.d.ts +290 -0
- package/dist/locar.es.js +245 -346
- package/dist/locar.umd.js +1 -1
- package/package.json +11 -8
- package/lib/types/locar.d.ts +0 -336
package/dist/locar.es.js
CHANGED
|
@@ -1,97 +1,49 @@
|
|
|
1
|
-
import * as
|
|
2
|
-
import { Vector3 as
|
|
3
|
-
class
|
|
1
|
+
import * as g from "three";
|
|
2
|
+
import { Vector3 as T, Euler as C, Quaternion as E, EventDispatcher as _, MathUtils as u } from "three";
|
|
3
|
+
class w {
|
|
4
4
|
/**
|
|
5
5
|
* Create a SphMercProjection.
|
|
6
6
|
*/
|
|
7
7
|
constructor() {
|
|
8
|
-
this.
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
*/
|
|
16
|
-
project(e, i) {
|
|
17
|
-
return [this.#t(e), this.#l(i)];
|
|
18
|
-
}
|
|
19
|
-
/**
|
|
20
|
-
* Unproject a Spherical Mercator easting and northing.
|
|
21
|
-
* @param {Array} projected - Two-member array containing easting and northing
|
|
22
|
-
* @return {Array} Two-member array containing longitude and latitude
|
|
23
|
-
*/
|
|
24
|
-
unproject(e) {
|
|
25
|
-
return [this.#e(e[0]), this.#s(e[1])];
|
|
26
|
-
}
|
|
27
|
-
#t(e) {
|
|
28
|
-
return e / 180 * this.HALF_EARTH;
|
|
29
|
-
}
|
|
30
|
-
#l(e) {
|
|
31
|
-
var i = Math.log(Math.tan((90 + e) * Math.PI / 360)) / (Math.PI / 180);
|
|
32
|
-
return i * this.HALF_EARTH / 180;
|
|
33
|
-
}
|
|
34
|
-
#e(e) {
|
|
35
|
-
return e / this.HALF_EARTH * 180;
|
|
36
|
-
}
|
|
37
|
-
#s(e) {
|
|
38
|
-
var i = e / this.HALF_EARTH * 180;
|
|
39
|
-
return i = 180 / Math.PI * (2 * Math.atan(Math.exp(i * Math.PI / 180)) - Math.PI / 2), i;
|
|
40
|
-
}
|
|
41
|
-
/**
|
|
42
|
-
* Return the projection's ID.
|
|
43
|
-
* @return {string} The value "epsg:3857".
|
|
44
|
-
*/
|
|
45
|
-
getID() {
|
|
46
|
-
return "epsg:3857";
|
|
8
|
+
this.project = (e, s) => [this.#t(e), this.#e(s)], this.unproject = (e) => [this.#i(e[0]), this.#s(e[1])], this.#t = (e) => e / 180 * this.HALF_EARTH, this.#e = (e) => {
|
|
9
|
+
var s = Math.log(Math.tan((90 + e) * Math.PI / 360)) / (Math.PI / 180);
|
|
10
|
+
return s * this.HALF_EARTH / 180;
|
|
11
|
+
}, this.#i = (e) => e / this.HALF_EARTH * 180, this.#s = (e) => {
|
|
12
|
+
var s = e / this.HALF_EARTH * 180;
|
|
13
|
+
return s = 180 / Math.PI * (2 * Math.atan(Math.exp(s * Math.PI / 180)) - Math.PI / 2), s;
|
|
14
|
+
}, this.getID = () => "epsg:3857", this.EARTH = 4007501668e-2, this.HALF_EARTH = 2003750834e-2;
|
|
47
15
|
}
|
|
16
|
+
#t;
|
|
17
|
+
#e;
|
|
18
|
+
#i;
|
|
19
|
+
#s;
|
|
48
20
|
}
|
|
49
|
-
class
|
|
21
|
+
class y {
|
|
50
22
|
constructor() {
|
|
51
|
-
this.
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
* @param {string} eventName - the event to emit.
|
|
64
|
-
* @param ...params - parameters to pass to the event handlers.
|
|
65
|
-
*/
|
|
66
|
-
emit(e, ...i) {
|
|
67
|
-
this.eventHandlers[e]?.forEach((t) => {
|
|
68
|
-
t(...i);
|
|
69
|
-
});
|
|
70
|
-
}
|
|
71
|
-
/**
|
|
72
|
-
* Remove an event handler.
|
|
73
|
-
* @param {string} eventName - the event to remove a handler from.
|
|
74
|
-
* @param {Function} eventHandler - the event handler function to remove.
|
|
75
|
-
*/
|
|
76
|
-
off(e, i) {
|
|
77
|
-
if (this.eventHandlers[e]) {
|
|
78
|
-
const t = this.eventHandlers[e].indexOf(i);
|
|
79
|
-
t > -1 && this.eventHandlers[e].splice(t, 1);
|
|
80
|
-
}
|
|
23
|
+
this.on = (e, s) => {
|
|
24
|
+
this.eventHandlers[e] === void 0 && (this.eventHandlers[e] = []), this.eventHandlers[e].push(s);
|
|
25
|
+
}, this.emit = (e, ...s) => {
|
|
26
|
+
this.eventHandlers[e]?.forEach((t) => {
|
|
27
|
+
t(...s);
|
|
28
|
+
});
|
|
29
|
+
}, this.off = (e, s) => {
|
|
30
|
+
if (this.eventHandlers[e]) {
|
|
31
|
+
const t = this.eventHandlers[e].indexOf(s);
|
|
32
|
+
t > -1 && this.eventHandlers[e].splice(t, 1);
|
|
33
|
+
}
|
|
34
|
+
}, this.eventHandlers = {};
|
|
81
35
|
}
|
|
82
36
|
}
|
|
83
|
-
class
|
|
37
|
+
class F extends y {
|
|
84
38
|
#t;
|
|
85
|
-
// eslint-disable-next-line no-unused-private-class-members
|
|
86
|
-
#l;
|
|
87
39
|
#e;
|
|
88
|
-
#s;
|
|
89
|
-
#c;
|
|
90
|
-
#o;
|
|
91
40
|
#i;
|
|
92
|
-
#
|
|
41
|
+
#s;
|
|
93
42
|
#a;
|
|
94
43
|
#n;
|
|
44
|
+
#l;
|
|
45
|
+
#r;
|
|
46
|
+
#o;
|
|
95
47
|
/**
|
|
96
48
|
* @param {THREE.Scene} scene - The Three.js scene to use.
|
|
97
49
|
* @param {THREE.Camera} camera - The Three.js camera to use. Should usually
|
|
@@ -100,8 +52,8 @@ class q extends A {
|
|
|
100
52
|
* setGpsOptions() below.
|
|
101
53
|
* @param {Object} serverLogger - an object which can optionally log GPS position to a server for debugging. null by default, so no logging will be done. This object should implement a sendData() method to send data (2nd arg) to a given endpoint (1st arg). Please see source code for details. Ensure you comply with privacy laws (GDPR or equivalent) if implementing this.
|
|
102
54
|
*/
|
|
103
|
-
constructor(e,
|
|
104
|
-
super(), this.scene = e, this.camera =
|
|
55
|
+
constructor(e, s, t = {}, c = null) {
|
|
56
|
+
super(), this.scene = e, this.camera = s, this.#t = new w(), this.#e = null, this.#i = 0, this.#s = 100, this.#a = null, this.setGpsOptions(t), this.#n = null, this.#l = 0, this.#r = 0, this.#o = c;
|
|
105
57
|
}
|
|
106
58
|
/**
|
|
107
59
|
* Set the projection to use.
|
|
@@ -120,7 +72,7 @@ class q extends A {
|
|
|
120
72
|
* minimum accuracy, in metres, for a GPS reading to be counted.
|
|
121
73
|
*/
|
|
122
74
|
setGpsOptions(e = {}) {
|
|
123
|
-
e.gpsMinDistance !== void 0 && (this.#
|
|
75
|
+
e.gpsMinDistance !== void 0 && (this.#i = e.gpsMinDistance), e.gpsMinAccuracy !== void 0 && (this.#s = e.gpsMinAccuracy);
|
|
124
76
|
}
|
|
125
77
|
/**
|
|
126
78
|
* Start the GPS on a real device
|
|
@@ -128,14 +80,14 @@ class q extends A {
|
|
|
128
80
|
* GPS errors can be handled by handling the gpserror event.
|
|
129
81
|
*/
|
|
130
82
|
async startGps() {
|
|
131
|
-
if (this.#
|
|
132
|
-
const
|
|
133
|
-
gpsMinDistance: this.#
|
|
134
|
-
gpsMinAccuracy: this.#
|
|
83
|
+
if (this.#o) {
|
|
84
|
+
const s = await (await this.#o.sendData("/gps/start", {
|
|
85
|
+
gpsMinDistance: this.#i,
|
|
86
|
+
gpsMinAccuracy: this.#s
|
|
135
87
|
})).json();
|
|
136
|
-
this.#
|
|
88
|
+
this.#r = s.session;
|
|
137
89
|
}
|
|
138
|
-
return this.#
|
|
90
|
+
return this.#a === null ? (this.#a = navigator.geolocation.watchPosition(
|
|
139
91
|
(e) => {
|
|
140
92
|
this.#h(e);
|
|
141
93
|
},
|
|
@@ -153,7 +105,7 @@ class q extends A {
|
|
|
153
105
|
* stopped (i.e. it was never started).
|
|
154
106
|
*/
|
|
155
107
|
stopGps() {
|
|
156
|
-
return this.#
|
|
108
|
+
return this.#a !== null ? (navigator.geolocation.clearWatch(this.#a), this.#a = null, !0) : !1;
|
|
157
109
|
}
|
|
158
110
|
/**
|
|
159
111
|
* Send a fake GPS signal. Useful for testing on a desktop or laptop.
|
|
@@ -164,11 +116,11 @@ class q extends A {
|
|
|
164
116
|
* @param {number} acc - The accuracy of the GPS reading in metres. May be
|
|
165
117
|
* ignored if lower than the specified minimum accuracy.
|
|
166
118
|
*/
|
|
167
|
-
fakeGps(e,
|
|
119
|
+
fakeGps(e, s, t = null, c = 0) {
|
|
168
120
|
t !== null && this.setElevation(t), this.#h({
|
|
169
121
|
coords: {
|
|
170
122
|
longitude: e,
|
|
171
|
-
latitude:
|
|
123
|
+
latitude: s,
|
|
172
124
|
accuracy: c
|
|
173
125
|
}
|
|
174
126
|
});
|
|
@@ -184,10 +136,10 @@ class q extends A {
|
|
|
184
136
|
* @param {number} lat - The latitude.
|
|
185
137
|
* @return {Array} a two member array containing the WebGL x and z coordinates
|
|
186
138
|
*/
|
|
187
|
-
lonLatToWorldCoords(e,
|
|
188
|
-
const t = this.#t.project(e,
|
|
189
|
-
if (this.#
|
|
190
|
-
t[0] -= this.#
|
|
139
|
+
lonLatToWorldCoords(e, s) {
|
|
140
|
+
const t = this.#t.project(e, s);
|
|
141
|
+
if (this.#n)
|
|
142
|
+
t[0] -= this.#n[0], t[1] -= this.#n[1];
|
|
191
143
|
else
|
|
192
144
|
throw "No initial position determined";
|
|
193
145
|
return [t[0], -t[1]];
|
|
@@ -202,17 +154,17 @@ class q extends A {
|
|
|
202
154
|
* @param {Object} properties - properties describing the object (for example,
|
|
203
155
|
* the contents of the GeoJSON properties field).
|
|
204
156
|
*/
|
|
205
|
-
add(e,
|
|
206
|
-
e.properties = h, this.#
|
|
157
|
+
add(e, s, t, c, h = {}) {
|
|
158
|
+
e.properties = h, this.#c(e, s, t, c), this.scene.add(e), this.#o?.sendData("/object/new", {
|
|
207
159
|
position: e.position,
|
|
208
160
|
x: e.position.x,
|
|
209
161
|
z: e.position.z,
|
|
210
|
-
session: this.#
|
|
162
|
+
session: this.#r,
|
|
211
163
|
properties: h
|
|
212
164
|
});
|
|
213
165
|
}
|
|
214
|
-
#
|
|
215
|
-
const h = this.lonLatToWorldCoords(
|
|
166
|
+
#c(e, s, t, c) {
|
|
167
|
+
const h = this.lonLatToWorldCoords(s, t);
|
|
216
168
|
c !== void 0 && (e.position.y = c), [e.position.x, e.position.z] = h;
|
|
217
169
|
}
|
|
218
170
|
/**
|
|
@@ -222,48 +174,48 @@ class q extends A {
|
|
|
222
174
|
setElevation(e) {
|
|
223
175
|
this.camera.position.y = e;
|
|
224
176
|
}
|
|
225
|
-
#
|
|
226
|
-
this.#
|
|
177
|
+
#d(e, s) {
|
|
178
|
+
this.#n = this.#t.project(e, s);
|
|
227
179
|
}
|
|
228
180
|
#h(e) {
|
|
229
|
-
let
|
|
230
|
-
this.#
|
|
231
|
-
gpsCount: this.#
|
|
181
|
+
let s = Number.MAX_VALUE;
|
|
182
|
+
this.#l++, this.#o?.sendData("/gps/new", {
|
|
183
|
+
gpsCount: this.#l,
|
|
232
184
|
lat: e.coords.latitude,
|
|
233
185
|
lon: e.coords.longitude,
|
|
234
186
|
acc: e.coords.accuracy,
|
|
235
|
-
session: this.#
|
|
236
|
-
}), e.coords.accuracy <= this.#
|
|
187
|
+
session: this.#r
|
|
188
|
+
}), e.coords.accuracy <= this.#s && (this.#e === null ? this.#e = {
|
|
237
189
|
latitude: e.coords.latitude,
|
|
238
190
|
longitude: e.coords.longitude
|
|
239
|
-
} :
|
|
191
|
+
} : s = this.#u(this.#e, e.coords), s >= this.#i && (this.#e.longitude = e.coords.longitude, this.#e.latitude = e.coords.latitude, this.#n || (this.#d(
|
|
240
192
|
e.coords.longitude,
|
|
241
193
|
e.coords.latitude
|
|
242
|
-
), this.#
|
|
243
|
-
gpsCount: this.#
|
|
194
|
+
), this.#o?.sendData("/worldorigin/new", {
|
|
195
|
+
gpsCount: this.#l,
|
|
244
196
|
lat: e.coords.latitude,
|
|
245
197
|
lon: e.coords.longitude,
|
|
246
|
-
session: this.#
|
|
247
|
-
initialPosition: this.#
|
|
248
|
-
})), this.#
|
|
198
|
+
session: this.#r,
|
|
199
|
+
initialPosition: this.#n
|
|
200
|
+
})), this.#c(
|
|
249
201
|
this.camera,
|
|
250
202
|
e.coords.longitude,
|
|
251
203
|
e.coords.latitude
|
|
252
|
-
), this.#
|
|
253
|
-
gpsCount: this.#
|
|
204
|
+
), this.#o?.sendData("/gps/accepted", {
|
|
205
|
+
gpsCount: this.#l,
|
|
254
206
|
cameraX: this.camera.position.x,
|
|
255
207
|
cameraZ: this.camera.position.z,
|
|
256
|
-
session: this.#
|
|
257
|
-
distMoved:
|
|
258
|
-
}), this.emit("gpsupdate", { position: e, distMoved:
|
|
208
|
+
session: this.#r,
|
|
209
|
+
distMoved: s
|
|
210
|
+
}), this.emit("gpsupdate", { position: e, distMoved: s })));
|
|
259
211
|
}
|
|
260
212
|
/**
|
|
261
213
|
* Calculate haversine distance between two lat/lon pairs.
|
|
262
214
|
*
|
|
263
215
|
* Taken from original A-Frame AR.js location-based components
|
|
264
216
|
*/
|
|
265
|
-
#
|
|
266
|
-
const t =
|
|
217
|
+
#u(e, s) {
|
|
218
|
+
const t = g.MathUtils.degToRad(s.longitude - e.longitude), c = g.MathUtils.degToRad(s.latitude - e.latitude), h = Math.sin(c / 2) * Math.sin(c / 2) + Math.cos(g.MathUtils.degToRad(e.latitude)) * Math.cos(g.MathUtils.degToRad(s.latitude)) * (Math.sin(t / 2) * Math.sin(t / 2));
|
|
267
219
|
return 2 * Math.atan2(Math.sqrt(h), Math.sqrt(1 - h)) * 6371e3;
|
|
268
220
|
}
|
|
269
221
|
/**
|
|
@@ -275,74 +227,45 @@ class q extends A {
|
|
|
275
227
|
return this.#e;
|
|
276
228
|
}
|
|
277
229
|
}
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
/**
|
|
281
|
-
* Create a Webcam.
|
|
282
|
-
* @param constraints {Object} - options to use for initialising the camera.
|
|
283
|
-
* This is the same constraints object as used by standard MediaDevices API.
|
|
284
|
-
* @param {string} videoElementSelector - selector to obtain the HTML video
|
|
285
|
-
* element to render the webcam feed. If a falsy value (e.g. null or
|
|
286
|
-
* undefined), a video element will be created.
|
|
287
|
-
*/
|
|
288
|
-
constructor(e = { video: { facingMode: "environment" } }, i) {
|
|
289
|
-
super(), this.sceneWebcam = new m.Scene(), i ? this.#t = document.querySelector(i) : (this.#t = document.createElement("video"), this.#t.setAttribute("autoplay", !0), this.#t.setAttribute("playsinline", !0), this.#t.style.display = "none", document.body.appendChild(this.#t)), this.texture = new m.VideoTexture(this.#t), navigator.mediaDevices && navigator.mediaDevices.getUserMedia ? navigator.mediaDevices.getUserMedia(e).then((t) => {
|
|
290
|
-
this.#t.addEventListener("loadedmetadata", () => {
|
|
291
|
-
this.#t.setAttribute("width", this.#t.videoWidth), this.#t.setAttribute("height", this.#t.videoHeight), this.#t.play(), this.emit("webcamstarted", { texture: this.texture });
|
|
292
|
-
}), this.#t.srcObject = t;
|
|
293
|
-
}).catch((t) => {
|
|
294
|
-
this.emit("webcamerror", {
|
|
295
|
-
code: t.name,
|
|
296
|
-
message: t.message
|
|
297
|
-
});
|
|
298
|
-
}) : this.emit("webcamerror", {
|
|
299
|
-
code: "LOCAR_NO_MEDIA_DEVICES_API",
|
|
300
|
-
message: "Media devices API not supported"
|
|
301
|
-
});
|
|
302
|
-
}
|
|
303
|
-
/**
|
|
304
|
-
* Free up the memory associated with the webcam.
|
|
305
|
-
* Should be called when your application closes.
|
|
306
|
-
*/
|
|
307
|
-
dispose() {
|
|
308
|
-
this.texture.dispose();
|
|
309
|
-
}
|
|
310
|
-
}
|
|
311
|
-
const b = "locar-device-orientation-permission-modal", D = "locar-device-orientation-permission-button", S = "locar-device-orientation-permission-message", N = "locar-device-orientation-permission-inner", L = "locar-device-orientation-permission-button-inner", T = "This immersive website requires access to your device motion sensors.", O = navigator.userAgent.match(/iPhone|iPad|iPod/i) || /Macintosh/i.test(navigator.userAgent) && navigator.maxTouchPoints != null && navigator.maxTouchPoints > 1, x = new y(0, 0, 1), P = new C(), H = new I(), F = new I(-Math.sqrt(0.5), 0, 0, Math.sqrt(0.5));
|
|
312
|
-
class V extends w {
|
|
230
|
+
const R = "locar-device-orientation-permission-modal", P = "locar-device-orientation-permission-button", b = "locar-device-orientation-permission-message", D = "locar-device-orientation-permission-inner", S = "locar-device-orientation-permission-button-inner", I = "This immersive website requires access to your device motion sensors.", p = navigator.userAgent.match(/iPhone|iPad|iPod/i) || /Macintosh/i.test(navigator.userAgent) && navigator.maxTouchPoints != null && navigator.maxTouchPoints > 1, N = new T(0, 0, 1), A = new C(), x = new E(), L = new E(-Math.sqrt(0.5), 0, 0, Math.sqrt(0.5)), M = 2 * Math.PI, f = 0.5 * Math.PI;
|
|
231
|
+
class q extends _ {
|
|
313
232
|
/**
|
|
314
233
|
* Create an instance of DeviceOrientationControls.
|
|
315
234
|
* @param {Object} object - the object to attach the controls to
|
|
316
235
|
* (usually your Three.js camera)
|
|
317
|
-
* @param {Object} options - options for DeviceOrientationControls:
|
|
236
|
+
* @param {Object} options - options for DeviceOrientationControls:
|
|
318
237
|
* currently accepts smoothingFactor (< 1), enablePermissionDialog, orientationChangeThreshold (radians)
|
|
319
238
|
*/
|
|
320
|
-
constructor(e,
|
|
321
|
-
super(), this.
|
|
239
|
+
constructor(e, s = {}) {
|
|
240
|
+
super(), this.init = () => {
|
|
241
|
+
window.DeviceOrientationEvent === void 0 ? this.eventEmitter.emit("deviceorientationerror", {
|
|
242
|
+
code: "LOCAR_DEVICE_ORIENTATION_NOT_SUPPORTED",
|
|
243
|
+
message: "Device orientation API not supported"
|
|
244
|
+
}) : window.isSecureContext === !1 ? this.eventEmitter.emit("deviceorientationerror", {
|
|
245
|
+
code: "LOCAR_DEVICE_ORIENTATION_NO_HTTPS",
|
|
246
|
+
message: "DeviceOrientationEvent is only available in secure contexts (https)"
|
|
247
|
+
}) : typeof window.DeviceOrientationEvent.requestPermission == "function" && this.enablePermissionDialog ? this.obtainPermissionGesture() : this.eventEmitter.emit("deviceorientationgranted", { target: this });
|
|
248
|
+
}, this.eventEmitter = new y();
|
|
322
249
|
const t = this;
|
|
323
|
-
this.object = e, this.object.rotation.reorder("YXZ"), this.enabled = !0, this.deviceOrientation = null, this.screenOrientation = 0, this.alphaOffset = 0, this.orientationOffset = 0, this.initialOffset = null, this.lastCompassY = void 0, this.lastOrientation = null, this.
|
|
324
|
-
const c =
|
|
325
|
-
alpha: n,
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
}) {
|
|
330
|
-
if (O) {
|
|
331
|
-
const o = 360 - r;
|
|
332
|
-
t.alphaOffset = g.degToRad(o - n), t.deviceOrientation = { alpha: n, beta: s, gamma: a, webkitCompassHeading: r };
|
|
250
|
+
this.object = e, this.object.rotation.reorder("YXZ"), this.enabled = !0, this.deviceOrientation = null, this.screenOrientation = 0, this.alphaOffset = 0, this.orientationOffset = 0, this.initialOffset = null, this.lastCompassY = void 0, this.lastOrientation = null, this.orientationChangeEventName = "ondeviceorientationabsolute" in window ? "deviceorientationabsolute" : "deviceorientation", this.smoothingFactor = s.smoothingFactor || 1, this.enablePermissionDialog = s.enablePermissionDialog ?? !0, this.enableInlineStyling = s.enableStyling ?? !0, this.preferConfirmDialog = s.preferConfirmDialog ?? !1, this.orientationChangeThreshold = s.orientationChangeThreshold ?? 0;
|
|
251
|
+
const c = (i) => {
|
|
252
|
+
let { alpha: n, beta: a, gamma: r, webkitCompassHeading: o } = i;
|
|
253
|
+
if (n = n ?? 0, a = a ?? 0, r = r ?? 0, o = o ?? 0, p) {
|
|
254
|
+
const l = 360 - o;
|
|
255
|
+
t.alphaOffset = u.degToRad(l - n), t.deviceOrientation = { alpha: n, beta: a, gamma: r, webkitCompassHeading: o };
|
|
333
256
|
} else
|
|
334
|
-
n < 0 && (n += 360), t.deviceOrientation = { alpha: n, beta:
|
|
257
|
+
n < 0 && (n += 360), t.deviceOrientation = { alpha: n, beta: a, gamma: r };
|
|
335
258
|
window.dispatchEvent(
|
|
336
259
|
new CustomEvent("camera-rotation-change", {
|
|
337
260
|
detail: { cameraRotation: e.rotation }
|
|
338
261
|
})
|
|
339
262
|
);
|
|
340
|
-
}, h =
|
|
341
|
-
t.screenOrientation = window.orientation
|
|
342
|
-
},
|
|
343
|
-
|
|
263
|
+
}, h = () => {
|
|
264
|
+
t.screenOrientation = window.screen.orientation?.angle ?? 0, p && (t.screenOrientation === 90 ? t.orientationOffset = -f : t.screenOrientation === -90 ? t.orientationOffset = f : t.orientationOffset = 0);
|
|
265
|
+
}, O = (i, n, a, r, o) => {
|
|
266
|
+
A.set(a, n, -r, "YXZ"), i.setFromEuler(A), i.multiply(L), i.multiply(x.setFromAxisAngle(N, -o));
|
|
344
267
|
};
|
|
345
|
-
this.connect =
|
|
268
|
+
this.connect = () => {
|
|
346
269
|
h(), window.addEventListener(
|
|
347
270
|
"orientationchange",
|
|
348
271
|
h
|
|
@@ -350,7 +273,7 @@ class V extends w {
|
|
|
350
273
|
t.orientationChangeEventName,
|
|
351
274
|
c
|
|
352
275
|
), t.enabled = !0;
|
|
353
|
-
}, this.disconnect =
|
|
276
|
+
}, this.disconnect = () => {
|
|
354
277
|
window.removeEventListener(
|
|
355
278
|
"orientationchange",
|
|
356
279
|
h
|
|
@@ -358,215 +281,152 @@ class V extends w {
|
|
|
358
281
|
t.orientationChangeEventName,
|
|
359
282
|
c
|
|
360
283
|
), t.enabled = !1, t.initialOffset = !1, t.deviceOrientation = null;
|
|
361
|
-
}, this.requestOrientationPermissions =
|
|
362
|
-
window.DeviceOrientationEvent !== void 0 && typeof window.DeviceOrientationEvent.requestPermission == "function" ? window.DeviceOrientationEvent.requestPermission().then((
|
|
363
|
-
|
|
284
|
+
}, this.requestOrientationPermissions = () => {
|
|
285
|
+
window.DeviceOrientationEvent !== void 0 && typeof window.DeviceOrientationEvent.requestPermission == "function" ? window.DeviceOrientationEvent.requestPermission().then((i) => {
|
|
286
|
+
i === "granted" ? this.eventEmitter.emit("deviceorientationgranted", {
|
|
364
287
|
target: this
|
|
365
288
|
}) : this.eventEmitter.emit("deviceorientationerror", {
|
|
366
289
|
code: "LOCAR_DEVICE_ORIENTATION_PERMISSION_DENIED",
|
|
367
290
|
message: "Permission for device orientation denied - AR will not work correctly"
|
|
368
291
|
});
|
|
369
|
-
}).catch(
|
|
292
|
+
}).catch((i) => {
|
|
370
293
|
this.eventEmitter.emit("deviceorientationerror", {
|
|
371
294
|
code: "LOCAR_DEVICE_ORIENTATION_PERMISSION_FAILED",
|
|
372
295
|
message: "Permission request for device orientation failed - AR will not work correctly",
|
|
373
|
-
error: JSON.stringify(
|
|
296
|
+
error: JSON.stringify(i, null, 2)
|
|
374
297
|
});
|
|
375
298
|
}) : this.eventEmitter.emit("deviceorientationerror", {
|
|
376
299
|
code: "LOCAR_DEVICE_ORIENTATION_INTERNAL_ERROR",
|
|
377
300
|
message: "Internal error: no requestPermission() found although requestOrientationPermissions() was called - please raise an issue on GitHub"
|
|
378
301
|
});
|
|
379
|
-
}, this.update =
|
|
302
|
+
}, this.update = () => {
|
|
380
303
|
if (t.enabled === !1) return;
|
|
381
|
-
const
|
|
382
|
-
if (
|
|
383
|
-
let
|
|
384
|
-
const
|
|
304
|
+
const i = t.deviceOrientation;
|
|
305
|
+
if (i) {
|
|
306
|
+
let n = i.alpha ? u.degToRad(i.alpha) + t.alphaOffset : 0, a = i.beta ? u.degToRad(i.beta) : 0, r = i.gamma ? u.degToRad(i.gamma) : 0;
|
|
307
|
+
const o = t.screenOrientation ? u.degToRad(t.screenOrientation) : 0;
|
|
385
308
|
if (t.smoothingFactor < 1)
|
|
386
309
|
if (t.lastOrientation) {
|
|
387
|
-
const
|
|
388
|
-
|
|
389
|
-
|
|
310
|
+
const l = t.smoothingFactor;
|
|
311
|
+
n = t._getSmoothedAngle(
|
|
312
|
+
n,
|
|
390
313
|
t.lastOrientation.alpha,
|
|
391
|
-
|
|
392
|
-
),
|
|
393
|
-
|
|
314
|
+
l
|
|
315
|
+
), a = t._getSmoothedAngle(
|
|
316
|
+
a + Math.PI,
|
|
394
317
|
t.lastOrientation.beta,
|
|
395
|
-
|
|
396
|
-
),
|
|
397
|
-
|
|
318
|
+
l
|
|
319
|
+
), r = t._getSmoothedAngle(
|
|
320
|
+
r + f,
|
|
398
321
|
t.lastOrientation.gamma,
|
|
399
|
-
|
|
322
|
+
l,
|
|
400
323
|
Math.PI
|
|
401
324
|
);
|
|
402
325
|
} else
|
|
403
|
-
|
|
404
|
-
if (t.lastOrientation && (
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
326
|
+
a += Math.PI, r += f;
|
|
327
|
+
if (t.lastOrientation && (n = t._calcAngleWithThreshold(
|
|
328
|
+
n,
|
|
329
|
+
t.lastOrientation.alpha
|
|
330
|
+
), a = t._calcAngleWithThreshold(
|
|
331
|
+
a,
|
|
332
|
+
t.lastOrientation.beta
|
|
333
|
+
), r = t._calcAngleWithThreshold(
|
|
334
|
+
r,
|
|
335
|
+
t.lastOrientation.gamma
|
|
336
|
+
)), p) {
|
|
337
|
+
const l = new E();
|
|
338
|
+
O(
|
|
339
|
+
l,
|
|
340
|
+
n,
|
|
341
|
+
t.smoothingFactor < 1 ? a - Math.PI : a,
|
|
342
|
+
t.smoothingFactor < 1 ? r - Math.PI / 2 : r,
|
|
343
|
+
o
|
|
412
344
|
);
|
|
413
|
-
const
|
|
414
|
-
|
|
345
|
+
const v = new C().setFromQuaternion(
|
|
346
|
+
l,
|
|
415
347
|
"YXZ"
|
|
416
348
|
);
|
|
417
|
-
let
|
|
418
|
-
|
|
419
|
-
|
|
349
|
+
let d = u.degToRad(
|
|
350
|
+
360 - (i.webkitCompassHeading ?? 0)
|
|
351
|
+
);
|
|
352
|
+
t.smoothingFactor < 1 && t.lastCompassY !== void 0 && (d = t._getSmoothedAngle(
|
|
353
|
+
d,
|
|
420
354
|
t.lastCompassY,
|
|
421
355
|
t.smoothingFactor
|
|
422
|
-
)), t.lastCompassY =
|
|
356
|
+
)), t.lastCompassY = d, v.y = d + (t.orientationOffset || 0), l.setFromEuler(v), t.object.quaternion.copy(l);
|
|
423
357
|
} else
|
|
424
|
-
|
|
358
|
+
O(
|
|
425
359
|
t.object.quaternion,
|
|
426
|
-
|
|
427
|
-
t.smoothingFactor < 1 ?
|
|
428
|
-
t.smoothingFactor < 1 ?
|
|
429
|
-
|
|
360
|
+
p ? n + t.alphaOffset : n,
|
|
361
|
+
t.smoothingFactor < 1 ? a - Math.PI : a,
|
|
362
|
+
t.smoothingFactor < 1 ? r - f : r,
|
|
363
|
+
o
|
|
430
364
|
);
|
|
431
365
|
t.lastOrientation = {
|
|
432
|
-
alpha:
|
|
433
|
-
beta:
|
|
434
|
-
gamma:
|
|
366
|
+
alpha: n,
|
|
367
|
+
beta: a,
|
|
368
|
+
gamma: r
|
|
435
369
|
};
|
|
436
370
|
}
|
|
437
|
-
}, this.getCorrectedHeading =
|
|
438
|
-
const { deviceOrientation:
|
|
439
|
-
if (!
|
|
440
|
-
let
|
|
441
|
-
return
|
|
442
|
-
}, this._calcAngleWithThreshold =
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
o.left = 0, o.right -= f, o.right < 0 && (o.right += r);
|
|
449
|
-
let u = d == s ? (1 - a) * o.right + a * o.left : a * o.right + (1 - a) * o.left;
|
|
450
|
-
return u += f, u >= r && (u -= r), u;
|
|
451
|
-
}, this.updateAlphaOffset = function() {
|
|
371
|
+
}, this.getCorrectedHeading = () => {
|
|
372
|
+
const { deviceOrientation: i } = t;
|
|
373
|
+
if (!i) return 0;
|
|
374
|
+
let n = 0;
|
|
375
|
+
return p ? (n = 360 - (i.webkitCompassHeading ?? 0), t.orientationOffset && (n += t.orientationOffset * (180 / Math.PI), n = (n + 360) % 360)) : (i.absolute === !0 || t.orientationChangeEventName, n = i.alpha ? i.alpha : 0, n = (360 - n) % 360, n < 0 && (n += 360)), n;
|
|
376
|
+
}, this._calcAngleWithThreshold = (i, n) => Math.abs(i - n) < t.orientationChangeThreshold ? n : i, this._orderAngle = (i, n, a = M) => n > i && Math.abs(n - i) < a / 2 || i > n && Math.abs(n - i) > a / 2 ? { left: i, right: n } : { left: n, right: i }, this._getSmoothedAngle = (i, n, a, r = M) => {
|
|
377
|
+
const o = t._orderAngle(i, n, r), l = o.left, v = o.right;
|
|
378
|
+
o.left = 0, o.right -= l, o.right < 0 && (o.right += r);
|
|
379
|
+
let d = v == n ? (1 - a) * o.right + a * o.left : a * o.right + (1 - a) * o.left;
|
|
380
|
+
return d += l, d >= r && (d -= r), d;
|
|
381
|
+
}, this.updateAlphaOffset = () => {
|
|
452
382
|
t.initialOffset = !1;
|
|
453
|
-
}, this.dispose =
|
|
383
|
+
}, this.dispose = () => {
|
|
454
384
|
t.disconnect();
|
|
455
|
-
}, this.getAlpha =
|
|
456
|
-
const { deviceOrientation:
|
|
457
|
-
return
|
|
458
|
-
}, this.getBeta =
|
|
459
|
-
const { deviceOrientation:
|
|
460
|
-
return
|
|
461
|
-
}, this.getGamma =
|
|
462
|
-
const { deviceOrientation:
|
|
463
|
-
return
|
|
464
|
-
}, this.createObtainPermissionGestureDialog =
|
|
385
|
+
}, this.getAlpha = () => {
|
|
386
|
+
const { deviceOrientation: i } = t;
|
|
387
|
+
return i && i.alpha ? u.degToRad(i.alpha) + t.alphaOffset : 0;
|
|
388
|
+
}, this.getBeta = () => {
|
|
389
|
+
const { deviceOrientation: i } = t;
|
|
390
|
+
return i && i.beta ? u.degToRad(i.beta) : 0;
|
|
391
|
+
}, this.getGamma = () => {
|
|
392
|
+
const { deviceOrientation: i } = t;
|
|
393
|
+
return i && i.gamma ? u.degToRad(i.gamma) : 0;
|
|
394
|
+
}, this.createObtainPermissionGestureDialog = () => {
|
|
395
|
+
const i = document.createElement("div");
|
|
396
|
+
i.classList.add(R);
|
|
465
397
|
const n = document.createElement("div");
|
|
466
|
-
n.classList.add(
|
|
467
|
-
const s = document.createElement("div");
|
|
468
|
-
s.classList.add(N);
|
|
398
|
+
n.classList.add(D);
|
|
469
399
|
const a = document.createElement("div");
|
|
470
|
-
a.classList.add(
|
|
400
|
+
a.classList.add(b);
|
|
471
401
|
const r = document.createElement("div");
|
|
472
|
-
r.classList.add(
|
|
402
|
+
r.classList.add(S);
|
|
473
403
|
const o = document.createElement("button");
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
fontFamily: "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'",
|
|
477
|
-
display: "flex",
|
|
478
|
-
position: "fixed",
|
|
479
|
-
zIndex: 1e5,
|
|
480
|
-
justifyContent: "center",
|
|
481
|
-
alignItems: "center",
|
|
482
|
-
backgroundColor: "rgba(0,0,0,0.2)",
|
|
483
|
-
inset: 0,
|
|
484
|
-
padding: "20px"
|
|
485
|
-
}, u = {
|
|
486
|
-
backgroundColor: "rgba(220, 220, 220, 0.85)",
|
|
487
|
-
padding: "6px 0",
|
|
488
|
-
borderRadius: "10px",
|
|
489
|
-
width: "100%",
|
|
490
|
-
maxWidth: "400px"
|
|
491
|
-
}, p = {
|
|
492
|
-
padding: "10px 12px",
|
|
493
|
-
textAlign: "center",
|
|
494
|
-
fontWeight: 400,
|
|
495
|
-
fontSize: "13px",
|
|
496
|
-
display: "flex",
|
|
497
|
-
justifyContent: "center",
|
|
498
|
-
alignItems: "center"
|
|
499
|
-
}, M = {
|
|
500
|
-
display: "block",
|
|
501
|
-
textAlign: "center",
|
|
502
|
-
textDecoration: "none",
|
|
503
|
-
borderTop: "rgb(180,180,180) solid 1px"
|
|
504
|
-
}, _ = {
|
|
505
|
-
display: "block",
|
|
506
|
-
width: "100%",
|
|
507
|
-
textAlign: "center",
|
|
508
|
-
appearance: "none",
|
|
509
|
-
background: "none",
|
|
510
|
-
border: "none",
|
|
511
|
-
outline: "none",
|
|
512
|
-
padding: "10px",
|
|
513
|
-
fontWeight: 400,
|
|
514
|
-
fontSize: "16px",
|
|
515
|
-
color: "#2e7cf1",
|
|
516
|
-
cursor: "pointer"
|
|
517
|
-
};
|
|
518
|
-
for (let l in d)
|
|
519
|
-
n.style[l] = d[l];
|
|
520
|
-
for (let l in u)
|
|
521
|
-
s.style[l] = u[l];
|
|
522
|
-
for (let l in p)
|
|
523
|
-
a.style[l] = p[l];
|
|
524
|
-
for (let l in M)
|
|
525
|
-
r.style[l] = M[l];
|
|
526
|
-
for (let l in _)
|
|
527
|
-
o.style[l] = _[l];
|
|
528
|
-
}
|
|
529
|
-
n.appendChild(s), s.appendChild(a), s.appendChild(r), a.appendChild(
|
|
530
|
-
document.createTextNode(T)
|
|
404
|
+
o.classList.add(P), document.body.appendChild(i), this.enableInlineStyling === !0 && (i.style.fontFamily = "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'", i.style.display = "flex", i.style.position = "fixed", i.style.zIndex = "100000", i.style.justifyContent = "center", i.style.alignItems = "center", i.style.backgroundColor = "rgba(0,0,0,0.2)", i.style.inset = "0", i.style.padding = "20px", n.style.backgroundColor = "rgba(220, 220, 220, 0.85)", n.style.padding = "6px 0", n.style.borderRadius = "10px", n.style.width = "100%", n.style.maxWidth = "400px", a.style.padding = "10px 12px", a.style.textAlign = "center", a.style.fontWeight = "400", a.style.fontSize = "13px", a.style.display = "flex", a.style.justifyContent = "center", a.style.alignItems = "center", r.style.display = "block", r.style.textAlign = "center", r.style.textDecoration = "none", r.style.borderTop = "rgb(180,180,180) solid 1px", o.style.display = "block", o.style.width = "100%", o.style.textAlign = "center", o.style.appearance = "none", o.style.background = "none", o.style.border = "none", o.style.outline = "none", o.style.padding = "10px", o.style.fontWeight = "400", o.style.fontSize = "16px", o.style.color = "#2e7cf1", o.style.cursor = "pointer"), i.appendChild(n), n.appendChild(a), n.appendChild(r), a.appendChild(
|
|
405
|
+
document.createTextNode(I)
|
|
531
406
|
);
|
|
532
|
-
const
|
|
533
|
-
this.requestOrientationPermissions(),
|
|
407
|
+
const l = () => {
|
|
408
|
+
this.requestOrientationPermissions(), i.style.display = "none";
|
|
534
409
|
};
|
|
535
|
-
o.addEventListener("click",
|
|
536
|
-
}, this.obtainPermissionGesture =
|
|
537
|
-
this.preferConfirmDialog === !0 ? window.confirm(
|
|
410
|
+
o.addEventListener("click", l), o.appendChild(document.createTextNode("OK")), r.appendChild(o), document.body.appendChild(i);
|
|
411
|
+
}, this.obtainPermissionGesture = () => {
|
|
412
|
+
this.preferConfirmDialog === !0 ? window.confirm(I) && this.requestOrientationPermissions() : this.createObtainPermissionGestureDialog();
|
|
538
413
|
};
|
|
539
414
|
}
|
|
540
|
-
on(e,
|
|
541
|
-
this.eventEmitter.on(e,
|
|
542
|
-
}
|
|
543
|
-
/**
|
|
544
|
-
* Initialise device orientation controls.
|
|
545
|
-
* Should be called after you have created the DeviceOrientationControls
|
|
546
|
-
* object and set up the deviceorientationgranted and deviceorientationerror
|
|
547
|
-
* event handlers.
|
|
548
|
-
*/
|
|
549
|
-
init() {
|
|
550
|
-
window.DeviceOrientationEvent === void 0 ? this.eventEmitter.emit("deviceorientationerror", {
|
|
551
|
-
code: "LOCAR_DEVICE_ORIENTATION_NOT_SUPPORTED",
|
|
552
|
-
message: "Device orientation API not supported"
|
|
553
|
-
}) : window.isSecureContext === !1 ? this.eventEmitter.emit("deviceorientationerror", {
|
|
554
|
-
code: "LOCAR_DEVICE_ORIENTATION_NO_HTTPS",
|
|
555
|
-
message: "DeviceOrientationEvent is only available in secure contexts (https)"
|
|
556
|
-
}) : typeof window.DeviceOrientationEvent.requestPermission == "function" && this.enablePermissionDialog ? this.obtainPermissionGesture() : this.eventEmitter.emit("deviceorientationgranted", { target: this });
|
|
415
|
+
on(e, s) {
|
|
416
|
+
this.eventEmitter.on(e, s);
|
|
557
417
|
}
|
|
558
418
|
}
|
|
559
|
-
class
|
|
419
|
+
class W {
|
|
560
420
|
/**
|
|
561
421
|
* Create a ClickHandler.
|
|
562
422
|
* @param {THREE.WebGLRenderer} - The Three.js renderer on which the click
|
|
563
423
|
* events will be handled.
|
|
564
424
|
*/
|
|
565
425
|
constructor(e) {
|
|
566
|
-
this.raycaster = new
|
|
567
|
-
this.normalisedMousePosition.
|
|
568
|
-
|
|
569
|
-
-(
|
|
426
|
+
this.raycaster = new g.Raycaster(), this.normalisedMousePosition = null, e.domElement.addEventListener("click", (s) => {
|
|
427
|
+
this.normalisedMousePosition = new g.Vector2(
|
|
428
|
+
s.clientX / e.domElement.clientWidth * 2 - 1,
|
|
429
|
+
-(s.clientY / e.domElement.clientHeight * 2) + 1
|
|
570
430
|
);
|
|
571
431
|
});
|
|
572
432
|
}
|
|
@@ -578,22 +438,61 @@ class j {
|
|
|
578
438
|
* cast into.
|
|
579
439
|
* @return {Array} - array of all intersected objects.
|
|
580
440
|
*/
|
|
581
|
-
raycast(e,
|
|
582
|
-
if (this.normalisedMousePosition
|
|
441
|
+
raycast(e, s) {
|
|
442
|
+
if (this.normalisedMousePosition !== null) {
|
|
583
443
|
this.raycaster.setFromCamera(this.normalisedMousePosition, e);
|
|
584
|
-
const t = this.raycaster.intersectObjects(
|
|
585
|
-
return this.normalisedMousePosition
|
|
444
|
+
const t = this.raycaster.intersectObjects(s.children, !1);
|
|
445
|
+
return this.normalisedMousePosition = null, t;
|
|
586
446
|
}
|
|
587
447
|
return [];
|
|
588
448
|
}
|
|
589
449
|
}
|
|
590
|
-
|
|
450
|
+
class V extends y {
|
|
451
|
+
#t;
|
|
452
|
+
/**
|
|
453
|
+
* Create a Webcam.
|
|
454
|
+
* @param constraints {Object} - options to use for initialising the camera.
|
|
455
|
+
* This is the same constraints object as used by standard MediaDevices API.
|
|
456
|
+
* @param {string} videoElementSelector - selector to obtain the HTML video
|
|
457
|
+
* element to render the webcam feed. If a falsy value (e.g. null or
|
|
458
|
+
* undefined), a video element will be created.
|
|
459
|
+
*/
|
|
460
|
+
constructor(e = { video: { facingMode: "environment" } }, s) {
|
|
461
|
+
super(), this.sceneWebcam = new g.Scene(), s ? this.#t = document.querySelector(s) : (this.#t = document.createElement("video"), this.#t.setAttribute("autoplay", "true"), this.#t.setAttribute("playsinline", "true"), this.#t.style.display = "none", document.body.appendChild(this.#t)), this.texture = this.#t ? new g.VideoTexture(this.#t) : null, navigator.mediaDevices && navigator.mediaDevices.getUserMedia ? navigator.mediaDevices.getUserMedia(e).then((t) => {
|
|
462
|
+
this.#t?.addEventListener("loadedmetadata", () => {
|
|
463
|
+
this.#t?.setAttribute(
|
|
464
|
+
"width",
|
|
465
|
+
this.#t?.videoWidth.toString() ?? "0"
|
|
466
|
+
), this.#t?.setAttribute(
|
|
467
|
+
"height",
|
|
468
|
+
this.#t?.videoHeight.toString() ?? "0"
|
|
469
|
+
), this.#t?.play(), this.emit("webcamstarted", { texture: this.texture });
|
|
470
|
+
}), this.#t && (this.#t.srcObject = t);
|
|
471
|
+
}).catch((t) => {
|
|
472
|
+
this.emit("webcamerror", {
|
|
473
|
+
code: t.name,
|
|
474
|
+
message: t.message
|
|
475
|
+
});
|
|
476
|
+
}) : this.emit("webcamerror", {
|
|
477
|
+
code: "LOCAR_NO_MEDIA_DEVICES_API",
|
|
478
|
+
message: "Media devices API not supported"
|
|
479
|
+
});
|
|
480
|
+
}
|
|
481
|
+
/**
|
|
482
|
+
* Free up the memory associated with the webcam.
|
|
483
|
+
* Should be called when your application closes.
|
|
484
|
+
*/
|
|
485
|
+
dispose() {
|
|
486
|
+
this.texture?.dispose();
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
const j = "0.1.7";
|
|
591
490
|
export {
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
491
|
+
W as ClickHandler,
|
|
492
|
+
q as DeviceOrientationControls,
|
|
493
|
+
y as EventEmitter,
|
|
494
|
+
F as LocationBased,
|
|
495
|
+
w as SphMercProjection,
|
|
496
|
+
V as Webcam,
|
|
497
|
+
j as version
|
|
599
498
|
};
|