locar 0.1.6 → 0.1.8

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.es.js CHANGED
@@ -1,97 +1,49 @@
1
- import * as m from "three";
2
- import { Vector3 as y, Euler as C, Quaternion as I, EventDispatcher as w, MathUtils as g } from "three";
1
+ import * as u from "three";
2
+ import { Vector3 as T, Euler as w, Quaternion as f, EventDispatcher as A, MathUtils as h } from "three";
3
3
  class R {
4
4
  /**
5
5
  * Create a SphMercProjection.
6
6
  */
7
7
  constructor() {
8
- this.EARTH = 4007501668e-2, this.HALF_EARTH = 2003750834e-2;
9
- }
10
- /**
11
- * Project a longitude and latitude into Spherical Mercator.
12
- * @param {number} lon - the longitude.
13
- * @param {number} lat - the latitude.
14
- * @return {Array} Two-member array containing easting and northing.
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, i) => [this.#e(e), this.#t(i)], this.unproject = (e) => [this.#i(e[0]), this.#s(e[1])], this.#e = (e) => e / 180 * this.HALF_EARTH, this.#t = (e) => {
9
+ var i = Math.log(Math.tan((90 + e) * Math.PI / 360)) / (Math.PI / 180);
10
+ return i * this.HALF_EARTH / 180;
11
+ }, this.#i = (e) => e / this.HALF_EARTH * 180, this.#s = (e) => {
12
+ var i = e / this.HALF_EARTH * 180;
13
+ return i = 180 / Math.PI * (2 * Math.atan(Math.exp(i * Math.PI / 180)) - Math.PI / 2), i;
14
+ }, this.getID = () => "epsg:3857", this.EARTH = 4007501668e-2, this.HALF_EARTH = 2003750834e-2;
47
15
  }
16
+ #e;
17
+ #t;
18
+ #i;
19
+ #s;
48
20
  }
49
- class A {
21
+ class E {
50
22
  constructor() {
51
- this.eventHandlers = {};
52
- }
53
- /**
54
- * Add an event handler.
55
- * @param {string} eventName - the event to handle.
56
- * @param {Function} eventHandler - the event handler function.
57
- */
58
- on(e, i) {
59
- this.eventHandlers[e] === void 0 && (this.eventHandlers[e] = []), this.eventHandlers[e].push(i);
60
- }
61
- /**
62
- * Emit an event.
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, i) => {
24
+ this.eventHandlers[e] === void 0 && (this.eventHandlers[e] = []), this.eventHandlers[e].push(i);
25
+ }, this.emit = (e, ...i) => {
26
+ this.eventHandlers[e]?.forEach((t) => {
27
+ t(...i);
28
+ });
29
+ }, this.off = (e, i) => {
30
+ if (this.eventHandlers[e]) {
31
+ const t = this.eventHandlers[e].indexOf(i);
32
+ t > -1 && this.eventHandlers[e].splice(t, 1);
33
+ }
34
+ }, this.eventHandlers = {};
81
35
  }
82
36
  }
83
- class q extends A {
84
- #t;
85
- // eslint-disable-next-line no-unused-private-class-members
86
- #l;
37
+ class H extends E {
87
38
  #e;
88
- #s;
89
- #c;
90
- #o;
39
+ #t;
91
40
  #i;
92
- #r;
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, i, t = {}, c = null) {
104
- super(), this.scene = e, this.camera = i, this.#t = new R(), this.#e = null, this.#s = 0, this.#c = 100, this.#o = null, this.setGpsOptions(t), this.#i = null, this.#r = 0, this.#a = 0, this.#n = c;
55
+ constructor(e, i, t = {}, l = null) {
56
+ super(), this.scene = e, this.camera = i, this.#e = new R(), this.#t = null, this.#i = 0, this.#s = 100, this.#a = null, this.setGpsOptions(t), this.#n = null, this.#l = 0, this.#r = 0, this.#o = l;
105
57
  }
106
58
  /**
107
59
  * Set the projection to use.
@@ -110,7 +62,7 @@ class q extends A {
110
62
  * containing easting and northing.
111
63
  */
112
64
  setProjection(e) {
113
- this.#t = e;
65
+ this.#e = e;
114
66
  }
115
67
  /**
116
68
  * Set the GPS options.
@@ -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.#s = e.gpsMinDistance), e.gpsMinAccuracy !== void 0 && (this.#c = e.gpsMinAccuracy);
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,16 +80,16 @@ 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.#n) {
132
- const i = await (await this.#n.sendData("/gps/start", {
133
- gpsMinDistance: this.#s,
134
- gpsMinAccuracy: this.#c
83
+ if (this.#o) {
84
+ const i = await (await this.#o.sendData("/gps/start", {
85
+ gpsMinDistance: this.#i,
86
+ gpsMinAccuracy: this.#s
135
87
  })).json();
136
- this.#a = i.session;
88
+ this.#r = i.session;
137
89
  }
138
- return this.#o === null ? (this.#o = navigator.geolocation.watchPosition(
90
+ return this.#a === null ? (this.#a = navigator.geolocation.watchPosition(
139
91
  (e) => {
140
- this.#h(e);
92
+ this.#d(e);
141
93
  },
142
94
  (e) => {
143
95
  this.emit("gpserror", e);
@@ -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.#o !== null ? (navigator.geolocation.clearWatch(this.#o), this.#o = null, !0) : !1;
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,12 +116,12 @@ 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, i, t = null, c = 0) {
168
- t !== null && this.setElevation(t), this.#h({
119
+ fakeGps(e, i, t = null, l = 0) {
120
+ t !== null && this.setElevation(t), this.#d({
169
121
  coords: {
170
122
  longitude: e,
171
123
  latitude: i,
172
- accuracy: c
124
+ accuracy: l
173
125
  }
174
126
  });
175
127
  }
@@ -185,9 +137,9 @@ class q extends A {
185
137
  * @return {Array} a two member array containing the WebGL x and z coordinates
186
138
  */
187
139
  lonLatToWorldCoords(e, i) {
188
- const t = this.#t.project(e, i);
189
- if (this.#i)
190
- t[0] -= this.#i[0], t[1] -= this.#i[1];
140
+ const t = this.#e.project(e, i);
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,18 +154,18 @@ 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, i, t, c, h = {}) {
206
- e.properties = h, this.#d(e, i, t, c), this.scene.add(e), this.#n?.sendData("/object/new", {
157
+ add(e, i, t, l, c = {}) {
158
+ e.properties = c, this.#c(e, i, t, l), 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.#a,
211
- properties: h
162
+ session: this.#r,
163
+ properties: c
212
164
  });
213
165
  }
214
- #d(e, i, t, c) {
215
- const h = this.lonLatToWorldCoords(i, t);
216
- c !== void 0 && (e.position.y = c), [e.position.x, e.position.z] = h;
166
+ #c(e, i, t, l) {
167
+ const c = this.lonLatToWorldCoords(i, t);
168
+ l !== void 0 && (e.position.y = l), [e.position.x, e.position.z] = c;
217
169
  }
