locar 0.0.8 → 0.0.10

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/README.md CHANGED
@@ -4,7 +4,7 @@ Location-based AR from AR.js.
4
4
 
5
5
  ## What is this?
6
6
 
7
- LocAR.js is an AR.js project to develop a library focused specifically on location-based augmented reality in the browser. Currently it consists of the location-based three.js code from [the main AR.js repository](https://github.com/AR-js-org/AR.js), with some minor changes to make it compatible with latest versions (0.169.0 at time of writing) of three.js.
7
+ LocAR.js is an AR.js project to develop a library focused specifically on location-based augmented reality in the browser. Currently it consists of the location-based three.js code from [the main AR.js repository](https://github.com/AR-js-org/AR.js), with some minor changes to make it compatible with latest versions (0.175.0 at time of writing) of three.js.
8
8
 
9
9
  ## Why?
10
10
 
@@ -20,8 +20,6 @@ For a while there have been some bugs and issues with location-based AR.js which
20
20
 
21
21
  Some of these issues, such as incorrect North on some devices, may well be to do with incorrect or mis-calibrated sensors but the hope is that the standalone library will help to verify this and, if certain devices have North wrong by a consistent bearing, to develop a calibration tool.
22
22
 
23
- For this reason, the focus at present will be on developing a **pure three.js version only**. When we believe that the key bugs and issues have been resolved, the plan is to then provide an A-Frame wrapper.
24
-
25
23
  ## Cross-platform Compatibility
26
24
 
27
25
  Chrome on Android is recommended. It may also work on Chrome in iOS; please file an issue if not. It will not work on Safari on iOS, due to permissions issues - **though pull requests are welcome to fix this**. Firefox unfortunately does not appear to fully implement the Device Orientation API so is unlikely to work
@@ -42,8 +40,8 @@ import * as LocAR from 'locar';
42
40
  as long as you include `locar` as a dependency, e.g. in your `package.json`:
43
41
  ```
44
42
  "dependencies": {
45
- "locar" : "^0.0.7",
46
- "three" : "^0.169.0"
43
+ "locar" : "^0.0.10",
44
+ "three" : "^0.175.0"
47
45
  }
48
46
  ```
49
47
 
package/dist/locar.es.js CHANGED
@@ -1,25 +1,25 @@
1
- var j = (r) => {
2
- throw TypeError(r);
1
+ var W = (i) => {
2
+ throw TypeError(i);
3
3
  };
4
- var F = (r, t, e) => t.has(r) || j("Cannot " + e);
5
- var n = (r, t, e) => (F(r, t, "read from private field"), e ? e.call(r) : t.get(r)), m = (r, t, e) => t.has(r) ? j("Cannot add the same private member more than once") : t instanceof WeakSet ? t.add(r) : t.set(r, e), d = (r, t, e, i) => (F(r, t, "write to private field"), i ? i.call(r, e) : t.set(r, e), e), v = (r, t, e) => (F(r, t, "access private method"), e);
6
- var q = (r, t, e, i) => ({
7
- set _(o) {
8
- d(r, t, o, e);
4
+ var S = (i, t, e) => t.has(i) || W("Cannot " + e);
5
+ var s = (i, t, e) => (S(i, t, "read from private field"), e ? e.call(i) : t.get(i)), m = (i, t, e) => t.has(i) ? W("Cannot add the same private member more than once") : t instanceof WeakSet ? t.add(i) : t.set(i, e), u = (i, t, e, n) => (S(i, t, "write to private field"), n ? n.call(i, e) : t.set(i, e), e), f = (i, t, e) => (S(i, t, "access private method"), e);
6
+ var k = (i, t, e, n) => ({
7
+ set _(r) {
8
+ u(i, t, r, e);
9
9
  },
10
10
  get _() {
11
- return n(r, t, i);
11
+ return s(i, t, n);
12
12
  }
13
13
  });
14
- import * as f from "three";
15
- import { Vector3 as Z, Euler as N, Quaternion as _, EventDispatcher as B, MathUtils as D } from "three";
16
- var P, U, G, X, Q;
17
- class K {
14
+ import * as L from "three";
15
+ import { Vector3 as Y, Euler as U, Quaternion as _, EventDispatcher as Z, MathUtils as C } from "three";
16
+ var E, N, z, V, X;
17
+ class $ {
18
18
  /**
19
19
  * Create a SphMercProjection.
20
20
  */
21
21
  constructor() {
22
- m(this, P);
22
+ m(this, E);
23
23
  this.EARTH = 4007501668e-2, this.HALF_EARTH = 2003750834e-2;
24
24
  }
25
25
  /**
@@ -29,7 +29,7 @@ class K {
29
29
  * @return {Array} Two-member array containing easting and northing.
30
30
  */
31
31
  project(t, e) {
32
- return [v(this, P, U).call(this, t), v(this, P, G).call(this, e)];
32
+ return [f(this, E, N).call(this, t), f(this, E, z).call(this, e)];
33
33
  }
34
34
  /**
35
35
  * Unproject a Spherical Mercator easting and northing.
@@ -37,7 +37,7 @@ class K {
37
37
  * @return {Array} Two-member array containing longitude and latitude
38
38
  */
39
39
  unproject(t) {
40
- return [v(this, P, X).call(this, t[0]), v(this, P, Q).call(this, t[1])];
40
+ return [f(this, E, V).call(this, t[0]), f(this, E, X).call(this, t[1])];
41
41
  }
42
42
  /**
43
43
  * Return the projection's ID.
@@ -47,19 +47,19 @@ class K {
47
47
  return "epsg:3857";
48
48
  }
49
49
  }
50
- P = new WeakSet(), U = function(t) {
50
+ E = new WeakSet(), N = function(t) {
51
51
  return t / 180 * this.HALF_EARTH;
52
- }, G = function(t) {
52
+ }, z = function(t) {
53
53
  var e = Math.log(Math.tan((90 + t) * Math.PI / 360)) / (Math.PI / 180);
54
54
  return e * this.HALF_EARTH / 180;
55
- }, X = function(t) {
55
+ }, V = function(t) {
56
56
  return t / this.HALF_EARTH * 180;
57
- }, Q = function(t) {
57
+ }, X = function(t) {
58
58
  var e = t / this.HALF_EARTH * 180;
59
59
  return e = 180 / Math.PI * (2 * Math.atan(Math.exp(e * Math.PI / 180)) - Math.PI / 2), e;
60
60
  };
61
- var R, A, T, x, L, C, E, I, b, O, p, S, V, W, Y;
62
- class st {
61
+ var D, A, b, H, R, P, M, T, O, w, p, j, Q, F, B;
62
+ class K {
63
63
  /**
64
64
  * @param {THREE.Scene} scene - The Three.js scene to use.
65
65
  * @param {THREE.Camera} camera - The Three.js camera to use. Should usually
@@ -68,19 +68,19 @@ class st {
68
68
  * setGpsOptions() below.
69
69
  * @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.
70
70
  */
71
- constructor(t, e, i = {}, o = null) {
71
+ constructor(t, e, n = {}, r = null) {
72
72
  m(this, p);
73
- m(this, R);
73
+ m(this, D);
74
74
  m(this, A);
75
- m(this, T);
76
- m(this, x);
77
- m(this, L);
78
- m(this, C);
79
- m(this, E);
80
- m(this, I);
81
75
  m(this, b);
76
+ m(this, H);
77
+ m(this, R);
78
+ m(this, P);
79
+ m(this, M);
80
+ m(this, T);
82
81
  m(this, O);
83
- this.scene = t, this.camera = e, d(this, R, new K()), d(this, A, {}), d(this, T, null), d(this, x, 0), d(this, L, 100), d(this, C, null), this.setGpsOptions(i), d(this, E, null), d(this, I, 0), d(this, b, 0), d(this, O, o);
82
+ m(this, w);
83
+ this.scene = t, this.camera = e, u(this, D, new $()), u(this, A, {}), u(this, b, null), u(this, H, 0), u(this, R, 100), u(this, P, null), this.setGpsOptions(n), u(this, M, null), u(this, T, 0), u(this, O, 0), u(this, w, r);
84
84
  }
85
85
  /**
86
86
  * Set the projection to use.
@@ -89,7 +89,7 @@ class st {
89
89
  * containing easting and northing.
90
90
  */
91
91
  setProjection(t) {
92
- d(this, R, t);
92
+ u(this, D, t);
93
93
  }
94
94
  /**
95
95
  * Set the GPS options.
@@ -99,7 +99,7 @@ class st {
99
99
  * minimum accuracy, in metres, for a GPS reading to be counted.
100
100
  */
101
101
  setGpsOptions(t = {}) {
102
- t.gpsMinDistance !== void 0 && d(this, x, t.gpsMinDistance), t.gpsMinAccuracy !== void 0 && d(this, L, t.gpsMinAccuracy);
102
+ t.gpsMinDistance !== void 0 && u(this, H, t.gpsMinDistance), t.gpsMinAccuracy !== void 0 && u(this, R, t.gpsMinAccuracy);
103
103
  }
104
104
  /**
105
105
  * Start the GPS on a real device
@@ -107,19 +107,19 @@ class st {
107
107
  * GPS errors can be handled by handling the gpserror event.
108
108
  */
109
109
  async startGps() {
110
- if (n(this, O)) {
111
- const e = await (await n(this, O).sendData("/gps/start", {
112
- gpsMinDistance: n(this, x),
113
- gpsMinAccuracy: n(this, L)
110
+ if (s(this, w)) {
111
+ const e = await (await s(this, w).sendData("/gps/start", {
112
+ gpsMinDistance: s(this, H),
113
+ gpsMinAccuracy: s(this, R)
114
114
  })).json();
115
- d(this, b, e.session);
115
+ u(this, O, e.session);
116
116
  }
117
- return n(this, C) === null ? (d(this, C, navigator.geolocation.watchPosition(
117
+ return s(this, P) === null ? (u(this, P, navigator.geolocation.watchPosition(
118
118
  (t) => {
119
- v(this, p, W).call(this, t);
119
+ f(this, p, F).call(this, t);
120
120
  },
121
121
  (t) => {
122
- n(this, A).gpserror ? n(this, A).gpserror(t.code) : alert(`GPS error: code ${t.code}`);
122
+ s(this, A).gpserror ? s(this, A).gpserror(t.code) : alert(`GPS error: code ${t.code}`);
123
123
  },
124
124
  {
125
125
  enableHighAccuracy: !0
@@ -132,7 +132,7 @@ class st {
132
132
  * stopped (i.e. it was never started).
133
133
  */
134
134
  stopGps() {
135
- return n(this, C) !== null ? (navigator.geolocation.clearWatch(n(this, C)), d(this, C, null), !0) : !1;
135
+ return s(this, P) !== null ? (navigator.geolocation.clearWatch(s(this, P)), u(this, P, null), !0) : !1;
136
136
  }
137
137
  /**
138
138
  * Send a fake GPS signal. Useful for testing on a desktop or laptop.
@@ -143,12 +143,12 @@ class st {
143
143
  * @param {number} acc - The accuracy of the GPS reading in metres. May be
144
144
  * ignored if lower than the specified minimum accuracy.
145
145
  */
146
- fakeGps(t, e, i = null, o = 0) {
147
- i !== null && this.setElevation(i), v(this, p, W).call(this, {
146
+ fakeGps(t, e, n = null, r = 0) {
147
+ n !== null && this.setElevation(n), f(this, p, F).call(this, {
148
148
  coords: {
149
149
  longitude: t,
150
150
  latitude: e,
151
- accuracy: o
151
+ accuracy: r
152
152
  }
153
153
  });
154
154
  }
@@ -163,12 +163,12 @@ class st {
163
163
  * @return {Array} a two member array containing the WebGL x and z coordinates
164
164
  */
165
165
  lonLatToWorldCoords(t, e) {
166
- const i = n(this, R).project(t, e);
167
- if (n(this, E))
168
- i[0] -= n(this, E)[0], i[1] -= n(this, E)[1];
166
+ const n = s(this, D).project(t, e);
167
+ if (s(this, M))
168
+ n[0] -= s(this, M)[0], n[1] -= s(this, M)[1];
169
169
  else
170
170
  throw "No initial position determined";
171
- return [i[0], -i[1]];
171
+ return [n[0], -n[1]];
172
172
  }
173
173
  /**
174
174
  * Add a new AR object at a given latitude, longitude and elevation.
@@ -180,14 +180,14 @@ class st {
180
180
  * @param {Object} properties - properties describing the object (for example,
181
181
  * the contents of the GeoJSON properties field).
182
182
  */
183
- add(t, e, i, o, u = {}) {
183
+ add(t, e, n, r, d = {}) {
184
184
  var g;
185
- t.properties = u, v(this, p, S).call(this, t, e, i, o), this.scene.add(t), (g = n(this, O)) == null || g.sendData("/object/new", {
185
+ t.properties = d, f(this, p, j).call(this, t, e, n, r), this.scene.add(t), (g = s(this, w)) == null || g.sendData("/object/new", {
186
186
  position: t.position,
187
187
  x: t.position.x,
188
188
  z: t.position.z,
189
- session: n(this, b),
190
- properties: u
189
+ session: s(this, O),
190
+ properties: d
191
191
  });
192
192
  }
193
193
  /**
@@ -211,86 +211,83 @@ class st {
211
211
  * @listens LocationBased#gpserror
212
212
  */
213
213
  on(t, e) {
214
- n(this, A)[t] = e;
214
+ s(this, A)[t] = e;
215
215
  }
216
216
  }
217
- R = new WeakMap(), A = new WeakMap(), T = new WeakMap(), x = new WeakMap(), L = new WeakMap(), C = new WeakMap(), E = new WeakMap(), I = new WeakMap(), b = new WeakMap(), O = new WeakMap(), p = new WeakSet(), S = function(t, e, i, o) {
218
- const u = this.lonLatToWorldCoords(e, i);
219
- o !== void 0 && (t.position.y = o), [t.position.x, t.position.z] = u;
220
- }, V = function(t, e) {
221
- d(this, E, n(this, R).project(t, e));
222
- }, W = function(t) {
223
- var i, o, u;
217
+ D = new WeakMap(), A = new WeakMap(), b = new WeakMap(), H = new WeakMap(), R = new WeakMap(), P = new WeakMap(), M = new WeakMap(), T = new WeakMap(), O = new WeakMap(), w = new WeakMap(), p = new WeakSet(), j = function(t, e, n, r) {
218
+ const d = this.lonLatToWorldCoords(e, n);
219
+ r !== void 0 && (t.position.y = r), [t.position.x, t.position.z] = d;
220
+ }, Q = function(t, e) {
221
+ u(this, M, s(this, D).project(t, e));
222
+ }, F = function(t) {
223
+ var n, r, d;
224
224
  let e = Number.MAX_VALUE;
225
- q(this, I)._++, (i = n(this, O)) == null || i.sendData("/gps/new", {
226
- gpsCount: n(this, I),
225
+ k(this, T)._++, (n = s(this, w)) == null || n.sendData("/gps/new", {
226
+ gpsCount: s(this, T),
227
227
  lat: t.coords.latitude,
228
228
  lon: t.coords.longitude,
229
229
  acc: t.coords.accuracy,
230
- session: n(this, b)
231
- }), t.coords.accuracy <= n(this, L) && (n(this, T) === null ? d(this, T, {
230
+ session: s(this, O)
231
+ }), t.coords.accuracy <= s(this, R) && (s(this, b) === null ? u(this, b, {
232
232
  latitude: t.coords.latitude,
233
233
  longitude: t.coords.longitude
234
- }) : e = v(this, p, Y).call(this, n(this, T), t.coords), e >= n(this, x) && (n(this, T).longitude = t.coords.longitude, n(this, T).latitude = t.coords.latitude, n(this, E) || (v(this, p, V).call(this, t.coords.longitude, t.coords.latitude), (o = n(this, O)) == null || o.sendData("/worldorigin/new", {
235
- gpsCount: n(this, I),
234
+ }) : e = f(this, p, B).call(this, s(this, b), t.coords), e >= s(this, H) && (s(this, b).longitude = t.coords.longitude, s(this, b).latitude = t.coords.latitude, s(this, M) || (f(this, p, Q).call(this, t.coords.longitude, t.coords.latitude), (r = s(this, w)) == null || r.sendData("/worldorigin/new", {
235
+ gpsCount: s(this, T),
236
236
  lat: t.coords.latitude,
237
237
  lon: t.coords.longitude,
238
- session: n(this, b),
239
- initialPosition: n(this, E)
240
- })), v(this, p, S).call(this, this.camera, t.coords.longitude, t.coords.latitude), (u = n(this, O)) == null || u.sendData("/gps/accepted", {
241
- gpsCount: n(this, I),
238
+ session: s(this, O),
239
+ initialPosition: s(this, M)
240
+ })), f(this, p, j).call(this, this.camera, t.coords.longitude, t.coords.latitude), (d = s(this, w)) == null || d.sendData("/gps/accepted", {
241
+ gpsCount: s(this, T),
242
242
  cameraX: this.camera.position.x,
243
243
  cameraZ: this.camera.position.z,
244
- session: n(this, b),
244
+ session: s(this, O),
245
245
  distMoved: e
246
- }), n(this, A).gpsupdate && n(this, A).gpsupdate(t, e)));
246
+ }), s(this, A).gpsupdate && s(this, A).gpsupdate(t, e)));
247
247
  }, /**
248
248
  * Calculate haversine distance between two lat/lon pairs.
249
249
  *
250
250
  * Taken from original A-Frame AR.js location-based components
251
251
  */
252
- Y = function(t, e) {
253
- const i = f.MathUtils.degToRad(e.longitude - t.longitude), o = f.MathUtils.degToRad(e.latitude - t.latitude), u = Math.sin(o / 2) * Math.sin(o / 2) + Math.cos(f.MathUtils.degToRad(t.latitude)) * Math.cos(f.MathUtils.degToRad(e.latitude)) * (Math.sin(i / 2) * Math.sin(i / 2));
254
- return 2 * Math.atan2(Math.sqrt(u), Math.sqrt(1 - u)) * 6371e3;
252
+ B = function(t, e) {
253
+ const n = L.MathUtils.degToRad(e.longitude - t.longitude), r = L.MathUtils.degToRad(e.latitude - t.latitude), d = Math.sin(r / 2) * Math.sin(r / 2) + Math.cos(L.MathUtils.degToRad(t.latitude)) * Math.cos(L.MathUtils.degToRad(e.latitude)) * (Math.sin(n / 2) * Math.sin(n / 2));
254
+ return 2 * Math.atan2(Math.sqrt(d), Math.sqrt(1 - d)) * 6371e3;
255
255
  };
256
- class ot {
256
+ class J {
257
257
  /**
258
- * Create a WebcamRenderer.
259
- * @param {THREE.WebGLRenderer} renderer - the Three.js renderer.
258
+ * Create a Webcam.
259
+ * @param options {Object} - options to use for initialising the camera.
260
+ * Currently idealWidth and idealHeight properties are understood as well as
261
+ * onVideoStarted(), a *required* callback which runs when the camera has
262
+ * been initialised.
263
+ * This takes a THREE.VideoTexture as an argument which can be used to set
264
+ * the background of your three.js scene within a callback.
260
265
  * @param {string} videoElementSelector - selector to obtain the HTML video
261
266
  * element to render the webcam feed. If a falsy value (e.g. null or
262
267
  * undefined), a video element will be created.
263
- * @options {Object} - options to use for initialising the camera. Currently
264
- * width and height properties are understood.
265
268
  */
266
- constructor(t, e, i) {
267
- this.renderer = t, this.renderer.autoClear = !1, this.sceneWebcam = new f.Scene();
268
- let o;
269
- e ? o = document.querySelector(e) : (o = document.createElement("video"), o.setAttribute("autoplay", !0), o.setAttribute("playsinline", !0), o.style.display = "none", document.body.appendChild(o)), this.geom = new f.PlaneGeometry(), this.texture = new f.VideoTexture(o), this.material = new f.MeshBasicMaterial({ map: this.texture });
270
- const u = new f.Mesh(this.geom, this.material);
271
- if (this.sceneWebcam.add(u), this.cameraWebcam = new f.OrthographicCamera(
272
- -0.5,
273
- 0.5,
274
- 0.5,
275
- -0.5,
276
- 0,
277
- 10
278
- ), navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
279
- const g = {
269
+ constructor(t = {}, e) {
270
+ this.sceneWebcam = new L.Scene();
271
+ let n;
272
+ if (e ? n = document.querySelector(e) : (n = document.createElement("video"), n.setAttribute("autoplay", !0), n.setAttribute("playsinline", !0), n.style.display = "none", document.body.appendChild(n)), this.texture = new L.VideoTexture(n), navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
273
+ const r = {
280
274
  video: {
281
- width: (i == null ? void 0 : i.width) || 1280,
282
- height: (i == null ? void 0 : i.height) || 720,
275
+ width: { ideal: t.idealWidth || 1280 },
276
+ height: { ideal: t.idealHeight || 720 },
283
277
  facingMode: "environment"
284
278
  }
285
279
  };
286
- navigator.mediaDevices.getUserMedia(g).then((w) => {
287
- console.log("using the webcam successfully..."), o.srcObject = w, o.play();
288
- }).catch((w) => {
280
+ navigator.mediaDevices.getUserMedia(r).then((d) => {
281
+ n.addEventListener("loadedmetadata", () => {
282
+ var g;
283
+ n.setAttribute("width", n.videoWidth), n.setAttribute("height", n.videoHeight), n.play(), (g = t.onVideoStarted) == null || g.call(this, this.texture);
284
+ }), n.srcObject = d;
285
+ }).catch((d) => {
289
286
  setTimeout(() => {
290
287
  alert(
291
288
  `Webcam Error
292
- Name: ` + w.name + `
293
- Message: ` + w.message
289
+ Name: ` + d.name + `
290
+ Message: ` + d.message
294
291
  );
295
292
  }, 1e3);
296
293
  });
@@ -299,23 +296,16 @@ Message: ` + w.message
299
296
  alert("sorry - media devices API not supported");
300
297
  }, 1e3);
301
298
  }
302
- /**
303
- * Update the webcam.
304
- * Should be called from your Three.js rendering (animation) function.
305
- */
306
- update() {
307
- this.renderer.clear(), this.renderer.render(this.sceneWebcam, this.cameraWebcam), this.renderer.clearDepth();
308
- }
309
299
  /**
310
300
  * Free up the memory associated with the webcam.
311
301
  * Should be called when your application closes.
312
302
  */
313
303
  dispose() {
314
- this.material.dispose(), this.texture.dispose(), this.geom.dispose();
304
+ this.texture.dispose();
315
305
  }
316
306
  }
317
- const k = navigator.userAgent.match(/iPhone|iPad|iPod/i) || /Macintosh/i.test(navigator.userAgent) && navigator.maxTouchPoints != null && navigator.maxTouchPoints > 1, $ = new Z(0, 0, 1), z = new N(), J = new _(), tt = new _(-Math.sqrt(0.5), 0, 0, Math.sqrt(0.5)), et = { type: "change" };
318
- class at extends B {
307
+ const q = navigator.userAgent.match(/iPhone|iPad|iPod/i) || /Macintosh/i.test(navigator.userAgent) && navigator.maxTouchPoints != null && navigator.maxTouchPoints > 1, tt = new Y(0, 0, 1), G = new U(), et = new _(), it = new _(-Math.sqrt(0.5), 0, 0, Math.sqrt(0.5)), nt = { type: "change" };
308
+ class st extends Z {
319
309
  /**
320
310
  * Create an instance of DeviceOrientationControls.
321
311
  * @param {Object} object - the object to attach the controls to
@@ -325,19 +315,19 @@ class at extends B {
325
315
  super(), window.isSecureContext === !1 && console.error(
326
316
  "THREE.DeviceOrientationControls: DeviceOrientationEvent is only available in secure contexts (https)"
327
317
  );
328
- const e = this, i = 1e-6, o = new _();
318
+ const e = this, n = 1e-6, r = new _();
329
319
  this.object = t, this.object.rotation.reorder("YXZ"), this.enabled = !0, this.deviceOrientation = null, this.screenOrientation = 0, this.alphaOffset = 0, this.initialOffset = null, this.TWO_PI = 2 * Math.PI, this.HALF_PI = 0.5 * Math.PI, this.orientationChangeEventName = "ondeviceorientationabsolute" in window ? "deviceorientationabsolute" : "deviceorientation", this.smoothingFactor = 1;
330
- const u = function({
331
- alpha: s,
320
+ const d = function({
321
+ alpha: o,
332
322
  beta: c,
333
- gamma: h,
323
+ gamma: l,
334
324
  webkitCompassHeading: a
335
325
  }) {
336
- if (k) {
337
- const l = 360 - a;
338
- e.alphaOffset = D.degToRad(l - s), e.deviceOrientation = { alpha: s, beta: c, gamma: h, webkitCompassHeading: a };
326
+ if (q) {
327
+ const h = 360 - a;
328
+ e.alphaOffset = C.degToRad(h - o), e.deviceOrientation = { alpha: o, beta: c, gamma: l, webkitCompassHeading: a };
339
329
  } else
340
- s < 0 && (s += 360), e.deviceOrientation = { alpha: s, beta: c, gamma: h };
330
+ o < 0 && (o += 360), e.deviceOrientation = { alpha: o, beta: c, gamma: l };
341
331
  window.dispatchEvent(
342
332
  new CustomEvent("camera-rotation-change", {
343
333
  detail: { cameraRotation: t.rotation }
@@ -345,29 +335,29 @@ class at extends B {
345
335
  );
346
336
  }, g = function() {
347
337
  e.screenOrientation = window.orientation || 0;
348
- }, w = function(s, c, h, a, l) {
349
- z.set(h, c, -a, "YXZ"), s.setFromEuler(z), s.multiply(tt), s.multiply(J.setFromAxisAngle($, -l));
338
+ }, x = function(o, c, l, a, h) {
339
+ G.set(l, c, -a, "YXZ"), o.setFromEuler(G), o.multiply(it), o.multiply(et.setFromAxisAngle(tt, -h));
350
340
  };
351
341
  this.connect = function() {
352
- g(), window.DeviceOrientationEvent !== void 0 && typeof window.DeviceOrientationEvent.requestPermission == "function" ? window.DeviceOrientationEvent.requestPermission().then((s) => {
353
- s === "granted" && (window.addEventListener(
342
+ g(), window.DeviceOrientationEvent !== void 0 && typeof window.DeviceOrientationEvent.requestPermission == "function" ? window.DeviceOrientationEvent.requestPermission().then((o) => {
343
+ o === "granted" && (window.addEventListener(
354
344
  "orientationchange",
355
345
  g
356
346
  ), window.addEventListener(
357
347
  e.orientationChangeEventName,
358
- u
348
+ d
359
349
  ));
360
- }).catch(function(s) {
350
+ }).catch(function(o) {
361
351
  console.error(
362
352
  "THREE.DeviceOrientationControls: Unable to use DeviceOrientation API:",
363
- s
353
+ o
364
354
  );
365
355
  }) : (window.addEventListener(
366
356
  "orientationchange",
367
357
  g
368
358
  ), window.addEventListener(
369
359
  e.orientationChangeEventName,
370
- u
360
+ d
371
361
  )), e.enabled = !0;
372
362
  }, this.disconnect = function() {
373
363
  window.removeEventListener(
@@ -375,86 +365,86 @@ class at extends B {
375
365
  g
376
366
  ), window.removeEventListener(
377
367
  e.orientationChangeEventName,
378
- u
368
+ d
379
369
  ), e.enabled = !1, e.initialOffset = !1, e.deviceOrientation = null;
380
- }, this.update = function({ theta: s = 0 } = { theta: 0 }) {
370
+ }, this.update = function({ theta: o = 0 } = { theta: 0 }) {
381
371
  if (e.enabled === !1) return;
382
372
  const c = e.deviceOrientation;
383
373
  if (c) {
384
- let h = c.alpha ? D.degToRad(c.alpha) + e.alphaOffset : 0, a = c.beta ? D.degToRad(c.beta) : 0, l = c.gamma ? D.degToRad(c.gamma) : 0;
385
- const H = e.screenOrientation ? D.degToRad(e.screenOrientation) : 0;
386
- if (k) {
387
- const y = new _();
388
- w(y, h, a, l, H);
389
- const M = new N().setFromQuaternion(
390
- y,
374
+ let l = c.alpha ? C.degToRad(c.alpha) + e.alphaOffset : 0, a = c.beta ? C.degToRad(c.beta) : 0, h = c.gamma ? C.degToRad(c.gamma) : 0;
375
+ const I = e.screenOrientation ? C.degToRad(e.screenOrientation) : 0;
376
+ if (q) {
377
+ const v = new _();
378
+ x(v, l, a, h, I);
379
+ const y = new U().setFromQuaternion(
380
+ v,
391
381
  "YXZ"
392
382
  );
393
- console.log(M.x, M.y, M.z), M.y = D.degToRad(
383
+ console.log(y.x, y.y, y.z), y.y = C.degToRad(
394
384
  360 - c.webkitCompassHeading
395
- ), y.setFromEuler(M), e.object.quaternion.copy(y);
385
+ ), v.setFromEuler(y), e.object.quaternion.copy(v);
396
386
  } else {
397
387
  if (this.smoothingFactor < 1) {
398
388
  if (this.lastOrientation) {
399
- const y = this.smoothingFactor;
400
- h = this._getSmoothedAngle(
401
- h,
389
+ const v = this.smoothingFactor;
390
+ l = this._getSmoothedAngle(
391
+ l,
402
392
  this.lastOrientation.alpha,
403
- y
393
+ v
404
394
  ), a = this._getSmoothedAngle(
405
395
  a + Math.PI,
406
396
  this.lastOrientation.beta,
407
- y
408
- ), l = this._getSmoothedAngle(
409
- l + this.HALF_PI,
397
+ v
398
+ ), h = this._getSmoothedAngle(
399
+ h + this.HALF_PI,
410
400
  this.lastOrientation.gamma,
411
- y,
401
+ v,
412
402
  Math.PI
413
403
  );
414
404
  } else
415
- a += Math.PI, l += this.HALF_PI;
405
+ a += Math.PI, h += this.HALF_PI;
416
406
  this.lastOrientation = {
417
- alpha: h,
407
+ alpha: l,
418
408
  beta: a,
419
- gamma: l
409
+ gamma: h
420
410
  };
421
411
  }
422
- w(
412
+ x(
423
413
  e.object.quaternion,
424
- h + s,
414
+ l + o,
425
415
  this.smoothingFactor < 1 ? a - Math.PI : a,
426
- this.smoothingFactor < 1 ? l - this.HALF_PI : l,
427
- H
416
+ this.smoothingFactor < 1 ? h - this.HALF_PI : h,
417
+ I
428
418
  );
429
419
  }
430
- 8 * (1 - o.dot(e.object.quaternion)) > i && (o.copy(e.object.quaternion), e.dispatchEvent(et));
420
+ 8 * (1 - r.dot(e.object.quaternion)) > n && (r.copy(e.object.quaternion), e.dispatchEvent(nt));
431
421
  }
432
- }, this._orderAngle = function(s, c, h = this.TWO_PI) {
433
- return c > s && Math.abs(c - s) < h / 2 || s > c && Math.abs(c - s) > h / 2 ? { left: s, right: c } : { left: c, right: s };
434
- }, this._getSmoothedAngle = function(s, c, h, a = this.TWO_PI) {
435
- const l = this._orderAngle(s, c, a), H = l.left, y = l.right;
436
- l.left = 0, l.right -= H, l.right < 0 && (l.right += a);
437
- let M = y == c ? (1 - h) * l.right + h * l.left : h * l.right + (1 - h) * l.left;
438
- return M += H, M >= a && (M -= a), M;
422
+ }, this._orderAngle = function(o, c, l = this.TWO_PI) {
423
+ return c > o && Math.abs(c - o) < l / 2 || o > c && Math.abs(c - o) > l / 2 ? { left: o, right: c } : { left: c, right: o };
424
+ }, this._getSmoothedAngle = function(o, c, l, a = this.TWO_PI) {
425
+ const h = this._orderAngle(o, c, a), I = h.left, v = h.right;
426
+ h.left = 0, h.right -= I, h.right < 0 && (h.right += a);
427
+ let y = v == c ? (1 - l) * h.right + l * h.left : l * h.right + (1 - l) * h.left;
428
+ return y += I, y >= a && (y -= a), y;
439
429
  }, this.updateAlphaOffset = function() {
440
430
  e.initialOffset = !1;
441
431
  }, this.dispose = function() {
442
432
  e.disconnect();
443
433
  }, this.getAlpha = function() {
444
- const { deviceOrientation: s } = e;
445
- return s && s.alpha ? D.degToRad(s.alpha) + e.alphaOffset : 0;
434
+ const { deviceOrientation: o } = e;
435
+ return o && o.alpha ? C.degToRad(o.alpha) + e.alphaOffset : 0;
446
436
  }, this.getBeta = function() {
447
- const { deviceOrientation: s } = e;
448
- return s && s.beta ? D.degToRad(s.beta) : 0;
437
+ const { deviceOrientation: o } = e;
438
+ return o && o.beta ? C.degToRad(o.beta) : 0;
449
439
  }, window.DeviceOrientationEvent !== void 0 && typeof window.DeviceOrientationEvent.requestPermission == "function" ? this.initPermissionDialog() : this.connect();
450
440
  }
451
441
  // Provide gesture before initialising device orientation controls
452
442
  // From PR #659 on the main AR.js repo
453
443
  // Thanks to @ma2yama
454
444
  initPermissionDialog() {
455
- const t = document.createElement("div"), e = document.createElement("div"), i = document.createElement("div"), o = document.createElement("div");
445
+ const t = document.createElement("div"), e = document.createElement("div"), n = document.createElement("div"), r = document.createElement("div");
456
446
  document.body.appendChild(t);
457
- const u = {
447
+ const d = {
458
448
  display: "flex",
459
449
  position: "fixed",
460
450
  top: 0,
@@ -471,32 +461,32 @@ class at extends B {
471
461
  borderRadius: "3px",
472
462
  width: "36rem",
473
463
  height: "24rem"
474
- }, w = {
464
+ }, x = {
475
465
  width: "100%",
476
466
  height: "70%",
477
467
  display: "flex",
478
468
  justifyContent: "center",
479
469
  alignItems: "center"
480
- }, s = {
470
+ }, o = {
481
471
  display: "inline-flex",
482
472
  width: "100%",
483
473
  height: "30%",
484
474
  justifyContent: "center",
485
475
  alignItems: "center"
486
476
  };
487
- for (let a in u)
488
- t.style[a] = u[a];
477
+ for (let a in d)
478
+ t.style[a] = d[a];
489
479
  for (let a in g)
490
480
  e.style[a] = g[a];
491
- for (let a in w)
492
- i.style[a] = w[a];
493
- for (let a in s)
494
- o.style[a] = s[a];
495
- t.appendChild(e), e.appendChild(i), e.appendChild(o), i.innerHTML = '<div style="font-size: 24pt; margin: 1rem;">This immersive website requires access to your device motion sensors.</div>';
481
+ for (let a in x)
482
+ n.style[a] = x[a];
483
+ for (let a in o)
484
+ r.style[a] = o[a];
485
+ t.appendChild(e), e.appendChild(n), e.appendChild(r), n.innerHTML = '<div style="font-size: 24pt; margin: 1rem;">This immersive website requires access to your device motion sensors.</div>';
496
486
  const c = () => {
497
487
  this.connect(), t.style.display = "none";
498
- }, h = document.createElement("button");
499
- h.addEventListener("click", c), h.style.width = "50%", h.style.height = "80%", h.style.fontSize = "20pt", h.appendChild(document.createTextNode("OK")), o.appendChild(h), document.body.appendChild(t);
488
+ }, l = document.createElement("button");
489
+ l.addEventListener("click", c), l.style.width = "50%", l.style.height = "80%", l.style.fontSize = "20pt", l.appendChild(document.createTextNode("OK")), r.appendChild(l), document.body.appendChild(t);
500
490
  }
501
491
  }
502
492
  class rt {
@@ -506,7 +496,7 @@ class rt {
506
496
  * events will be handled.
507
497
  */
508
498
  constructor(t) {
509
- this.raycaster = new f.Raycaster(), this.normalisedMousePosition = new f.Vector2(null, null), t.domElement.addEventListener("click", (e) => {
499
+ this.raycaster = new L.Raycaster(), this.normalisedMousePosition = new L.Vector2(null, null), t.domElement.addEventListener("click", (e) => {
510
500
  this.normalisedMousePosition.set(
511
501
  e.clientX / t.domElement.clientWidth * 2 - 1,
512
502
  -(e.clientY / t.domElement.clientHeight * 2) + 1
@@ -524,16 +514,146 @@ class rt {
524
514
  raycast(t, e) {
525
515
  if (this.normalisedMousePosition.x !== null && this.normalisedMousePosition.y !== null) {
526
516
  this.raycaster.setFromCamera(this.normalisedMousePosition, t);
527
- const i = this.raycaster.intersectObjects(e.children, !1);
528
- return this.normalisedMousePosition.set(null, null), i;
517
+ const n = this.raycaster.intersectObjects(e.children, !1);
518
+ return this.normalisedMousePosition.set(null, null), n;
529
519
  }
530
520
  return [];
531
521
  }
532
522
  }
523
+ AFRAME.registerComponent("locar-webcam", {
524
+ schema: {
525
+ idealWidth: {
526
+ type: "number",
527
+ default: 1024
528
+ },
529
+ idealHeight: {
530
+ type: "number",
531
+ default: 768
532
+ },
533
+ videoElement: {
534
+ type: "string",
535
+ default: ""
536
+ }
537
+ },
538
+ init: function() {
539
+ new J({
540
+ idealWidth: this.data.idealWidth,
541
+ idealHeight: this.data.idealHeight,
542
+ onVideoStarted: (i) => {
543
+ this.el.object3D.background = i;
544
+ }
545
+ }, this.data.videoElement || null);
546
+ }
547
+ });
548
+ AFRAME.registerComponent("locar-camera", {
549
+ schema: {
550
+ simulateLatitude: {
551
+ type: "number",
552
+ default: 0
553
+ },
554
+ simulateLongitude: {
555
+ type: "number",
556
+ default: 0
557
+ },
558
+ simulateAltitude: {
559
+ type: "number",
560
+ default: -Number.MAX_VALUE
561
+ },
562
+ positionMinAccuracy: {
563
+ type: "number",
564
+ default: 100
565
+ }
566
+ },
567
+ init: function() {
568
+ this.locar = new K(
569
+ this.el.sceneEl.object3D,
570
+ this.el.object3D
571
+ ), this.locar.on("gpsupdate", (i, t) => {
572
+ this.el.emit("gpsupdate", {
573
+ position: i,
574
+ distMoved: t
575
+ });
576
+ }), this.locar.on("gpserror", (i) => {
577
+ const t = [
578
+ "User denied access to GPS.",
579
+ "GPS satellites not available.",
580
+ "Timeout communicating with GPS satellites - try moving to a more open area."
581
+ ];
582
+ i >= 1 && i <= 3 ? alert(t[i - 1]) : alert(`Unknown geolocation error code ${i}.`);
583
+ }), this._isMobile() && (this.deviceOrientationControls = new st(this.el.object3D));
584
+ },
585
+ update: function(i) {
586
+ this.locar.setGpsOptions({
587
+ gpsMinAccuracy: this.data.positionMinAccuracy,
588
+ gpsMinDistance: this.data.gpsMinDistance
589
+ }), (this.data.simulateLatitude !== 0 || this.data.simulateLongitude !== 0) && (this.data.simulateLatitude != (i == null ? void 0 : i.simulateLatitude) || this.data.simulateLongitude != (i == null ? void 0 : i.simulateLongitude)) && (this.locar.stopGps(), this.locar.fakeGps(
590
+ this.data.simulateLongitude,
591
+ this.data.simulateLatitude
592
+ ), this.data.simulateLongitude = 0, this.data.simulateLatitude = 0), this.data.simulateAltitude > -Number.MAX_VALUE && this.locar.setElevation(this.data.simulateAltitude + 1.6);
593
+ },
594
+ play: function() {
595
+ this.locar.startGps();
596
+ },
597
+ pause: function() {
598
+ this.locar.stopGps();
599
+ },
600
+ /**
601
+ * Convert longitude and latitude to three.js/WebGL world coordinates.
602
+ * Uses the specified projection, and negates the northing (in typical
603
+ * projections, northings increase northwards, but in the WebGL coordinate
604
+ * system, we face negative z if the camera is at the origin with default
605
+ * rotation).
606
+ * @param {number} lon - The longitude.
607
+ * @param {number} lat - The latitude.
608
+ * @return {Array} a two member array containing the WebGL x and z coordinates
609
+ */
610
+ lonLatToWorldCoords: function(i, t) {
611
+ return this.locar.lonLatToWorldCoords(i, t);
612
+ },
613
+ tick: function() {
614
+ var i;
615
+ (i = this.deviceOrientationControls) == null || i.update();
616
+ },
617
+ _isMobile: function() {
618
+ return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(
619
+ navigator.userAgent
620
+ ) || /Macintosh/i.test(navigator.userAgent) && navigator.maxTouchPoints != null && navigator.maxTouchPoints > 1;
621
+ }
622
+ });
623
+ AFRAME.registerComponent("locar-entity-place", {
624
+ schema: {
625
+ latitude: {
626
+ type: "number",
627
+ default: 0
628
+ },
629
+ longitude: {
630
+ type: "number",
631
+ default: 0
632
+ }
633
+ },
634
+ init: function() {
635
+ const i = this.el.sceneEl.querySelector("[locar-camera]");
636
+ this.locarCamera = i.components["locar-camera"];
637
+ },
638
+ update: function(i) {
639
+ this.locarCamera || console.error("Cannot update locar-entity-place without a locar-camera component on the scene camera.");
640
+ const t = this.locarCamera.lonLatToWorldCoords(
641
+ this.data.longitude,
642
+ this.data.latitude
643
+ );
644
+ this.el.object3D.position.set(
645
+ t[0],
646
+ this.el.object3D.position.y,
647
+ t[1]
648
+ );
649
+ }
650
+ });
651
+ const ct = "0.0.10";
533
652
  export {
534
653
  rt as ClickHandler,
535
- at as DeviceOrientationControls,
536
- st as LocationBased,
537
- K as SphMercProjection,
538
- ot as WebcamRenderer
654
+ st as DeviceOrientationControls,
655
+ K as LocationBased,
656
+ $ as SphMercProjection,
657
+ J as Webcam,
658
+ ct as version
539
659
  };
package/dist/locar.umd.js CHANGED
@@ -1,3 +1,3 @@
1
- (function(a,i){typeof exports=="object"&&typeof module<"u"?i(exports,require("three")):typeof define=="function"&&define.amd?define(["exports","three"],i):(a=typeof globalThis<"u"?globalThis:a||self,i(a.locar={},a.THREE))})(this,function(a,i){"use strict";var H=a=>{throw TypeError(a)};var U=(a,i,f)=>i.has(a)||H("Cannot "+f);var n=(a,i,f)=>(U(a,i,"read from private field"),f?f.call(a):i.get(a)),v=(a,i,f)=>i.has(a)?H("Cannot add the same private member more than once"):i instanceof WeakSet?i.add(a):i.set(a,f),u=(a,i,f,m)=>(U(a,i,"write to private field"),m?m.call(a,f):i.set(a,f),f),y=(a,i,f)=>(U(a,i,"access private method"),f);var N=(a,i,f,m)=>({set _(W){u(a,i,W,f)},get _(){return n(a,i,m)}});var w,Q,G,X,B,S,I,T,x,j,_,O,E,L,P,M,q,V,R,Y;function f(b){const t=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(b){for(const e in b)if(e!=="default"){const s=Object.getOwnPropertyDescriptor(b,e);Object.defineProperty(t,e,s.get?s:{enumerable:!0,get:()=>b[e]})}}return t.default=b,Object.freeze(t)}const m=f(i);class W{constructor(){v(this,w);this.EARTH=4007501668e-2,this.HALF_EARTH=2003750834e-2}project(t,e){return[y(this,w,Q).call(this,t),y(this,w,G).call(this,e)]}unproject(t){return[y(this,w,X).call(this,t[0]),y(this,w,B).call(this,t[1])]}getID(){return"epsg:3857"}}w=new WeakSet,Q=function(t){return t/180*this.HALF_EARTH},G=function(t){var e=Math.log(Math.tan((90+t)*Math.PI/360))/(Math.PI/180);return e*this.HALF_EARTH/180},X=function(t){return t/this.HALF_EARTH*180},B=function(t){var e=t/this.HALF_EARTH*180;return e=180/Math.PI*(2*Math.atan(Math.exp(e*Math.PI/180))-Math.PI/2),e};class Z{constructor(t,e,s={},r=null){v(this,M);v(this,S);v(this,I);v(this,T);v(this,x);v(this,j);v(this,_);v(this,O);v(this,E);v(this,L);v(this,P);this.scene=t,this.camera=e,u(this,S,new W),u(this,I,{}),u(this,T,null),u(this,x,0),u(this,j,100),u(this,_,null),this.setGpsOptions(s),u(this,O,null),u(this,E,0),u(this,L,0),u(this,P,r)}setProjection(t){u(this,S,t)}setGpsOptions(t={}){t.gpsMinDistance!==void 0&&u(this,x,t.gpsMinDistance),t.gpsMinAccuracy!==void 0&&u(this,j,t.gpsMinAccuracy)}async startGps(){if(n(this,P)){const e=await(await n(this,P).sendData("/gps/start",{gpsMinDistance:n(this,x),gpsMinAccuracy:n(this,j)})).json();u(this,L,e.session)}return n(this,_)===null?(u(this,_,navigator.geolocation.watchPosition(t=>{y(this,M,R).call(this,t)},t=>{n(this,I).gpserror?n(this,I).gpserror(t.code):alert(`GPS error: code ${t.code}`)},{enableHighAccuracy:!0})),!0):!1}stopGps(){return n(this,_)!==null?(navigator.geolocation.clearWatch(n(this,_)),u(this,_,null),!0):!1}fakeGps(t,e,s=null,r=0){s!==null&&this.setElevation(s),y(this,M,R).call(this,{coords:{longitude:t,latitude:e,accuracy:r}})}lonLatToWorldCoords(t,e){const s=n(this,S).project(t,e);if(n(this,O))s[0]-=n(this,O)[0],s[1]-=n(this,O)[1];else throw"No initial position determined";return[s[0],-s[1]]}add(t,e,s,r,g={}){var p;t.properties=g,y(this,M,q).call(this,t,e,s,r),this.scene.add(t),(p=n(this,P))==null||p.sendData("/object/new",{position:t.position,x:t.position.x,z:t.position.z,session:n(this,L),properties:g})}setElevation(t){this.camera.position.y=t}on(t,e){n(this,I)[t]=e}}S=new WeakMap,I=new WeakMap,T=new WeakMap,x=new WeakMap,j=new WeakMap,_=new WeakMap,O=new WeakMap,E=new WeakMap,L=new WeakMap,P=new WeakMap,M=new WeakSet,q=function(t,e,s,r){const g=this.lonLatToWorldCoords(e,s);r!==void 0&&(t.position.y=r),[t.position.x,t.position.z]=g},V=function(t,e){u(this,O,n(this,S).project(t,e))},R=function(t){var s,r,g;let e=Number.MAX_VALUE;N(this,E)._++,(s=n(this,P))==null||s.sendData("/gps/new",{gpsCount:n(this,E),lat:t.coords.latitude,lon:t.coords.longitude,acc:t.coords.accuracy,session:n(this,L)}),t.coords.accuracy<=n(this,j)&&(n(this,T)===null?u(this,T,{latitude:t.coords.latitude,longitude:t.coords.longitude}):e=y(this,M,Y).call(this,n(this,T),t.coords),e>=n(this,x)&&(n(this,T).longitude=t.coords.longitude,n(this,T).latitude=t.coords.latitude,n(this,O)||(y(this,M,V).call(this,t.coords.longitude,t.coords.latitude),(r=n(this,P))==null||r.sendData("/worldorigin/new",{gpsCount:n(this,E),lat:t.coords.latitude,lon:t.coords.longitude,session:n(this,L),initialPosition:n(this,O)})),y(this,M,q).call(this,this.camera,t.coords.longitude,t.coords.latitude),(g=n(this,P))==null||g.sendData("/gps/accepted",{gpsCount:n(this,E),cameraX:this.camera.position.x,cameraZ:this.camera.position.z,session:n(this,L),distMoved:e}),n(this,I).gpsupdate&&n(this,I).gpsupdate(t,e)))},Y=function(t,e){const s=m.MathUtils.degToRad(e.longitude-t.longitude),r=m.MathUtils.degToRad(e.latitude-t.latitude),g=Math.sin(r/2)*Math.sin(r/2)+Math.cos(m.MathUtils.degToRad(t.latitude))*Math.cos(m.MathUtils.degToRad(e.latitude))*(Math.sin(s/2)*Math.sin(s/2));return 2*Math.atan2(Math.sqrt(g),Math.sqrt(1-g))*6371e3};class K{constructor(t,e,s){this.renderer=t,this.renderer.autoClear=!1,this.sceneWebcam=new m.Scene;let r;e?r=document.querySelector(e):(r=document.createElement("video"),r.setAttribute("autoplay",!0),r.setAttribute("playsinline",!0),r.style.display="none",document.body.appendChild(r)),this.geom=new m.PlaneGeometry,this.texture=new m.VideoTexture(r),this.material=new m.MeshBasicMaterial({map:this.texture});const g=new m.Mesh(this.geom,this.material);if(this.sceneWebcam.add(g),this.cameraWebcam=new m.OrthographicCamera(-.5,.5,.5,-.5,0,10),navigator.mediaDevices&&navigator.mediaDevices.getUserMedia){const p={video:{width:(s==null?void 0:s.width)||1280,height:(s==null?void 0:s.height)||720,facingMode:"environment"}};navigator.mediaDevices.getUserMedia(p).then(A=>{console.log("using the webcam successfully..."),r.srcObject=A,r.play()}).catch(A=>{setTimeout(()=>{alert(`Webcam Error
2
- Name: `+A.name+`
3
- Message: `+A.message)},1e3)})}else setTimeout(()=>{alert("sorry - media devices API not supported")},1e3)}update(){this.renderer.clear(),this.renderer.render(this.sceneWebcam,this.cameraWebcam),this.renderer.clearDepth()}dispose(){this.material.dispose(),this.texture.dispose(),this.geom.dispose()}}const k=navigator.userAgent.match(/iPhone|iPad|iPod/i)||/Macintosh/i.test(navigator.userAgent)&&navigator.maxTouchPoints!=null&&navigator.maxTouchPoints>1,$=new i.Vector3(0,0,1),z=new i.Euler,J=new i.Quaternion,tt=new i.Quaternion(-Math.sqrt(.5),0,0,Math.sqrt(.5)),et={type:"change"};class it extends i.EventDispatcher{constructor(t){super(),window.isSecureContext===!1&&console.error("THREE.DeviceOrientationControls: DeviceOrientationEvent is only available in secure contexts (https)");const e=this,s=1e-6,r=new i.Quaternion;this.object=t,this.object.rotation.reorder("YXZ"),this.enabled=!0,this.deviceOrientation=null,this.screenOrientation=0,this.alphaOffset=0,this.initialOffset=null,this.TWO_PI=2*Math.PI,this.HALF_PI=.5*Math.PI,this.orientationChangeEventName="ondeviceorientationabsolute"in window?"deviceorientationabsolute":"deviceorientation",this.smoothingFactor=1;const g=function({alpha:o,beta:h,gamma:l,webkitCompassHeading:c}){if(k){const d=360-c;e.alphaOffset=i.MathUtils.degToRad(d-o),e.deviceOrientation={alpha:o,beta:h,gamma:l,webkitCompassHeading:c}}else o<0&&(o+=360),e.deviceOrientation={alpha:o,beta:h,gamma:l};window.dispatchEvent(new CustomEvent("camera-rotation-change",{detail:{cameraRotation:t.rotation}}))},p=function(){e.screenOrientation=window.orientation||0},A=function(o,h,l,c,d){z.set(l,h,-c,"YXZ"),o.setFromEuler(z),o.multiply(tt),o.multiply(J.setFromAxisAngle($,-d))};this.connect=function(){p(),window.DeviceOrientationEvent!==void 0&&typeof window.DeviceOrientationEvent.requestPermission=="function"?window.DeviceOrientationEvent.requestPermission().then(o=>{o==="granted"&&(window.addEventListener("orientationchange",p),window.addEventListener(e.orientationChangeEventName,g))}).catch(function(o){console.error("THREE.DeviceOrientationControls: Unable to use DeviceOrientation API:",o)}):(window.addEventListener("orientationchange",p),window.addEventListener(e.orientationChangeEventName,g)),e.enabled=!0},this.disconnect=function(){window.removeEventListener("orientationchange",p),window.removeEventListener(e.orientationChangeEventName,g),e.enabled=!1,e.initialOffset=!1,e.deviceOrientation=null},this.update=function({theta:o=0}={theta:0}){if(e.enabled===!1)return;const h=e.deviceOrientation;if(h){let l=h.alpha?i.MathUtils.degToRad(h.alpha)+e.alphaOffset:0,c=h.beta?i.MathUtils.degToRad(h.beta):0,d=h.gamma?i.MathUtils.degToRad(h.gamma):0;const F=e.screenOrientation?i.MathUtils.degToRad(e.screenOrientation):0;if(k){const C=new i.Quaternion;A(C,l,c,d,F);const D=new i.Euler().setFromQuaternion(C,"YXZ");console.log(D.x,D.y,D.z),D.y=i.MathUtils.degToRad(360-h.webkitCompassHeading),C.setFromEuler(D),e.object.quaternion.copy(C)}else{if(this.smoothingFactor<1){if(this.lastOrientation){const C=this.smoothingFactor;l=this._getSmoothedAngle(l,this.lastOrientation.alpha,C),c=this._getSmoothedAngle(c+Math.PI,this.lastOrientation.beta,C),d=this._getSmoothedAngle(d+this.HALF_PI,this.lastOrientation.gamma,C,Math.PI)}else c+=Math.PI,d+=this.HALF_PI;this.lastOrientation={alpha:l,beta:c,gamma:d}}A(e.object.quaternion,l+o,this.smoothingFactor<1?c-Math.PI:c,this.smoothingFactor<1?d-this.HALF_PI:d,F)}8*(1-r.dot(e.object.quaternion))>s&&(r.copy(e.object.quaternion),e.dispatchEvent(et))}},this._orderAngle=function(o,h,l=this.TWO_PI){return h>o&&Math.abs(h-o)<l/2||o>h&&Math.abs(h-o)>l/2?{left:o,right:h}:{left:h,right:o}},this._getSmoothedAngle=function(o,h,l,c=this.TWO_PI){const d=this._orderAngle(o,h,c),F=d.left,C=d.right;d.left=0,d.right-=F,d.right<0&&(d.right+=c);let D=C==h?(1-l)*d.right+l*d.left:l*d.right+(1-l)*d.left;return D+=F,D>=c&&(D-=c),D},this.updateAlphaOffset=function(){e.initialOffset=!1},this.dispose=function(){e.disconnect()},this.getAlpha=function(){const{deviceOrientation:o}=e;return o&&o.alpha?i.MathUtils.degToRad(o.alpha)+e.alphaOffset:0},this.getBeta=function(){const{deviceOrientation:o}=e;return o&&o.beta?i.MathUtils.degToRad(o.beta):0},window.DeviceOrientationEvent!==void 0&&typeof window.DeviceOrientationEvent.requestPermission=="function"?this.initPermissionDialog():this.connect()}initPermissionDialog(){const t=document.createElement("div"),e=document.createElement("div"),s=document.createElement("div"),r=document.createElement("div");document.body.appendChild(t);const g={display:"flex",position:"fixed",top:0,left:0,width:"100%",height:"100%",zIndex:1,backgroundColor:"rgba(0,0,0,0.6)",justifyContent:"center",alignItems:"center"},p={backgroundColor:"white",padding:"6px",borderRadius:"3px",width:"36rem",height:"24rem"},A={width:"100%",height:"70%",display:"flex",justifyContent:"center",alignItems:"center"},o={display:"inline-flex",width:"100%",height:"30%",justifyContent:"center",alignItems:"center"};for(let c in g)t.style[c]=g[c];for(let c in p)e.style[c]=p[c];for(let c in A)s.style[c]=A[c];for(let c in o)r.style[c]=o[c];t.appendChild(e),e.appendChild(s),e.appendChild(r),s.innerHTML='<div style="font-size: 24pt; margin: 1rem;">This immersive website requires access to your device motion sensors.</div>';const h=()=>{this.connect(),t.style.display="none"},l=document.createElement("button");l.addEventListener("click",h),l.style.width="50%",l.style.height="80%",l.style.fontSize="20pt",l.appendChild(document.createTextNode("OK")),r.appendChild(l),document.body.appendChild(t)}}class nt{constructor(t){this.raycaster=new m.Raycaster,this.normalisedMousePosition=new m.Vector2(null,null),t.domElement.addEventListener("click",e=>{this.normalisedMousePosition.set(e.clientX/t.domElement.clientWidth*2-1,-(e.clientY/t.domElement.clientHeight*2)+1)})}raycast(t,e){if(this.normalisedMousePosition.x!==null&&this.normalisedMousePosition.y!==null){this.raycaster.setFromCamera(this.normalisedMousePosition,t);const s=this.raycaster.intersectObjects(e.children,!1);return this.normalisedMousePosition.set(null,null),s}return[]}}a.ClickHandler=nt,a.DeviceOrientationControls=it,a.LocationBased=Z,a.SphMercProjection=W,a.WebcamRenderer=K,Object.defineProperty(a,Symbol.toStringTag,{value:"Module"})});
1
+ (function(r,n){typeof exports=="object"&&typeof module<"u"?n(exports,require("three")):typeof define=="function"&&define.amd?define(["exports","three"],n):(r=typeof globalThis<"u"?globalThis:r||self,n(r.locar={},r.THREE))})(this,function(r,n){"use strict";var Q=r=>{throw TypeError(r)};var U=(r,n,p)=>n.has(r)||Q("Cannot "+p);var s=(r,n,p)=>(U(r,n,"read from private field"),p?p.call(r):n.get(r)),y=(r,n,p)=>n.has(r)?Q("Cannot add the same private member more than once"):n instanceof WeakSet?n.add(r):n.set(r,p),m=(r,n,p,v)=>(U(r,n,"write to private field"),v?v.call(r,p):n.set(r,p),p),w=(r,n,p)=>(U(r,n,"access private method"),p);var V=(r,n,p,v)=>({set _(W){m(r,n,W,p)},get _(){return s(r,n,v)}});var b,X,B,Y,Z,_,L,E,j,I,D,A,S,T,O,M,k,$,q,K;function p(a){const t=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(a){for(const e in a)if(e!=="default"){const i=Object.getOwnPropertyDescriptor(a,e);Object.defineProperty(t,e,i.get?i:{enumerable:!0,get:()=>a[e]})}}return t.default=a,Object.freeze(t)}const v=p(n);class W{constructor(){y(this,b);this.EARTH=4007501668e-2,this.HALF_EARTH=2003750834e-2}project(t,e){return[w(this,b,X).call(this,t),w(this,b,B).call(this,e)]}unproject(t){return[w(this,b,Y).call(this,t[0]),w(this,b,Z).call(this,t[1])]}getID(){return"epsg:3857"}}b=new WeakSet,X=function(t){return t/180*this.HALF_EARTH},B=function(t){var e=Math.log(Math.tan((90+t)*Math.PI/360))/(Math.PI/180);return e*this.HALF_EARTH/180},Y=function(t){return t/this.HALF_EARTH*180},Z=function(t){var e=t/this.HALF_EARTH*180;return e=180/Math.PI*(2*Math.atan(Math.exp(e*Math.PI/180))-Math.PI/2),e};class H{constructor(t,e,i={},h=null){y(this,M);y(this,_);y(this,L);y(this,E);y(this,j);y(this,I);y(this,D);y(this,A);y(this,S);y(this,T);y(this,O);this.scene=t,this.camera=e,m(this,_,new W),m(this,L,{}),m(this,E,null),m(this,j,0),m(this,I,100),m(this,D,null),this.setGpsOptions(i),m(this,A,null),m(this,S,0),m(this,T,0),m(this,O,h)}setProjection(t){m(this,_,t)}setGpsOptions(t={}){t.gpsMinDistance!==void 0&&m(this,j,t.gpsMinDistance),t.gpsMinAccuracy!==void 0&&m(this,I,t.gpsMinAccuracy)}async startGps(){if(s(this,O)){const e=await(await s(this,O).sendData("/gps/start",{gpsMinDistance:s(this,j),gpsMinAccuracy:s(this,I)})).json();m(this,T,e.session)}return s(this,D)===null?(m(this,D,navigator.geolocation.watchPosition(t=>{w(this,M,q).call(this,t)},t=>{s(this,L).gpserror?s(this,L).gpserror(t.code):alert(`GPS error: code ${t.code}`)},{enableHighAccuracy:!0})),!0):!1}stopGps(){return s(this,D)!==null?(navigator.geolocation.clearWatch(s(this,D)),m(this,D,null),!0):!1}fakeGps(t,e,i=null,h=0){i!==null&&this.setElevation(i),w(this,M,q).call(this,{coords:{longitude:t,latitude:e,accuracy:h}})}lonLatToWorldCoords(t,e){const i=s(this,_).project(t,e);if(s(this,A))i[0]-=s(this,A)[0],i[1]-=s(this,A)[1];else throw"No initial position determined";return[i[0],-i[1]]}add(t,e,i,h,u={}){var f;t.properties=u,w(this,M,k).call(this,t,e,i,h),this.scene.add(t),(f=s(this,O))==null||f.sendData("/object/new",{position:t.position,x:t.position.x,z:t.position.z,session:s(this,T),properties:u})}setElevation(t){this.camera.position.y=t}on(t,e){s(this,L)[t]=e}}_=new WeakMap,L=new WeakMap,E=new WeakMap,j=new WeakMap,I=new WeakMap,D=new WeakMap,A=new WeakMap,S=new WeakMap,T=new WeakMap,O=new WeakMap,M=new WeakSet,k=function(t,e,i,h){const u=this.lonLatToWorldCoords(e,i);h!==void 0&&(t.position.y=h),[t.position.x,t.position.z]=u},$=function(t,e){m(this,A,s(this,_).project(t,e))},q=function(t){var i,h,u;let e=Number.MAX_VALUE;V(this,S)._++,(i=s(this,O))==null||i.sendData("/gps/new",{gpsCount:s(this,S),lat:t.coords.latitude,lon:t.coords.longitude,acc:t.coords.accuracy,session:s(this,T)}),t.coords.accuracy<=s(this,I)&&(s(this,E)===null?m(this,E,{latitude:t.coords.latitude,longitude:t.coords.longitude}):e=w(this,M,K).call(this,s(this,E),t.coords),e>=s(this,j)&&(s(this,E).longitude=t.coords.longitude,s(this,E).latitude=t.coords.latitude,s(this,A)||(w(this,M,$).call(this,t.coords.longitude,t.coords.latitude),(h=s(this,O))==null||h.sendData("/worldorigin/new",{gpsCount:s(this,S),lat:t.coords.latitude,lon:t.coords.longitude,session:s(this,T),initialPosition:s(this,A)})),w(this,M,k).call(this,this.camera,t.coords.longitude,t.coords.latitude),(u=s(this,O))==null||u.sendData("/gps/accepted",{gpsCount:s(this,S),cameraX:this.camera.position.x,cameraZ:this.camera.position.z,session:s(this,T),distMoved:e}),s(this,L).gpsupdate&&s(this,L).gpsupdate(t,e)))},K=function(t,e){const i=v.MathUtils.degToRad(e.longitude-t.longitude),h=v.MathUtils.degToRad(e.latitude-t.latitude),u=Math.sin(h/2)*Math.sin(h/2)+Math.cos(v.MathUtils.degToRad(t.latitude))*Math.cos(v.MathUtils.degToRad(e.latitude))*(Math.sin(i/2)*Math.sin(i/2));return 2*Math.atan2(Math.sqrt(u),Math.sqrt(1-u))*6371e3};class G{constructor(t={},e){this.sceneWebcam=new v.Scene;let i;if(e?i=document.querySelector(e):(i=document.createElement("video"),i.setAttribute("autoplay",!0),i.setAttribute("playsinline",!0),i.style.display="none",document.body.appendChild(i)),this.texture=new v.VideoTexture(i),navigator.mediaDevices&&navigator.mediaDevices.getUserMedia){const h={video:{width:{ideal:t.idealWidth||1280},height:{ideal:t.idealHeight||720},facingMode:"environment"}};navigator.mediaDevices.getUserMedia(h).then(u=>{i.addEventListener("loadedmetadata",()=>{var f;i.setAttribute("width",i.videoWidth),i.setAttribute("height",i.videoHeight),i.play(),(f=t.onVideoStarted)==null||f.call(this,this.texture)}),i.srcObject=u}).catch(u=>{setTimeout(()=>{alert(`Webcam Error
2
+ Name: `+u.name+`
3
+ Message: `+u.message)},1e3)})}else setTimeout(()=>{alert("sorry - media devices API not supported")},1e3)}dispose(){this.texture.dispose()}}const R=navigator.userAgent.match(/iPhone|iPad|iPod/i)||/Macintosh/i.test(navigator.userAgent)&&navigator.maxTouchPoints!=null&&navigator.maxTouchPoints>1,J=new n.Vector3(0,0,1),N=new n.Euler,tt=new n.Quaternion,et=new n.Quaternion(-Math.sqrt(.5),0,0,Math.sqrt(.5)),it={type:"change"};class z extends n.EventDispatcher{constructor(t){super(),window.isSecureContext===!1&&console.error("THREE.DeviceOrientationControls: DeviceOrientationEvent is only available in secure contexts (https)");const e=this,i=1e-6,h=new n.Quaternion;this.object=t,this.object.rotation.reorder("YXZ"),this.enabled=!0,this.deviceOrientation=null,this.screenOrientation=0,this.alphaOffset=0,this.initialOffset=null,this.TWO_PI=2*Math.PI,this.HALF_PI=.5*Math.PI,this.orientationChangeEventName="ondeviceorientationabsolute"in window?"deviceorientationabsolute":"deviceorientation",this.smoothingFactor=1;const u=function({alpha:o,beta:l,gamma:d,webkitCompassHeading:c}){if(R){const g=360-c;e.alphaOffset=n.MathUtils.degToRad(g-o),e.deviceOrientation={alpha:o,beta:l,gamma:d,webkitCompassHeading:c}}else o<0&&(o+=360),e.deviceOrientation={alpha:o,beta:l,gamma:d};window.dispatchEvent(new CustomEvent("camera-rotation-change",{detail:{cameraRotation:t.rotation}}))},f=function(){e.screenOrientation=window.orientation||0},x=function(o,l,d,c,g){N.set(d,l,-c,"YXZ"),o.setFromEuler(N),o.multiply(et),o.multiply(tt.setFromAxisAngle(J,-g))};this.connect=function(){f(),window.DeviceOrientationEvent!==void 0&&typeof window.DeviceOrientationEvent.requestPermission=="function"?window.DeviceOrientationEvent.requestPermission().then(o=>{o==="granted"&&(window.addEventListener("orientationchange",f),window.addEventListener(e.orientationChangeEventName,u))}).catch(function(o){console.error("THREE.DeviceOrientationControls: Unable to use DeviceOrientation API:",o)}):(window.addEventListener("orientationchange",f),window.addEventListener(e.orientationChangeEventName,u)),e.enabled=!0},this.disconnect=function(){window.removeEventListener("orientationchange",f),window.removeEventListener(e.orientationChangeEventName,u),e.enabled=!1,e.initialOffset=!1,e.deviceOrientation=null},this.update=function({theta:o=0}={theta:0}){if(e.enabled===!1)return;const l=e.deviceOrientation;if(l){let d=l.alpha?n.MathUtils.degToRad(l.alpha)+e.alphaOffset:0,c=l.beta?n.MathUtils.degToRad(l.beta):0,g=l.gamma?n.MathUtils.degToRad(l.gamma):0;const F=e.screenOrientation?n.MathUtils.degToRad(e.screenOrientation):0;if(R){const P=new n.Quaternion;x(P,d,c,g,F);const C=new n.Euler().setFromQuaternion(P,"YXZ");console.log(C.x,C.y,C.z),C.y=n.MathUtils.degToRad(360-l.webkitCompassHeading),P.setFromEuler(C),e.object.quaternion.copy(P)}else{if(this.smoothingFactor<1){if(this.lastOrientation){const P=this.smoothingFactor;d=this._getSmoothedAngle(d,this.lastOrientation.alpha,P),c=this._getSmoothedAngle(c+Math.PI,this.lastOrientation.beta,P),g=this._getSmoothedAngle(g+this.HALF_PI,this.lastOrientation.gamma,P,Math.PI)}else c+=Math.PI,g+=this.HALF_PI;this.lastOrientation={alpha:d,beta:c,gamma:g}}x(e.object.quaternion,d+o,this.smoothingFactor<1?c-Math.PI:c,this.smoothingFactor<1?g-this.HALF_PI:g,F)}8*(1-h.dot(e.object.quaternion))>i&&(h.copy(e.object.quaternion),e.dispatchEvent(it))}},this._orderAngle=function(o,l,d=this.TWO_PI){return l>o&&Math.abs(l-o)<d/2||o>l&&Math.abs(l-o)>d/2?{left:o,right:l}:{left:l,right:o}},this._getSmoothedAngle=function(o,l,d,c=this.TWO_PI){const g=this._orderAngle(o,l,c),F=g.left,P=g.right;g.left=0,g.right-=F,g.right<0&&(g.right+=c);let C=P==l?(1-d)*g.right+d*g.left:d*g.right+(1-d)*g.left;return C+=F,C>=c&&(C-=c),C},this.updateAlphaOffset=function(){e.initialOffset=!1},this.dispose=function(){e.disconnect()},this.getAlpha=function(){const{deviceOrientation:o}=e;return o&&o.alpha?n.MathUtils.degToRad(o.alpha)+e.alphaOffset:0},this.getBeta=function(){const{deviceOrientation:o}=e;return o&&o.beta?n.MathUtils.degToRad(o.beta):0},window.DeviceOrientationEvent!==void 0&&typeof window.DeviceOrientationEvent.requestPermission=="function"?this.initPermissionDialog():this.connect()}initPermissionDialog(){const t=document.createElement("div"),e=document.createElement("div"),i=document.createElement("div"),h=document.createElement("div");document.body.appendChild(t);const u={display:"flex",position:"fixed",top:0,left:0,width:"100%",height:"100%",zIndex:1,backgroundColor:"rgba(0,0,0,0.6)",justifyContent:"center",alignItems:"center"},f={backgroundColor:"white",padding:"6px",borderRadius:"3px",width:"36rem",height:"24rem"},x={width:"100%",height:"70%",display:"flex",justifyContent:"center",alignItems:"center"},o={display:"inline-flex",width:"100%",height:"30%",justifyContent:"center",alignItems:"center"};for(let c in u)t.style[c]=u[c];for(let c in f)e.style[c]=f[c];for(let c in x)i.style[c]=x[c];for(let c in o)h.style[c]=o[c];t.appendChild(e),e.appendChild(i),e.appendChild(h),i.innerHTML='<div style="font-size: 24pt; margin: 1rem;">This immersive website requires access to your device motion sensors.</div>';const l=()=>{this.connect(),t.style.display="none"},d=document.createElement("button");d.addEventListener("click",l),d.style.width="50%",d.style.height="80%",d.style.fontSize="20pt",d.appendChild(document.createTextNode("OK")),h.appendChild(d),document.body.appendChild(t)}}class nt{constructor(t){this.raycaster=new v.Raycaster,this.normalisedMousePosition=new v.Vector2(null,null),t.domElement.addEventListener("click",e=>{this.normalisedMousePosition.set(e.clientX/t.domElement.clientWidth*2-1,-(e.clientY/t.domElement.clientHeight*2)+1)})}raycast(t,e){if(this.normalisedMousePosition.x!==null&&this.normalisedMousePosition.y!==null){this.raycaster.setFromCamera(this.normalisedMousePosition,t);const i=this.raycaster.intersectObjects(e.children,!1);return this.normalisedMousePosition.set(null,null),i}return[]}}AFRAME.registerComponent("locar-webcam",{schema:{idealWidth:{type:"number",default:1024},idealHeight:{type:"number",default:768},videoElement:{type:"string",default:""}},init:function(){new G({idealWidth:this.data.idealWidth,idealHeight:this.data.idealHeight,onVideoStarted:a=>{this.el.object3D.background=a}},this.data.videoElement||null)}}),AFRAME.registerComponent("locar-camera",{schema:{simulateLatitude:{type:"number",default:0},simulateLongitude:{type:"number",default:0},simulateAltitude:{type:"number",default:-Number.MAX_VALUE},positionMinAccuracy:{type:"number",default:100}},init:function(){this.locar=new H(this.el.sceneEl.object3D,this.el.object3D),this.locar.on("gpsupdate",(a,t)=>{this.el.emit("gpsupdate",{position:a,distMoved:t})}),this.locar.on("gpserror",a=>{const t=["User denied access to GPS.","GPS satellites not available.","Timeout communicating with GPS satellites - try moving to a more open area."];a>=1&&a<=3?alert(t[a-1]):alert(`Unknown geolocation error code ${a}.`)}),this._isMobile()&&(this.deviceOrientationControls=new z(this.el.object3D))},update:function(a){this.locar.setGpsOptions({gpsMinAccuracy:this.data.positionMinAccuracy,gpsMinDistance:this.data.gpsMinDistance}),(this.data.simulateLatitude!==0||this.data.simulateLongitude!==0)&&(this.data.simulateLatitude!=(a==null?void 0:a.simulateLatitude)||this.data.simulateLongitude!=(a==null?void 0:a.simulateLongitude))&&(this.locar.stopGps(),this.locar.fakeGps(this.data.simulateLongitude,this.data.simulateLatitude),this.data.simulateLongitude=0,this.data.simulateLatitude=0),this.data.simulateAltitude>-Number.MAX_VALUE&&this.locar.setElevation(this.data.simulateAltitude+1.6)},play:function(){this.locar.startGps()},pause:function(){this.locar.stopGps()},lonLatToWorldCoords:function(a,t){return this.locar.lonLatToWorldCoords(a,t)},tick:function(){var a;(a=this.deviceOrientationControls)==null||a.update()},_isMobile:function(){return/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)||/Macintosh/i.test(navigator.userAgent)&&navigator.maxTouchPoints!=null&&navigator.maxTouchPoints>1}}),AFRAME.registerComponent("locar-entity-place",{schema:{latitude:{type:"number",default:0},longitude:{type:"number",default:0}},init:function(){const a=this.el.sceneEl.querySelector("[locar-camera]");this.locarCamera=a.components["locar-camera"]},update:function(a){this.locarCamera||console.error("Cannot update locar-entity-place without a locar-camera component on the scene camera.");const t=this.locarCamera.lonLatToWorldCoords(this.data.longitude,this.data.latitude);this.el.object3D.position.set(t[0],this.el.object3D.position.y,t[1])}});const st="0.0.10";r.ClickHandler=nt,r.DeviceOrientationControls=z,r.LocationBased=H,r.SphMercProjection=W,r.Webcam=G,r.version=st,Object.defineProperty(r,Symbol.toStringTag,{value:"Module"})});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "locar",
3
- "version": "0.0.8",
3
+ "version": "0.0.10",
4
4
  "description": "Location-based AR from AR.js.",
5
5
  "files": [
6
6
  "dist"
@@ -20,5 +20,8 @@
20
20
  "devDependencies": {
21
21
  "jsdoc": "^4.0.4",
22
22
  "vite": "^5.4.8"
23
+ },
24
+ "dependencies": {
25
+ "three": "^0.175.0"
23
26
  }
24
27
  }