218
170
  /**
219
171
  * Set the elevation (y coordinate) of the camera.
@@ -222,38 +174,38 @@ class q extends A {
222
174
  setElevation(e) {
223
175
  this.camera.position.y = e;
224
176
  }
225
- #u(e, i) {
226
- this.#i = this.#t.project(e, i);
177
+ #h(e, i) {
178
+ this.#n = this.#e.project(e, i);
227
179
  }
228
- #h(e) {
180
+ #d(e) {
229
181
  let i = Number.MAX_VALUE;
230
- this.#r++, this.#n?.sendData("/gps/new", {
231
- gpsCount: this.#r,
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.#a
236
- }), e.coords.accuracy <= this.#c && (this.#e === null ? this.#e = {
187
+ session: this.#r
188
+ }), e.coords.accuracy <= this.#s && (this.#t === null ? this.#t = {
237
189
  latitude: e.coords.latitude,
238
190
  longitude: e.coords.longitude
239
- } : i = this.#g(this.#e, e.coords), i >= this.#s && (this.#e.longitude = e.coords.longitude, this.#e.latitude = e.coords.latitude, this.#i || (this.#u(
191
+ } : i = this.#u(this.#t, e.coords), i >= this.#i && (this.#t.longitude = e.coords.longitude, this.#t.latitude = e.coords.latitude, this.#n || (this.#h(
240
192
  e.coords.longitude,
241
193
  e.coords.latitude
242
- ), this.#n?.sendData("/worldorigin/new", {
243
- gpsCount: this.#r,
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.#a,
247
- initialPosition: this.#i
248
- })), this.#d(
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.#n?.sendData("/gps/accepted", {
253
- gpsCount: this.#r,
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.#a,
208
+ session: this.#r,
257
209
  distMoved: i
258
210
  }), this.emit("gpsupdate", { position: e, distMoved: i })));
259
211
  }
@@ -262,9 +214,9 @@ class q extends A {
262
214
  *
263
215
  * Taken from original A-Frame AR.js location-based components
264
216
  */
265
- #g(e, i) {
266
- const t = m.MathUtils.degToRad(i.longitude - e.longitude), c = m.MathUtils.degToRad(i.latitude - e.latitude), h = Math.sin(c / 2) * Math.sin(c / 2) + Math.cos(m.MathUtils.degToRad(e.latitude)) * Math.cos(m.MathUtils.degToRad(i.latitude)) * (Math.sin(t / 2) * Math.sin(t / 2));
267
- return 2 * Math.atan2(Math.sqrt(h), Math.sqrt(1 - h)) * 6371e3;
217
+ #u(e, i) {
218
+ const t = u.MathUtils.degToRad(i.longitude - e.longitude), l = u.MathUtils.degToRad(i.latitude - e.latitude), c = Math.sin(l / 2) * Math.sin(l / 2) + Math.cos(u.MathUtils.degToRad(e.latitude)) * Math.cos(u.MathUtils.degToRad(i.latitude)) * (Math.sin(t / 2) * Math.sin(t / 2));
219
+ return 2 * Math.atan2(Math.sqrt(c), Math.sqrt(1 - c)) * 6371e3;
268
220
  }
269
221
  /**
270
222
  * Obtain the last known GPS location.
@@ -272,299 +224,163 @@ class q extends A {
272
224
  * @return {Object} object containing latitude and longitude fields, or null if no previous GPS location.
273
225
  */
274
226
  getLastKnownLocation() {
275
- return this.#e;
227
+ return this.#t;
276
228
  }
277
229
  }
278
- class k extends A {
279
- #t;
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 b = "locar-device-orientation-permission-modal", M = "locar-device-orientation-permission-button", _ = "locar-device-orientation-permission-message", D = "locar-device-orientation-permission-inner", P = "locar-device-orientation-permission-button-inner", O = "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), y = new w(), S = new f(), x = new f(-Math.sqrt(0.5), 0, 0, Math.sqrt(0.5)), I = 0.5 * Math.PI;
231
+ class q extends A {
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
239
  constructor(e, i = {}) {
321
- super(), this.eventEmitter = new A();
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 E();
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.TWO_PI = 2 * Math.PI, this.HALF_PI = 0.5 * Math.PI, this.orientationChangeEventName = "ondeviceorientationabsolute" in window ? "deviceorientationabsolute" : "deviceorientation", this.smoothingFactor = i.smoothingFactor || 1, this.enablePermissionDialog = i.enablePermissionDialog ?? !0, this.enableInlineStyling = i.enableStyling ?? !0, this.preferConfirmDialog = i.preferConfirmDialog ?? !1, this.orientationChangeThreshold = i.orientationChangeThreshold ?? 0;
324
- const c = function({
325
- alpha: n,
326
- beta: s,
327
- gamma: a,
328
- webkitCompassHeading: r
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.lastQuaternion = null, this.orientationChangeEventName = "ondeviceorientationabsolute" in window ? "deviceorientationabsolute" : "deviceorientation", this.smoothingFactor = i.smoothingFactor || 1, this.enablePermissionDialog = i.enablePermissionDialog ?? !0, this.enableInlineStyling = i.enableStyling ?? !0, this.preferConfirmDialog = i.preferConfirmDialog ?? !1, this.orientationChangeThreshold = i.orientationChangeThreshold ?? 0;
251
+ const l = (s) => {
252
+ let { alpha: n, beta: a, gamma: r, webkitCompassHeading: o } = s;
253
+ if (n = n ?? 0, a = a ?? 0, r = r ?? 0, o = o ?? 0, p) {
254
+ const d = 360 - o;
255
+ t.alphaOffset = h.degToRad(d - n), t.deviceOrientation = { alpha: n, beta: a, gamma: r, webkitCompassHeading: o };
333
256
  } else
334
- n < 0 && (n += 360), t.deviceOrientation = { alpha: n, beta: s, gamma: a };
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 = function() {
341
- t.screenOrientation = window.orientation || 0, O && (t.screenOrientation === 90 ? t.orientationOffset = -t.HALF_PI : t.screenOrientation === -90 ? t.orientationOffset = t.HALF_PI : t.orientationOffset = 0);
342
- }, E = function(n, s, a, r, o) {
343
- P.set(a, s, -r, "YXZ"), n.setFromEuler(P), n.multiply(F), n.multiply(H.setFromAxisAngle(x, -o));
263
+ }, c = () => {
264
+ t.screenOrientation = window.screen.orientation?.angle ?? 0, p && (t.screenOrientation === 90 ? t.orientationOffset = -I : t.screenOrientation === -90 ? t.orientationOffset = I : t.orientationOffset = 0);
265
+ }, v = (s, n, a, r, o) => {
266
+ y.set(a, n, -r, "YXZ"), s.setFromEuler(y), s.multiply(x), s.multiply(S.setFromAxisAngle(N, -o));
344
267
  };
345
- this.connect = function() {
346
- h(), window.addEventListener(
268
+ this.connect = () => {
269
+ c(), window.addEventListener(
347
270
  "orientationchange",
348
- h
271
+ c
349
272
  ), window.addEventListener(
350
273
  t.orientationChangeEventName,
351
- c
274
+ l
352
275
  ), t.enabled = !0;
353
- }, this.disconnect = function() {
276
+ }, this.disconnect = () => {
354
277
  window.removeEventListener(
355
278
  "orientationchange",
356
- h
279
+ c
357
280
  ), window.removeEventListener(
358
281
  t.orientationChangeEventName,
359
- c
360
- ), t.enabled = !1, t.initialOffset = !1, t.deviceOrientation = null;
361
- }, this.requestOrientationPermissions = function() {
362
- window.DeviceOrientationEvent !== void 0 && typeof window.DeviceOrientationEvent.requestPermission == "function" ? window.DeviceOrientationEvent.requestPermission().then((n) => {
363
- n === "granted" ? this.eventEmitter.emit("deviceorientationgranted", {
282
+ l
283
+ ), t.enabled = !1, t.initialOffset = !1, t.deviceOrientation = null, t.lastQuaternion = null;
284
+ }, this.requestOrientationPermissions = () => {
285
+ window.DeviceOrientationEvent !== void 0 && typeof window.DeviceOrientationEvent.requestPermission == "function" ? window.DeviceOrientationEvent.requestPermission().then((s) => {
286
+ s === "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(function(n) {
292
+ }).catch((s) => {
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(n, null, 2)
296
+ error: JSON.stringify(s, 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 = function({ theta: n = 0 } = { theta: 0 }) {
302
+ }, this.update = () => {
380
303
  if (t.enabled === !1) return;
381
304
  const s = t.deviceOrientation;
382
305
  if (s) {
383
- let a = s.alpha ? g.degToRad(s.alpha) + t.alphaOffset : 0, r = s.beta ? g.degToRad(s.beta) : 0, o = s.gamma ? g.degToRad(s.gamma) : 0;
384
- const f = t.screenOrientation ? g.degToRad(t.screenOrientation) : 0;
385
- if (t.smoothingFactor < 1)
386
- if (t.lastOrientation) {
387
- const d = t.smoothingFactor;
388
- a = t._getSmoothedAngle(
389
- a,
390
- t.lastOrientation.alpha,
391
- d
392
- ), r = t._getSmoothedAngle(
393
- r + Math.PI,
394
- t.lastOrientation.beta,
395
- d
396
- ), o = t._getSmoothedAngle(
397
- o + t.HALF_PI,
398
- t.lastOrientation.gamma,
399
- d,
400
- Math.PI
401
- );
402
- } else
403
- r += Math.PI, o += t.HALF_PI;
404
- if (t.lastOrientation && (a = t._calcAngleWithThreshold(a, t.lastOrientation.alpha), r = t._calcAngleWithThreshold(r, t.lastOrientation.beta), o = t._calcAngleWithThreshold(o, t.lastOrientation.gamma)), O) {
405
- const d = new I();
406
- E(
407
- d,
408
- a,
409
- t.smoothingFactor < 1 ? r - Math.PI : r,
410
- t.smoothingFactor < 1 ? o - Math.PI / 2 : o,
411
- f
412
- );
413
- const u = new C().setFromQuaternion(
306
+ let n = s.alpha ? h.degToRad(s.alpha) + t.alphaOffset : 0, a = s.beta ? h.degToRad(s.beta) : 0, r = s.gamma ? h.degToRad(s.gamma) : 0;
307
+ const o = t.screenOrientation ? h.degToRad(t.screenOrientation) : 0, d = new f();
308
+ if (p) {
309
+ v(d, n, a, r, o);
310
+ const g = new w().setFromQuaternion(
414
311
  d,
415
312
  "YXZ"
313
+ ), C = h.degToRad(
314
+ 360 - (s.webkitCompassHeading ?? 0)
416
315
  );
417
- let p = g.degToRad(360 - s.webkitCompassHeading);
418
- t.smoothingFactor < 1 && t.lastCompassY !== void 0 && (p = t._getSmoothedAngle(
419
- p,
420
- t.lastCompassY,
421
- t.smoothingFactor
422
- )), t.lastCompassY = p, u.y = p + (t.orientationOffset || 0), d.setFromEuler(u), t.object.quaternion.copy(d);
316
+ g.y = C + (t.orientationOffset || 0), d.setFromEuler(g);
423
317
  } else
424
- E(
425
- t.object.quaternion,
426
- O ? a + t.alphaOffset : a,
427
- t.smoothingFactor < 1 ? r - Math.PI : r,
428
- t.smoothingFactor < 1 ? o - Math.PI / 2 : o,
429
- f
430
- );
431
- t.lastOrientation = {
432
- alpha: a,
433
- beta: r,
434
- gamma: o
435
- };
318
+ v(d, n, a, r, o);
319
+ if (t.lastQuaternion && t.orientationChangeThreshold > 0 && d.angleTo(t.lastQuaternion) < t.orientationChangeThreshold)
320
+ return;
321
+ if (t.smoothingFactor < 1 && t.lastQuaternion) {
322
+ const g = 1 - t.smoothingFactor;
323
+ t.object.quaternion.slerp(d, g);
324
+ } else
325
+ t.object.quaternion.copy(d);
326
+ t.lastQuaternion = t.object.quaternion.clone(), window.dispatchEvent(
327
+ new CustomEvent("camera-rotation-change", {
328
+ detail: { cameraRotation: t.object.rotation }
329
+ })
330
+ );
436
331
  }
437
- }, this.getCorrectedHeading = function() {
438
- const { deviceOrientation: n } = t;
439
- if (!n) return 0;
440
- let s = 0;
441
- return O ? (s = 360 - n.webkitCompassHeading, t.orientationOffset && (s += t.orientationOffset * (180 / Math.PI), s = (s + 360) % 360)) : (n.absolute === !0 || t.orientationChangeEventName, s = n.alpha ? n.alpha : 0, s = (360 - s) % 360, s < 0 && (s += 360)), s;
442
- }, this._calcAngleWithThreshold = function(n, s) {
443
- return Math.abs(n - s) < t.orientationChangeThreshold ? s : n;
444
- }, this._orderAngle = function(n, s, a = t.TWO_PI) {
445
- return s > n && Math.abs(s - n) < a / 2 || n > s && Math.abs(s - n) > a / 2 ? { left: n, right: s } : { left: s, right: n };
446
- }, this._getSmoothedAngle = function(n, s, a, r = t.TWO_PI) {
447
- const o = t._orderAngle(n, s, r), f = o.left, d = o.right;
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() {
332
+ }, this.getCorrectedHeading = () => {
333
+ const { deviceOrientation: s } = t;
334
+ if (!s) return 0;
335
+ let n = 0;
336
+ return p ? (n = 360 - (s.webkitCompassHeading ?? 0), t.orientationOffset && (n += t.orientationOffset * (180 / Math.PI), n = (n + 360) % 360)) : (s.absolute === !0 || t.orientationChangeEventName, n = s.alpha ? s.alpha : 0, n = (360 - n) % 360, n < 0 && (n += 360)), n;
337
+ }, this.updateAlphaOffset = () => {
452
338
  t.initialOffset = !1;
453
- }, this.dispose = function() {
339
+ }, this.dispose = () => {
454
340
  t.disconnect();
455
- }, this.getAlpha = function() {
456
- const { deviceOrientation: n } = t;
457
- return n && n.alpha ? g.degToRad(n.alpha) + t.alphaOffset : 0;
458
- }, this.getBeta = function() {
459
- const { deviceOrientation: n } = t;
460
- return n && n.beta ? g.degToRad(n.beta) : 0;
461
- }, this.getGamma = function() {
462
- const { deviceOrientation: n } = t;
463
- return n && n.gamma ? g.degToRad(n.gamma) : 0;
464
- }, this.createObtainPermissionGestureDialog = function() {
465
- const n = document.createElement("div");
466
- n.classList.add(b);
341
+ }, this.getAlpha = () => {
342
+ const { deviceOrientation: s } = t;
343
+ return s && s.alpha ? h.degToRad(s.alpha) + t.alphaOffset : 0;
344
+ }, this.getBeta = () => {
345
+ const { deviceOrientation: s } = t;
346
+ return s && s.beta ? h.degToRad(s.beta) : 0;
347
+ }, this.getGamma = () => {
348
+ const { deviceOrientation: s } = t;
349
+ return s && s.gamma ? h.degToRad(s.gamma) : 0;
350
+ }, this.createObtainPermissionGestureDialog = () => {
467
351
  const s = document.createElement("div");
468
- s.classList.add(N);
352
+ s.classList.add(b);
353
+ const n = document.createElement("div");
354
+ n.classList.add(D);
469
355
  const a = document.createElement("div");
470
- a.classList.add(S);
356
+ a.classList.add(_);
471
357
  const r = document.createElement("div");
472
- r.classList.add(L);
358
+ r.classList.add(P);
473
359
  const o = document.createElement("button");
474
- if (o.classList.add(D), document.body.appendChild(n), this.enableInlineStyling === !0) {
475
- const d = {
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)
360
+ o.classList.add(M), document.body.appendChild(s), this.enableInlineStyling === !0 && (s.style.fontFamily = "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'", s.style.display = "flex", s.style.position = "fixed", s.style.zIndex = "100000", s.style.justifyContent = "center", s.style.alignItems = "center", s.style.backgroundColor = "rgba(0,0,0,0.2)", s.style.inset = "0", s.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"), s.appendChild(n), n.appendChild(a), n.appendChild(r), a.appendChild(
361
+ document.createTextNode(O)
531
362
  );
532
- const f = () => {
533
- this.requestOrientationPermissions(), n.style.display = "none";
363
+ const d = () => {
364
+ this.requestOrientationPermissions(), s.style.display = "none";
534
365
  };
535
- o.addEventListener("click", f), o.appendChild(document.createTextNode("OK")), r.appendChild(o), document.body.appendChild(n);
536
- }, this.obtainPermissionGesture = function() {
537
- this.preferConfirmDialog === !0 ? window.confirm(T) && this.requestOrientationPermissions() : this.createObtainPermissionGestureDialog();
366
+ o.addEventListener("click", d), o.appendChild(document.createTextNode("OK")), r.appendChild(o), document.body.appendChild(s);
367
+ }, this.obtainPermissionGesture = () => {
368
+ this.preferConfirmDialog === !0 ? window.confirm(O) && this.requestOrientationPermissions() : this.createObtainPermissionGestureDialog();
538
369
  };
539
370
  }
540
371
  on(e, i) {
541
372
  this.eventEmitter.on(e, i);
542
373
  }
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 });
557
- }
558
374
  }
559
- class j {
375
+ class F {
560
376
  /**
561
377
  * Create a ClickHandler.
562
378
  * @param {THREE.WebGLRenderer} - The Three.js renderer on which the click
563
379
  * events will be handled.
564
380
  */
565
381
  constructor(e) {
566
- this.raycaster = new m.Raycaster(), this.normalisedMousePosition = new m.Vector2(null, null), e.domElement.addEventListener("click", (i) => {
567
- this.normalisedMousePosition.set(
382
+ this.raycaster = new u.Raycaster(), this.normalisedMousePosition = null, e.domElement.addEventListener("click", (i) => {
383
+ this.normalisedMousePosition = new u.Vector2(
568
384
  i.clientX / e.domElement.clientWidth * 2 - 1,
569
385
  -(i.clientY / e.domElement.clientHeight * 2) + 1
570
386
  );
@@ -579,21 +395,60 @@ class j {
579
395
  * @return {Array} - array of all intersected objects.
580
396
  */
581
397
  raycast(e, i) {
582
- if (this.normalisedMousePosition.x !== null && this.normalisedMousePosition.y !== null) {
398
+ if (this.normalisedMousePosition !== null) {
583
399
  this.raycaster.setFromCamera(this.normalisedMousePosition, e);
584
400
  const t = this.raycaster.intersectObjects(i.children, !1);
585
- return this.normalisedMousePosition.set(null, null), t;
401
+ return this.normalisedMousePosition = null, t;
586
402
  }
587
403
  return [];
588
404
  }
589
405
  }
590
- const U = "0.1.6";
406
+ class j extends E {
407
+ #e;
408
+ /**
409
+ * Create a Webcam.
410
+ * @param constraints {Object} - options to use for initialising the camera.
411
+ * This is the same constraints object as used by standard MediaDevices API.
412
+ * @param {string} videoElementSelector - selector to obtain the HTML video
413
+ * element to render the webcam feed. If a falsy value (e.g. null or
414
+ * undefined), a video element will be created.
415
+ */
416
+ constructor(e = { video: { facingMode: "environment" } }, i) {
417
+ super(), this.sceneWebcam = new u.Scene(), i ? this.#e = document.querySelector(i) : (this.#e = document.createElement("video"), this.#e.setAttribute("autoplay", "true"), this.#e.setAttribute("playsinline", "true"), this.#e.style.display = "none", document.body.appendChild(this.#e)), this.texture = this.#e ? new u.VideoTexture(this.#e) : null, navigator.mediaDevices && navigator.mediaDevices.getUserMedia ? navigator.mediaDevices.getUserMedia(e).then((t) => {
418
+ this.#e?.addEventListener("loadedmetadata", () => {
419
+ this.#e?.setAttribute(
420
+ "width",
421
+ this.#e?.videoWidth.toString() ?? "0"
422
+ ), this.#e?.setAttribute(
423
+ "height",
424
+ this.#e?.videoHeight.toString() ?? "0"
425
+ ), this.#e?.play(), this.emit("webcamstarted", { texture: this.texture });
426
+ }), this.#e && (this.#e.srcObject = t);
427
+ }).catch((t) => {
428
+ this.emit("webcamerror", {
429
+ code: t.name,
430
+ message: t.message
431
+ });
432
+ }) : this.emit("webcamerror", {
433
+ code: "LOCAR_NO_MEDIA_DEVICES_API",
434
+ message: "Media devices API not supported"
435
+ });
436
+ }
437
+ /**
438
+ * Free up the memory associated with the webcam.
439
+ * Should be called when your application closes.
440
+ */
441
+ dispose() {
442
+ this.texture?.dispose();
443
+ }
444
+ }
445
+ const k = "0.1.8";
591
446
  export {
592
- j as ClickHandler,
593
- V as DeviceOrientationControls,
594
- A as EventEmitter,
595
- q as LocationBased,
447
+ F as ClickHandler,
448
+ q as DeviceOrientationControls,
449
+ E as EventEmitter,
450
+ H as LocationBased,
596
451
  R as SphMercProjection,
597
- k as Webcam,
598
- U as version
452
+ j as Webcam,
453
+ k as version
599
454
  };