locar 0.0.12 → 0.1.0
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 +8 -2
- package/dist/locar.es.js +347 -343
- package/dist/locar.umd.js +1 -3
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -22,7 +22,9 @@ Some of these issues, such as incorrect North on some devices, may well be to do
|
|
|
22
22
|
|
|
23
23
|
## Cross-platform Compatibility
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
It should now work on Chrome (and possibly Safari) on iOS as well as Android, due to a number of recent iOS fixes by project contributors.
|
|
26
|
+
|
|
27
|
+
Firefox unfortunately does not appear to fully implement the Device Orientation API so is unlikely to work.
|
|
26
28
|
|
|
27
29
|
## Using the library
|
|
28
30
|
|
|
@@ -40,7 +42,7 @@ import * as LocAR from 'locar';
|
|
|
40
42
|
as long as you include `locar` as a dependency, e.g. in your `package.json`:
|
|
41
43
|
```
|
|
42
44
|
"dependencies": {
|
|
43
|
-
"locar" : "^0.0
|
|
45
|
+
"locar" : "^0.1.0",
|
|
44
46
|
"three" : "^0.175.0"
|
|
45
47
|
}
|
|
46
48
|
```
|
|
@@ -55,6 +57,10 @@ Please see [here](https://ar-js-org.github.io/locar.js/api) for full API documen
|
|
|
55
57
|
|
|
56
58
|
Please see [here](https://github.com/AR-js-org/locar.js/blob/master/docs/tutorial/index.md) for a tutorial introducing LocAR.js.
|
|
57
59
|
|
|
60
|
+
## Contributors
|
|
61
|
+
|
|
62
|
+
Many thanks to all contributors to the project, in particular [Darian Elias Weiß](https://github.com/darianwwu) and [Kazuhiro Matsuyama](https://github.com/ma2yama) for providing extremely valuable iOS fixes and enhancements.
|
|
63
|
+
|
|
58
64
|
## Disclaimer
|
|
59
65
|
|
|
60
66
|
This is an open-source project licensed under the [MIT License](LICENSE) and thus comes with no warranty. Also it is a volunteer-led project; work on the project by AR.js maintainers or any other contributor will be undertaken *time-permitting* only. For this reason we welcome contributors! The more people working on the project, the more likely it is that it will become full-featured and issues will be resolved.
|
package/dist/locar.es.js
CHANGED
|
@@ -1,25 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
var S = (r, t, i) => t.has(r) || q("Cannot " + i);
|
|
5
|
-
var n = (r, t, i) => (S(r, t, "read from private field"), i ? i.call(r) : t.get(r)), m = (r, t, i) => t.has(r) ? q("Cannot add the same private member more than once") : t instanceof WeakSet ? t.add(r) : t.set(r, i), l = (r, t, i, e) => (S(r, t, "write to private field"), e ? e.call(r, i) : t.set(r, i), i), p = (r, t, i) => (S(r, t, "access private method"), i);
|
|
6
|
-
var k = (r, t, i, e) => ({
|
|
7
|
-
set _(c) {
|
|
8
|
-
l(r, t, c, i);
|
|
9
|
-
},
|
|
10
|
-
get _() {
|
|
11
|
-
return n(r, t, e);
|
|
12
|
-
}
|
|
13
|
-
});
|
|
14
|
-
import * as b from "three";
|
|
15
|
-
import { Vector3 as B, Euler as U, Quaternion as F, EventDispatcher as K, MathUtils as C } from "three";
|
|
16
|
-
var E, G, X, Q, V;
|
|
17
|
-
class $ {
|
|
1
|
+
import * as f from "three";
|
|
2
|
+
import { Vector3 as I, Euler as A, Quaternion as w, EventDispatcher as C, MathUtils as m } from "three";
|
|
3
|
+
class T {
|
|
18
4
|
/**
|
|
19
5
|
* Create a SphMercProjection.
|
|
20
6
|
*/
|
|
21
7
|
constructor() {
|
|
22
|
-
m(this, E);
|
|
23
8
|
this.EARTH = 4007501668e-2, this.HALF_EARTH = 2003750834e-2;
|
|
24
9
|
}
|
|
25
10
|
/**
|
|
@@ -28,16 +13,30 @@ class $ {
|
|
|
28
13
|
* @param {number} lat - the latitude.
|
|
29
14
|
* @return {Array} Two-member array containing easting and northing.
|
|
30
15
|
*/
|
|
31
|
-
project(
|
|
32
|
-
return [
|
|
16
|
+
project(e, i) {
|
|
17
|
+
return [this.#t(e), this.#h(i)];
|
|
33
18
|
}
|
|
34
19
|
/**
|
|
35
20
|
* Unproject a Spherical Mercator easting and northing.
|
|
36
21
|
* @param {Array} projected - Two-member array containing easting and northing
|
|
37
22
|
* @return {Array} Two-member array containing longitude and latitude
|
|
38
23
|
*/
|
|
39
|
-
unproject(
|
|
40
|
-
return [
|
|
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
|
+
#h(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;
|
|
41
40
|
}
|
|
42
41
|
/**
|
|
43
42
|
* Return the projection's ID.
|
|
@@ -47,19 +46,38 @@ class $ {
|
|
|
47
46
|
return "epsg:3857";
|
|
48
47
|
}
|
|
49
48
|
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
49
|
+
class P {
|
|
50
|
+
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] = i;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Emit an event.
|
|
63
|
+
* @param {string} eventName - the event to emit.
|
|
64
|
+
* @param ...params - parameters to pass to the event handler.
|
|
65
|
+
*/
|
|
66
|
+
emit(e, ...i) {
|
|
67
|
+
this.eventHandlers[e]?.call(this, ...i);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
class L extends P {
|
|
71
|
+
#t;
|
|
72
|
+
#h;
|
|
73
|
+
#e;
|
|
74
|
+
#s;
|
|
75
|
+
#c;
|
|
76
|
+
#o;
|
|
77
|
+
#i;
|
|
78
|
+
#r;
|
|
79
|
+
#a;
|
|
80
|
+
#n;
|
|
63
81
|
/**
|
|
64
82
|
* @param {THREE.Scene} scene - The Three.js scene to use.
|
|
65
83
|
* @param {THREE.Camera} camera - The Three.js camera to use. Should usually
|
|
@@ -68,19 +86,8 @@ class ot {
|
|
|
68
86
|
* setGpsOptions() below.
|
|
69
87
|
* @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
88
|
*/
|
|
71
|
-
constructor(
|
|
72
|
-
|
|
73
|
-
m(this, x);
|
|
74
|
-
m(this, O);
|
|
75
|
-
m(this, P);
|
|
76
|
-
m(this, H);
|
|
77
|
-
m(this, L);
|
|
78
|
-
m(this, A);
|
|
79
|
-
m(this, y);
|
|
80
|
-
m(this, D);
|
|
81
|
-
m(this, T);
|
|
82
|
-
m(this, M);
|
|
83
|
-
this.scene = t, this.camera = i, l(this, x, new $()), l(this, O, {}), l(this, P, null), l(this, H, 0), l(this, L, 100), l(this, A, null), this.setGpsOptions(e), l(this, y, null), l(this, D, 0), l(this, T, 0), l(this, M, c);
|
|
89
|
+
constructor(e, i, t = {}, c = null) {
|
|
90
|
+
super(), this.scene = e, this.camera = i, this.#t = new T(), 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;
|
|
84
91
|
}
|
|
85
92
|
/**
|
|
86
93
|
* Set the projection to use.
|
|
@@ -88,8 +95,8 @@ class ot {
|
|
|
88
95
|
* taking longitude and latitude as arguments and returning an array
|
|
89
96
|
* containing easting and northing.
|
|
90
97
|
*/
|
|
91
|
-
setProjection(
|
|
92
|
-
|
|
98
|
+
setProjection(e) {
|
|
99
|
+
this.#t = e;
|
|
93
100
|
}
|
|
94
101
|
/**
|
|
95
102
|
* Set the GPS options.
|
|
@@ -98,8 +105,8 @@ class ot {
|
|
|
98
105
|
* must move to process a new GPS reading, and the latter specifies the
|
|
99
106
|
* minimum accuracy, in metres, for a GPS reading to be counted.
|
|
100
107
|
*/
|
|
101
|
-
setGpsOptions(
|
|
102
|
-
|
|
108
|
+
setGpsOptions(e = {}) {
|
|
109
|
+
e.gpsMinDistance !== void 0 && (this.#s = e.gpsMinDistance), e.gpsMinAccuracy !== void 0 && (this.#c = e.gpsMinAccuracy);
|
|
103
110
|
}
|
|
104
111
|
/**
|
|
105
112
|
* Start the GPS on a real device
|
|
@@ -107,24 +114,24 @@ class ot {
|
|
|
107
114
|
* GPS errors can be handled by handling the gpserror event.
|
|
108
115
|
*/
|
|
109
116
|
async startGps() {
|
|
110
|
-
if (n
|
|
111
|
-
const i = await (await n
|
|
112
|
-
gpsMinDistance:
|
|
113
|
-
gpsMinAccuracy:
|
|
117
|
+
if (this.#n) {
|
|
118
|
+
const i = await (await this.#n.sendData("/gps/start", {
|
|
119
|
+
gpsMinDistance: this.#s,
|
|
120
|
+
gpsMinAccuracy: this.#c
|
|
114
121
|
})).json();
|
|
115
|
-
|
|
122
|
+
this.#a = i.session;
|
|
116
123
|
}
|
|
117
|
-
return
|
|
118
|
-
(
|
|
119
|
-
|
|
124
|
+
return this.#o === null ? (this.#o = navigator.geolocation.watchPosition(
|
|
125
|
+
(e) => {
|
|
126
|
+
this.#l(e);
|
|
120
127
|
},
|
|
121
|
-
(
|
|
122
|
-
|
|
128
|
+
(e) => {
|
|
129
|
+
this.emit("gpserror", e);
|
|
123
130
|
},
|
|
124
131
|
{
|
|
125
132
|
enableHighAccuracy: !0
|
|
126
133
|
}
|
|
127
|
-
)
|
|
134
|
+
), !0) : !1;
|
|
128
135
|
}
|
|
129
136
|
/**
|
|
130
137
|
* Stop the GPS on a real device
|
|
@@ -132,7 +139,7 @@ class ot {
|
|
|
132
139
|
* stopped (i.e. it was never started).
|
|
133
140
|
*/
|
|
134
141
|
stopGps() {
|
|
135
|
-
return
|
|
142
|
+
return this.#o !== null ? (navigator.geolocation.clearWatch(this.#o), this.#o = null, !0) : !1;
|
|
136
143
|
}
|
|
137
144
|
/**
|
|
138
145
|
* Send a fake GPS signal. Useful for testing on a desktop or laptop.
|
|
@@ -143,10 +150,10 @@ class ot {
|
|
|
143
150
|
* @param {number} acc - The accuracy of the GPS reading in metres. May be
|
|
144
151
|
* ignored if lower than the specified minimum accuracy.
|
|
145
152
|
*/
|
|
146
|
-
fakeGps(
|
|
147
|
-
|
|
153
|
+
fakeGps(e, i, t = null, c = 0) {
|
|
154
|
+
t !== null && this.setElevation(t), this.#l({
|
|
148
155
|
coords: {
|
|
149
|
-
longitude:
|
|
156
|
+
longitude: e,
|
|
150
157
|
latitude: i,
|
|
151
158
|
accuracy: c
|
|
152
159
|
}
|
|
@@ -158,17 +165,18 @@ class ot {
|
|
|
158
165
|
* projections, northings increase northwards, but in the WebGL coordinate
|
|
159
166
|
* system, we face negative z if the camera is at the origin with default
|
|
160
167
|
* rotation).
|
|
168
|
+
* Must not be called until an initial position is determined.
|
|
161
169
|
* @param {number} lon - The longitude.
|
|
162
170
|
* @param {number} lat - The latitude.
|
|
163
171
|
* @return {Array} a two member array containing the WebGL x and z coordinates
|
|
164
172
|
*/
|
|
165
|
-
lonLatToWorldCoords(
|
|
166
|
-
const
|
|
167
|
-
if (
|
|
168
|
-
|
|
173
|
+
lonLatToWorldCoords(e, i) {
|
|
174
|
+
const t = this.#t.project(e, i);
|
|
175
|
+
if (this.#i)
|
|
176
|
+
t[0] -= this.#i[0], t[1] -= this.#i[1];
|
|
169
177
|
else
|
|
170
178
|
throw "No initial position determined";
|
|
171
|
-
return [
|
|
179
|
+
return [t[0], -t[1]];
|
|
172
180
|
}
|
|
173
181
|
/**
|
|
174
182
|
* Add a new AR object at a given latitude, longitude and elevation.
|
|
@@ -180,121 +188,95 @@ class ot {
|
|
|
180
188
|
* @param {Object} properties - properties describing the object (for example,
|
|
181
189
|
* the contents of the GeoJSON properties field).
|
|
182
190
|
*/
|
|
183
|
-
add(
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
session: n(this, T),
|
|
191
|
+
add(e, i, t, c, d = {}) {
|
|
192
|
+
e.properties = d, this.#d(e, i, t, c), this.scene.add(e), this.#n?.sendData("/object/new", {
|
|
193
|
+
position: e.position,
|
|
194
|
+
x: e.position.x,
|
|
195
|
+
z: e.position.z,
|
|
196
|
+
session: this.#a,
|
|
190
197
|
properties: d
|
|
191
198
|
});
|
|
192
199
|
}
|
|
200
|
+
#d(e, i, t, c) {
|
|
201
|
+
const d = this.lonLatToWorldCoords(i, t);
|
|
202
|
+
c !== void 0 && (e.position.y = c), [e.position.x, e.position.z] = d;
|
|
203
|
+
}
|
|
193
204
|
/**
|
|
194
205
|
* Set the elevation (y coordinate) of the camera.
|
|
195
206
|
* @param {number} elev - the elevation in metres.
|
|
196
207
|
*/
|
|
197
|
-
setElevation(
|
|
198
|
-
this.camera.position.y =
|
|
208
|
+
setElevation(e) {
|
|
209
|
+
this.camera.position.y = e;
|
|
210
|
+
}
|
|
211
|
+
#u(e, i) {
|
|
212
|
+
this.#i = this.#t.project(e, i);
|
|
213
|
+
}
|
|
214
|
+
#l(e) {
|
|
215
|
+
let i = Number.MAX_VALUE;
|
|
216
|
+
this.#r++, this.#n?.sendData("/gps/new", {
|
|
217
|
+
gpsCount: this.#r,
|
|
218
|
+
lat: e.coords.latitude,
|
|
219
|
+
lon: e.coords.longitude,
|
|
220
|
+
acc: e.coords.accuracy,
|
|
221
|
+
session: this.#a
|
|
222
|
+
}), e.coords.accuracy <= this.#c && (this.#e === null ? this.#e = {
|
|
223
|
+
latitude: e.coords.latitude,
|
|
224
|
+
longitude: e.coords.longitude
|
|
225
|
+
} : i = this.#m(this.#e, e.coords), i >= this.#s && (this.#e.longitude = e.coords.longitude, this.#e.latitude = e.coords.latitude, this.#i || (this.#u(
|
|
226
|
+
e.coords.longitude,
|
|
227
|
+
e.coords.latitude
|
|
228
|
+
), this.#n?.sendData("/worldorigin/new", {
|
|
229
|
+
gpsCount: this.#r,
|
|
230
|
+
lat: e.coords.latitude,
|
|
231
|
+
lon: e.coords.longitude,
|
|
232
|
+
session: this.#a,
|
|
233
|
+
initialPosition: this.#i
|
|
234
|
+
})), this.#d(
|
|
235
|
+
this.camera,
|
|
236
|
+
e.coords.longitude,
|
|
237
|
+
e.coords.latitude
|
|
238
|
+
), this.#n?.sendData("/gps/accepted", {
|
|
239
|
+
gpsCount: this.#r,
|
|
240
|
+
cameraX: this.camera.position.x,
|
|
241
|
+
cameraZ: this.camera.position.z,
|
|
242
|
+
session: this.#a,
|
|
243
|
+
distMoved: i
|
|
244
|
+
}), this.emit("gpsupdate", { position: e, distMoved: i })));
|
|
199
245
|
}
|
|
200
246
|
/**
|
|
201
|
-
*
|
|
202
|
-
*
|
|
203
|
-
*
|
|
204
|
-
* standard Geolocation API position object, along with the distance moved
|
|
205
|
-
* since the last GPS update in metres.
|
|
206
|
-
* The latter fires when a GPS error is generated, and is passed the
|
|
207
|
-
* standard Geolocation API numerical error code.
|
|
208
|
-
* @param {string} eventName - the event to handle.
|
|
209
|
-
* @param {Function} eventHandler - the event handler function.
|
|
210
|
-
* @listens LocationBased#gpsupdate
|
|
211
|
-
* @listens LocationBased#gpserror
|
|
247
|
+
* Calculate haversine distance between two lat/lon pairs.
|
|
248
|
+
*
|
|
249
|
+
* Taken from original A-Frame AR.js location-based components
|
|
212
250
|
*/
|
|
213
|
-
|
|
214
|
-
|
|
251
|
+
#m(e, i) {
|
|
252
|
+
const t = f.MathUtils.degToRad(i.longitude - e.longitude), c = f.MathUtils.degToRad(i.latitude - e.latitude), d = Math.sin(c / 2) * Math.sin(c / 2) + Math.cos(f.MathUtils.degToRad(e.latitude)) * Math.cos(f.MathUtils.degToRad(i.latitude)) * (Math.sin(t / 2) * Math.sin(t / 2));
|
|
253
|
+
return 2 * Math.atan2(Math.sqrt(d), Math.sqrt(1 - d)) * 6371e3;
|
|
215
254
|
}
|
|
216
255
|
}
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
c !== void 0 && (t.position.y = c), [t.position.x, t.position.z] = d;
|
|
220
|
-
}, Y = function(t, i) {
|
|
221
|
-
l(this, y, n(this, x).project(t, i));
|
|
222
|
-
}, W = function(t) {
|
|
223
|
-
var e, c, d;
|
|
224
|
-
let i = Number.MAX_VALUE;
|
|
225
|
-
k(this, D)._++, (e = n(this, M)) == null || e.sendData("/gps/new", {
|
|
226
|
-
gpsCount: n(this, D),
|
|
227
|
-
lat: t.coords.latitude,
|
|
228
|
-
lon: t.coords.longitude,
|
|
229
|
-
acc: t.coords.accuracy,
|
|
230
|
-
session: n(this, T)
|
|
231
|
-
}), t.coords.accuracy <= n(this, L) && (n(this, P) === null ? l(this, P, {
|
|
232
|
-
latitude: t.coords.latitude,
|
|
233
|
-
longitude: t.coords.longitude
|
|
234
|
-
}) : i = p(this, f, Z).call(this, n(this, P), t.coords), i >= n(this, H) && (n(this, P).longitude = t.coords.longitude, n(this, P).latitude = t.coords.latitude, n(this, y) || (p(this, f, Y).call(this, t.coords.longitude, t.coords.latitude), (c = n(this, M)) == null || c.sendData("/worldorigin/new", {
|
|
235
|
-
gpsCount: n(this, D),
|
|
236
|
-
lat: t.coords.latitude,
|
|
237
|
-
lon: t.coords.longitude,
|
|
238
|
-
session: n(this, T),
|
|
239
|
-
initialPosition: n(this, y)
|
|
240
|
-
})), p(this, f, j).call(this, this.camera, t.coords.longitude, t.coords.latitude), (d = n(this, M)) == null || d.sendData("/gps/accepted", {
|
|
241
|
-
gpsCount: n(this, D),
|
|
242
|
-
cameraX: this.camera.position.x,
|
|
243
|
-
cameraZ: this.camera.position.z,
|
|
244
|
-
session: n(this, T),
|
|
245
|
-
distMoved: i
|
|
246
|
-
}), n(this, O).gpsupdate && n(this, O).gpsupdate(t, i)));
|
|
247
|
-
}, /**
|
|
248
|
-
* Calculate haversine distance between two lat/lon pairs.
|
|
249
|
-
*
|
|
250
|
-
* Taken from original A-Frame AR.js location-based components
|
|
251
|
-
*/
|
|
252
|
-
Z = function(t, i) {
|
|
253
|
-
const e = b.MathUtils.degToRad(i.longitude - t.longitude), c = b.MathUtils.degToRad(i.latitude - t.latitude), d = Math.sin(c / 2) * Math.sin(c / 2) + Math.cos(b.MathUtils.degToRad(t.latitude)) * Math.cos(b.MathUtils.degToRad(i.latitude)) * (Math.sin(e / 2) * Math.sin(e / 2));
|
|
254
|
-
return 2 * Math.atan2(Math.sqrt(d), Math.sqrt(1 - d)) * 6371e3;
|
|
255
|
-
};
|
|
256
|
-
class at {
|
|
256
|
+
class H extends P {
|
|
257
|
+
#t;
|
|
257
258
|
/**
|
|
258
259
|
* Create a Webcam.
|
|
259
|
-
* @param
|
|
260
|
-
*
|
|
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
|
+
* @param constraints {Object} - options to use for initialising the camera.
|
|
261
|
+
* The same constraints object as used by standard MediaDevices API.
|
|
265
262
|
* @param {string} videoElementSelector - selector to obtain the HTML video
|
|
266
263
|
* element to render the webcam feed. If a falsy value (e.g. null or
|
|
267
264
|
* undefined), a video element will be created.
|
|
268
265
|
*/
|
|
269
|
-
constructor(
|
|
270
|
-
this.sceneWebcam = new
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
}
|
|
279
|
-
};
|
|
280
|
-
navigator.mediaDevices.getUserMedia(c).then((d) => {
|
|
281
|
-
e.addEventListener("loadedmetadata", () => {
|
|
282
|
-
var g;
|
|
283
|
-
e.setAttribute("width", e.videoWidth), e.setAttribute("height", e.videoHeight), e.play(), (g = t.onVideoStarted) == null || g.call(this, this.texture);
|
|
284
|
-
}), e.srcObject = d;
|
|
285
|
-
}).catch((d) => {
|
|
286
|
-
setTimeout(() => {
|
|
287
|
-
alert(
|
|
288
|
-
`Webcam Error
|
|
289
|
-
Name: ` + d.name + `
|
|
290
|
-
Message: ` + d.message
|
|
291
|
-
);
|
|
292
|
-
}, 1e3);
|
|
266
|
+
constructor(e = { video: { facingMode: "environment" } }, i) {
|
|
267
|
+
super(), this.sceneWebcam = new f.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 f.VideoTexture(this.#t), navigator.mediaDevices && navigator.mediaDevices.getUserMedia ? navigator.mediaDevices.getUserMedia(e).then((t) => {
|
|
268
|
+
this.#t.addEventListener("loadedmetadata", () => {
|
|
269
|
+
this.#t.setAttribute("width", this.#t.videoWidth), this.#t.setAttribute("height", this.#t.videoHeight), this.#t.play(), this.emit("webcamstarted", { texture: this.texture });
|
|
270
|
+
}), this.#t.srcObject = t;
|
|
271
|
+
}).catch((t) => {
|
|
272
|
+
this.emit("webcamerror", {
|
|
273
|
+
code: t.name,
|
|
274
|
+
message: t.message
|
|
293
275
|
});
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
276
|
+
}) : this.emit("webcamerror", {
|
|
277
|
+
code: "LOCAR_NO_MEDIA_DEVICES_API",
|
|
278
|
+
message: "Media devices API not supported"
|
|
279
|
+
});
|
|
298
280
|
}
|
|
299
281
|
/**
|
|
300
282
|
* Free up the memory associated with the webcam.
|
|
@@ -304,203 +286,224 @@ Message: ` + d.message
|
|
|
304
286
|
this.texture.dispose();
|
|
305
287
|
}
|
|
306
288
|
}
|
|
307
|
-
const
|
|
308
|
-
class
|
|
289
|
+
const E = navigator.userAgent.match(/iPhone|iPad|iPod/i) || /Macintosh/i.test(navigator.userAgent) && navigator.maxTouchPoints != null && navigator.maxTouchPoints > 1, _ = new I(0, 0, 1), y = new A(), R = new w(), D = new w(-Math.sqrt(0.5), 0, 0, Math.sqrt(0.5));
|
|
290
|
+
class x extends C {
|
|
309
291
|
/**
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
constructor(
|
|
316
|
-
super(),
|
|
317
|
-
|
|
318
|
-
);
|
|
319
|
-
const
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
alpha: s,
|
|
323
|
-
beta: o,
|
|
292
|
+
* Create an instance of DeviceOrientationControls.
|
|
293
|
+
* @param {Object} object - the object to attach the controls to
|
|
294
|
+
* (usually your Three.js camera)
|
|
295
|
+
* @param {Object} options - options for DeviceOrientationControls: currently accepts smoothingFactor, enablePermissionDialog
|
|
296
|
+
*/
|
|
297
|
+
constructor(e, i = {}) {
|
|
298
|
+
super(), this.eventEmitter = new P();
|
|
299
|
+
const t = this;
|
|
300
|
+
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", console.log("Device Orientation Event Name:", this.orientationChangeEventName), this.smoothingFactor = i.smoothingFactor || 1, this.enablePermissionDialog = i.enablePermissionDialog ?? !0;
|
|
301
|
+
const c = function({
|
|
302
|
+
alpha: n,
|
|
303
|
+
beta: s,
|
|
324
304
|
gamma: a,
|
|
325
|
-
webkitCompassHeading:
|
|
305
|
+
webkitCompassHeading: r
|
|
326
306
|
}) {
|
|
327
|
-
if (
|
|
328
|
-
const
|
|
329
|
-
|
|
307
|
+
if (E) {
|
|
308
|
+
const o = 360 - r;
|
|
309
|
+
t.alphaOffset = m.degToRad(o - n), t.deviceOrientation = { alpha: n, beta: s, gamma: a, webkitCompassHeading: r };
|
|
330
310
|
} else
|
|
331
|
-
|
|
311
|
+
n < 0 && (n += 360), t.deviceOrientation = { alpha: n, beta: s, gamma: a };
|
|
332
312
|
window.dispatchEvent(
|
|
333
313
|
new CustomEvent("camera-rotation-change", {
|
|
334
|
-
detail: { cameraRotation:
|
|
314
|
+
detail: { cameraRotation: e.rotation }
|
|
335
315
|
})
|
|
336
316
|
);
|
|
337
|
-
},
|
|
338
|
-
|
|
339
|
-
},
|
|
340
|
-
|
|
317
|
+
}, d = function() {
|
|
318
|
+
t.screenOrientation = window.orientation || 0, E && (t.screenOrientation === 90 ? t.orientationOffset = -t.HALF_PI : t.screenOrientation === -90 ? t.orientationOffset = t.HALF_PI : t.orientationOffset = 0);
|
|
319
|
+
}, M = function(n, s, a, r, o) {
|
|
320
|
+
y.set(a, s, -r, "YXZ"), n.setFromEuler(y), n.multiply(D), n.multiply(R.setFromAxisAngle(_, -o));
|
|
341
321
|
};
|
|
342
322
|
this.connect = function() {
|
|
343
|
-
|
|
344
|
-
s === "granted" && (window.addEventListener(
|
|
345
|
-
"orientationchange",
|
|
346
|
-
I
|
|
347
|
-
), window.addEventListener(
|
|
348
|
-
e.orientationChangeEventName,
|
|
349
|
-
g
|
|
350
|
-
));
|
|
351
|
-
}).catch(function(s) {
|
|
352
|
-
console.error(
|
|
353
|
-
"THREE.DeviceOrientationControls: Unable to use DeviceOrientation API:",
|
|
354
|
-
s
|
|
355
|
-
);
|
|
356
|
-
}) : (window.addEventListener(
|
|
323
|
+
d(), window.addEventListener(
|
|
357
324
|
"orientationchange",
|
|
358
|
-
|
|
325
|
+
d
|
|
359
326
|
), window.addEventListener(
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
)
|
|
327
|
+
t.orientationChangeEventName,
|
|
328
|
+
c
|
|
329
|
+
), t.enabled = !0;
|
|
363
330
|
}, this.disconnect = function() {
|
|
364
331
|
window.removeEventListener(
|
|
365
332
|
"orientationchange",
|
|
366
|
-
|
|
333
|
+
d
|
|
367
334
|
), window.removeEventListener(
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
),
|
|
371
|
-
}, this.
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
335
|
+
t.orientationChangeEventName,
|
|
336
|
+
c
|
|
337
|
+
), t.enabled = !1, t.initialOffset = !1, t.deviceOrientation = null;
|
|
338
|
+
}, this.requestOrientationPermissions = function() {
|
|
339
|
+
window.DeviceOrientationEvent !== void 0 && typeof window.DeviceOrientationEvent.requestPermission == "function" ? window.DeviceOrientationEvent.requestPermission().then((n) => {
|
|
340
|
+
n === "granted" ? this.eventEmitter.emit("deviceorientationgranted", {
|
|
341
|
+
target: this
|
|
342
|
+
}) : this.eventEmitter.emit("deviceorientationerror", {
|
|
343
|
+
code: "LOCAR_DEVICE_ORIENTATION_PERMISSION_DENIED",
|
|
344
|
+
message: "Permission for device orientation denied - AR will not work correctly"
|
|
345
|
+
});
|
|
346
|
+
}).catch(function(n) {
|
|
347
|
+
this.eventEmitter.emit("deviceorientationerror", {
|
|
348
|
+
code: "LOCAR_DEVICE_ORIENTATION_PERMISSION_FAILED",
|
|
349
|
+
message: "Permission request for device orientation failed - AR will not work correctly"
|
|
350
|
+
});
|
|
351
|
+
}) : this.eventEmitter.emit("deviceorientationerror", {
|
|
352
|
+
code: "LOCAR_DEVICE_ORIENTATION_INTERNAL_ERROR",
|
|
353
|
+
message: "Internal error: no requestPermission() found although requestOrientationPermissions() was called - please raise an issue on GitHub"
|
|
354
|
+
});
|
|
355
|
+
}, this.update = function({ theta: n = 0 } = { theta: 0 }) {
|
|
356
|
+
if (t.enabled === !1) return;
|
|
357
|
+
const s = t.deviceOrientation;
|
|
358
|
+
if (s) {
|
|
359
|
+
let a = s.alpha ? m.degToRad(s.alpha) + t.alphaOffset : 0, r = s.beta ? m.degToRad(s.beta) : 0, o = s.gamma ? m.degToRad(s.gamma) : 0;
|
|
360
|
+
const g = t.screenOrientation ? m.degToRad(t.screenOrientation) : 0;
|
|
361
|
+
if (t.smoothingFactor < 1) {
|
|
362
|
+
if (t.lastOrientation) {
|
|
363
|
+
const h = t.smoothingFactor;
|
|
364
|
+
a = t._getSmoothedAngle(
|
|
365
|
+
a,
|
|
366
|
+
t.lastOrientation.alpha,
|
|
367
|
+
h
|
|
368
|
+
), r = t._getSmoothedAngle(
|
|
369
|
+
r + Math.PI,
|
|
370
|
+
t.lastOrientation.beta,
|
|
371
|
+
h
|
|
372
|
+
), o = t._getSmoothedAngle(
|
|
373
|
+
o + t.HALF_PI,
|
|
374
|
+
t.lastOrientation.gamma,
|
|
375
|
+
h,
|
|
376
|
+
Math.PI
|
|
377
|
+
);
|
|
378
|
+
} else
|
|
379
|
+
r += Math.PI, o += t.HALF_PI;
|
|
380
|
+
t.lastOrientation = {
|
|
381
|
+
alpha: a,
|
|
382
|
+
beta: r,
|
|
383
|
+
gamma: o
|
|
384
|
+
};
|
|
385
|
+
}
|
|
386
|
+
if (E) {
|
|
387
|
+
const h = new w();
|
|
388
|
+
M(
|
|
389
|
+
h,
|
|
390
|
+
a,
|
|
391
|
+
t.smoothingFactor < 1 ? r - Math.PI : r,
|
|
392
|
+
t.smoothingFactor < 1 ? o - Math.PI / 2 : o,
|
|
393
|
+
g
|
|
394
|
+
);
|
|
395
|
+
const u = new A().setFromQuaternion(
|
|
396
|
+
h,
|
|
382
397
|
"YXZ"
|
|
383
398
|
);
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
this.lastOrientation.alpha,
|
|
394
|
-
v
|
|
395
|
-
), u = this._getSmoothedAngle(
|
|
396
|
-
u + Math.PI,
|
|
397
|
-
this.lastOrientation.beta,
|
|
398
|
-
v
|
|
399
|
-
), h = this._getSmoothedAngle(
|
|
400
|
-
h + this.HALF_PI,
|
|
401
|
-
this.lastOrientation.gamma,
|
|
402
|
-
v,
|
|
403
|
-
Math.PI
|
|
404
|
-
);
|
|
405
|
-
} else
|
|
406
|
-
u += Math.PI, h += this.HALF_PI;
|
|
407
|
-
this.lastOrientation = {
|
|
408
|
-
alpha: a,
|
|
409
|
-
beta: u,
|
|
410
|
-
gamma: h
|
|
411
|
-
};
|
|
412
|
-
}
|
|
413
|
-
R(
|
|
414
|
-
e.object.quaternion,
|
|
415
|
-
a + s,
|
|
416
|
-
this.smoothingFactor < 1 ? u - Math.PI : u,
|
|
417
|
-
this.smoothingFactor < 1 ? h - this.HALF_PI : h,
|
|
418
|
-
_
|
|
399
|
+
let v = m.degToRad(360 - s.webkitCompassHeading);
|
|
400
|
+
t.smoothingFactor < 1 && t.lastCompassY !== void 0 && (v = t._getSmoothedAngle(v, t.lastCompassY, t.smoothingFactor)), t.lastCompassY = v, u.y = v + (t.orientationOffset || 0), h.setFromEuler(u), t.object.quaternion.copy(h);
|
|
401
|
+
} else
|
|
402
|
+
M(
|
|
403
|
+
t.object.quaternion,
|
|
404
|
+
E ? a + t.alphaOffset : a,
|
|
405
|
+
t.smoothingFactor < 1 ? r - Math.PI : r,
|
|
406
|
+
t.smoothingFactor < 1 ? o - Math.PI / 2 : o,
|
|
407
|
+
g
|
|
419
408
|
);
|
|
420
|
-
}
|
|
421
|
-
8 * (1 - d.dot(e.object.quaternion)) > c && (d.copy(e.object.quaternion), e.dispatchEvent(it));
|
|
422
409
|
}
|
|
423
|
-
}, this.
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
return
|
|
410
|
+
}, this.getCorrectedHeading = function() {
|
|
411
|
+
const { deviceOrientation: n } = t;
|
|
412
|
+
if (!n) return 0;
|
|
413
|
+
let s = 0;
|
|
414
|
+
return E ? (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;
|
|
415
|
+
}, this._orderAngle = function(n, s, a = t.TWO_PI) {
|
|
416
|
+
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 };
|
|
417
|
+
}, this._getSmoothedAngle = function(n, s, a, r = t.TWO_PI) {
|
|
418
|
+
const o = t._orderAngle(n, s, r), g = o.left, h = o.right;
|
|
419
|
+
o.left = 0, o.right -= g, o.right < 0 && (o.right += r);
|
|
420
|
+
let u = h == s ? (1 - a) * o.right + a * o.left : a * o.right + (1 - a) * o.left;
|
|
421
|
+
return u += g, u >= r && (u -= r), u;
|
|
430
422
|
}, this.updateAlphaOffset = function() {
|
|
431
|
-
|
|
423
|
+
t.initialOffset = !1;
|
|
432
424
|
}, this.dispose = function() {
|
|
433
|
-
|
|
425
|
+
t.disconnect();
|
|
434
426
|
}, this.getAlpha = function() {
|
|
435
|
-
const { deviceOrientation:
|
|
436
|
-
return
|
|
427
|
+
const { deviceOrientation: n } = t;
|
|
428
|
+
return n && n.alpha ? m.degToRad(n.alpha) + t.alphaOffset : 0;
|
|
437
429
|
}, this.getBeta = function() {
|
|
438
|
-
const { deviceOrientation:
|
|
439
|
-
return
|
|
440
|
-
},
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
430
|
+
const { deviceOrientation: n } = t;
|
|
431
|
+
return n && n.beta ? m.degToRad(n.beta) : 0;
|
|
432
|
+
}, this.getGamma = function() {
|
|
433
|
+
const { deviceOrientation: n } = t;
|
|
434
|
+
return n && n.gamma ? m.degToRad(n.gamma) : 0;
|
|
435
|
+
}, this.obtainPermissionGesture = function() {
|
|
436
|
+
const n = document.createElement("div"), s = document.createElement("div"), a = document.createElement("div"), r = document.createElement("div");
|
|
437
|
+
document.body.appendChild(n);
|
|
438
|
+
const o = {
|
|
439
|
+
display: "flex",
|
|
440
|
+
position: "fixed",
|
|
441
|
+
top: 0,
|
|
442
|
+
left: 0,
|
|
443
|
+
width: "100%",
|
|
444
|
+
height: "100%",
|
|
445
|
+
zIndex: 1,
|
|
446
|
+
backgroundColor: "rgba(0,0,0,0.6)",
|
|
447
|
+
justifyContent: "center",
|
|
448
|
+
alignItems: "center"
|
|
449
|
+
}, g = {
|
|
450
|
+
backgroundColor: "white",
|
|
451
|
+
padding: "6px",
|
|
452
|
+
borderRadius: "3px",
|
|
453
|
+
width: "36rem",
|
|
454
|
+
height: "24rem"
|
|
455
|
+
}, h = {
|
|
456
|
+
width: "100%",
|
|
457
|
+
height: "70%",
|
|
458
|
+
display: "flex",
|
|
459
|
+
justifyContent: "center",
|
|
460
|
+
alignItems: "center"
|
|
461
|
+
}, u = {
|
|
462
|
+
display: "inline-flex",
|
|
463
|
+
width: "100%",
|
|
464
|
+
height: "30%",
|
|
465
|
+
justifyContent: "center",
|
|
466
|
+
alignItems: "center"
|
|
467
|
+
};
|
|
468
|
+
for (let l in o)
|
|
469
|
+
n.style[l] = o[l];
|
|
470
|
+
for (let l in g)
|
|
471
|
+
s.style[l] = g[l];
|
|
472
|
+
for (let l in h)
|
|
473
|
+
a.style[l] = h[l];
|
|
474
|
+
for (let l in u)
|
|
475
|
+
r.style[l] = u[l];
|
|
476
|
+
n.appendChild(s), s.appendChild(a), s.appendChild(r), a.innerHTML = '<div style="font-size: 24pt; margin: 1rem;">This immersive website requires access to your device motion sensors.</div>';
|
|
477
|
+
const v = () => {
|
|
478
|
+
this.requestOrientationPermissions(), n.style.display = "none";
|
|
479
|
+
}, p = document.createElement("button");
|
|
480
|
+
p.addEventListener("click", v), p.style.width = "50%", p.style.height = "80%", p.style.fontSize = "20pt", p.appendChild(document.createTextNode("OK")), r.appendChild(p), document.body.appendChild(n);
|
|
477
481
|
};
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
}
|
|
490
|
-
o.addEventListener("click", s), o.style.width = "50%", o.style.height = "80%", o.style.fontSize = "20pt", o.appendChild(document.createTextNode("OK")), c.appendChild(o), document.body.appendChild(t);
|
|
482
|
+
}
|
|
483
|
+
on(e, i) {
|
|
484
|
+
this.eventEmitter.on(e, i);
|
|
485
|
+
}
|
|
486
|
+
init() {
|
|
487
|
+
window.DeviceOrientationEvent === void 0 ? this.eventEmitter.emit("deviceorientationerror", {
|
|
488
|
+
code: "LOCAR_DEVICE_ORIENTATION_NOT_SUPPORTED",
|
|
489
|
+
message: "Device orientation API not supported"
|
|
490
|
+
}) : window.isSecureContext === !1 ? this.eventEmitter.emit("deviceorientationerror", {
|
|
491
|
+
code: "LOCAR_DEVICE_ORIENTATION_NO_HTTPS",
|
|
492
|
+
message: "DeviceOrientationEvent is only available in secure contexts (https)"
|
|
493
|
+
}) : typeof window.DeviceOrientationEvent.requestPermission == "function" && this.enablePermissionDialog ? this.obtainPermissionGesture() : this.eventEmitter.emit("deviceorientationgranted", { target: this });
|
|
491
494
|
}
|
|
492
495
|
}
|
|
493
|
-
class
|
|
496
|
+
class N {
|
|
494
497
|
/**
|
|
495
498
|
* Create a ClickHandler.
|
|
496
499
|
* @param {THREE.WebGLRenderer} - The Three.js renderer on which the click
|
|
497
500
|
* events will be handled.
|
|
498
501
|
*/
|
|
499
|
-
constructor(
|
|
500
|
-
this.raycaster = new
|
|
502
|
+
constructor(e) {
|
|
503
|
+
this.raycaster = new f.Raycaster(), this.normalisedMousePosition = new f.Vector2(null, null), e.domElement.addEventListener("click", (i) => {
|
|
501
504
|
this.normalisedMousePosition.set(
|
|
502
|
-
i.clientX /
|
|
503
|
-
-(i.clientY /
|
|
505
|
+
i.clientX / e.domElement.clientWidth * 2 - 1,
|
|
506
|
+
-(i.clientY / e.domElement.clientHeight * 2) + 1
|
|
504
507
|
);
|
|
505
508
|
});
|
|
506
509
|
}
|
|
@@ -512,21 +515,22 @@ class ct {
|
|
|
512
515
|
* cast into.
|
|
513
516
|
* @return {Array} - array of all intersected objects.
|
|
514
517
|
*/
|
|
515
|
-
raycast(
|
|
518
|
+
raycast(e, i) {
|
|
516
519
|
if (this.normalisedMousePosition.x !== null && this.normalisedMousePosition.y !== null) {
|
|
517
|
-
this.raycaster.setFromCamera(this.normalisedMousePosition,
|
|
518
|
-
const
|
|
519
|
-
return this.normalisedMousePosition.set(null, null),
|
|
520
|
+
this.raycaster.setFromCamera(this.normalisedMousePosition, e);
|
|
521
|
+
const t = this.raycaster.intersectObjects(i.children, !1);
|
|
522
|
+
return this.normalisedMousePosition.set(null, null), t;
|
|
520
523
|
}
|
|
521
524
|
return [];
|
|
522
525
|
}
|
|
523
526
|
}
|
|
524
|
-
const
|
|
527
|
+
const S = "0.1.0";
|
|
525
528
|
export {
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
529
|
+
N as ClickHandler,
|
|
530
|
+
x as DeviceOrientationControls,
|
|
531
|
+
P as EventEmitter,
|
|
532
|
+
L as LocationBased,
|
|
533
|
+
T as SphMercProjection,
|
|
534
|
+
H as Webcam,
|
|
535
|
+
S as version
|
|
532
536
|
};
|
package/dist/locar.umd.js
CHANGED
|
@@ -1,3 +1 @@
|
|
|
1
|
-
(function(a,n){typeof exports=="object"&&typeof module<"u"?n(exports,require("three")):typeof define=="function"&&define.amd?define(["exports","three"],n):(a=typeof globalThis<"u"?globalThis:a||self,n(a.locar={},a.THREE))})(this,function(a,n){"use strict";var N=a=>{throw TypeError(a)};var q=(a,n,f)=>n.has(a)||N("Cannot "+f);var s=(a,n,f)=>(q(a,n,"read from private field"),f?f.call(a):n.get(a)),v=(a,n,f)=>n.has(a)?N("Cannot add the same private member more than once"):n instanceof WeakSet?n.add(a):n.set(a,f),u=(a,n,f,m)=>(q(a,n,"write to private field"),m?m.call(a,f):n.set(a,f),f),y=(a,n,f)=>(q(a,n,"access private method"),f);var Q=(a,n,f,m)=>({set _(W){u(a,n,W,f)},get _(){return s(a,n,m)}});var w,G,X,V,Y,E,D,I,S,j,L,O,_,T,P,M,H,Z,k,B;function f(b){const t=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(b){for(const i in b)if(i!=="default"){const e=Object.getOwnPropertyDescriptor(b,i);Object.defineProperty(t,i,e.get?e:{enumerable:!0,get:()=>b[i]})}}return t.default=b,Object.freeze(t)}const m=f(n);class W{constructor(){v(this,w);this.EARTH=4007501668e-2,this.HALF_EARTH=2003750834e-2}project(t,i){return[y(this,w,G).call(this,t),y(this,w,X).call(this,i)]}unproject(t){return[y(this,w,V).call(this,t[0]),y(this,w,Y).call(this,t[1])]}getID(){return"epsg:3857"}}w=new WeakSet,G=function(t){return t/180*this.HALF_EARTH},X=function(t){var i=Math.log(Math.tan((90+t)*Math.PI/360))/(Math.PI/180);return i*this.HALF_EARTH/180},V=function(t){return t/this.HALF_EARTH*180},Y=function(t){var i=t/this.HALF_EARTH*180;return i=180/Math.PI*(2*Math.atan(Math.exp(i*Math.PI/180))-Math.PI/2),i};class K{constructor(t,i,e={},l=null){v(this,M);v(this,E);v(this,D);v(this,I);v(this,S);v(this,j);v(this,L);v(this,O);v(this,_);v(this,T);v(this,P);this.scene=t,this.camera=i,u(this,E,new W),u(this,D,{}),u(this,I,null),u(this,S,0),u(this,j,100),u(this,L,null),this.setGpsOptions(e),u(this,O,null),u(this,_,0),u(this,T,0),u(this,P,l)}setProjection(t){u(this,E,t)}setGpsOptions(t={}){t.gpsMinDistance!==void 0&&u(this,S,t.gpsMinDistance),t.gpsMinAccuracy!==void 0&&u(this,j,t.gpsMinAccuracy)}async startGps(){if(s(this,P)){const i=await(await s(this,P).sendData("/gps/start",{gpsMinDistance:s(this,S),gpsMinAccuracy:s(this,j)})).json();u(this,T,i.session)}return s(this,L)===null?(u(this,L,navigator.geolocation.watchPosition(t=>{y(this,M,k).call(this,t)},t=>{s(this,D).gpserror?s(this,D).gpserror(t.code):alert(`GPS error: code ${t.code}`)},{enableHighAccuracy:!0})),!0):!1}stopGps(){return s(this,L)!==null?(navigator.geolocation.clearWatch(s(this,L)),u(this,L,null),!0):!1}fakeGps(t,i,e=null,l=0){e!==null&&this.setElevation(e),y(this,M,k).call(this,{coords:{longitude:t,latitude:i,accuracy:l}})}lonLatToWorldCoords(t,i){const e=s(this,E).project(t,i);if(s(this,O))e[0]-=s(this,O)[0],e[1]-=s(this,O)[1];else throw"No initial position determined";return[e[0],-e[1]]}add(t,i,e,l,h={}){var p;t.properties=h,y(this,M,H).call(this,t,i,e,l),this.scene.add(t),(p=s(this,P))==null||p.sendData("/object/new",{position:t.position,x:t.position.x,z:t.position.z,session:s(this,T),properties:h})}setElevation(t){this.camera.position.y=t}on(t,i){s(this,D)[t]=i}}E=new WeakMap,D=new WeakMap,I=new WeakMap,S=new WeakMap,j=new WeakMap,L=new WeakMap,O=new WeakMap,_=new WeakMap,T=new WeakMap,P=new WeakMap,M=new WeakSet,H=function(t,i,e,l){const h=this.lonLatToWorldCoords(i,e);l!==void 0&&(t.position.y=l),[t.position.x,t.position.z]=h},Z=function(t,i){u(this,O,s(this,E).project(t,i))},k=function(t){var e,l,h;let i=Number.MAX_VALUE;Q(this,_)._++,(e=s(this,P))==null||e.sendData("/gps/new",{gpsCount:s(this,_),lat:t.coords.latitude,lon:t.coords.longitude,acc:t.coords.accuracy,session:s(this,T)}),t.coords.accuracy<=s(this,j)&&(s(this,I)===null?u(this,I,{latitude:t.coords.latitude,longitude:t.coords.longitude}):i=y(this,M,B).call(this,s(this,I),t.coords),i>=s(this,S)&&(s(this,I).longitude=t.coords.longitude,s(this,I).latitude=t.coords.latitude,s(this,O)||(y(this,M,Z).call(this,t.coords.longitude,t.coords.latitude),(l=s(this,P))==null||l.sendData("/worldorigin/new",{gpsCount:s(this,_),lat:t.coords.latitude,lon:t.coords.longitude,session:s(this,T),initialPosition:s(this,O)})),y(this,M,H).call(this,this.camera,t.coords.longitude,t.coords.latitude),(h=s(this,P))==null||h.sendData("/gps/accepted",{gpsCount:s(this,_),cameraX:this.camera.position.x,cameraZ:this.camera.position.z,session:s(this,T),distMoved:i}),s(this,D).gpsupdate&&s(this,D).gpsupdate(t,i)))},B=function(t,i){const e=m.MathUtils.degToRad(i.longitude-t.longitude),l=m.MathUtils.degToRad(i.latitude-t.latitude),h=Math.sin(l/2)*Math.sin(l/2)+Math.cos(m.MathUtils.degToRad(t.latitude))*Math.cos(m.MathUtils.degToRad(i.latitude))*(Math.sin(e/2)*Math.sin(e/2));return 2*Math.atan2(Math.sqrt(h),Math.sqrt(1-h))*6371e3};class ${constructor(t={},i){this.sceneWebcam=new m.Scene;let e;if(i?e=document.querySelector(i):(e=document.createElement("video"),e.setAttribute("autoplay",!0),e.setAttribute("playsinline",!0),e.style.display="none",document.body.appendChild(e)),this.texture=new m.VideoTexture(e),navigator.mediaDevices&&navigator.mediaDevices.getUserMedia){const l={video:{width:{ideal:t.idealWidth||1280},height:{ideal:t.idealHeight||720},facingMode:"environment"}};navigator.mediaDevices.getUserMedia(l).then(h=>{e.addEventListener("loadedmetadata",()=>{var p;e.setAttribute("width",e.videoWidth),e.setAttribute("height",e.videoHeight),e.play(),(p=t.onVideoStarted)==null||p.call(this,this.texture)}),e.srcObject=h}).catch(h=>{setTimeout(()=>{alert(`Webcam Error
|
|
2
|
-
Name: `+h.name+`
|
|
3
|
-
Message: `+h.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),z=new n.Euler,tt=new n.Quaternion,et=new n.Quaternion(-Math.sqrt(.5),0,0,Math.sqrt(.5)),it={type:"change"};class nt extends n.EventDispatcher{constructor(t,i={}){super(),window.isSecureContext===!1&&console.error("THREE.DeviceOrientationControls: DeviceOrientationEvent is only available in secure contexts (https)");const e=this,l=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=i.smoothingFactor||1;const p=function({alpha:o,beta:r,gamma:c,webkitCompassHeading:g}){if(R){const d=360-g;e.alphaOffset=n.MathUtils.degToRad(d-o),e.deviceOrientation={alpha:o,beta:r,gamma:c,webkitCompassHeading:g}}else o<0&&(o+=360),e.deviceOrientation={alpha:o,beta:r,gamma:c};window.dispatchEvent(new CustomEvent("camera-rotation-change",{detail:{cameraRotation:t.rotation}}))},x=function(){e.screenOrientation=window.orientation||0},F=function(o,r,c,g,d){z.set(c,r,-g,"YXZ"),o.setFromEuler(z),o.multiply(et),o.multiply(tt.setFromAxisAngle(J,-d))};this.connect=function(){x(),window.DeviceOrientationEvent!==void 0&&typeof window.DeviceOrientationEvent.requestPermission=="function"?window.DeviceOrientationEvent.requestPermission().then(o=>{o==="granted"&&(window.addEventListener("orientationchange",x),window.addEventListener(e.orientationChangeEventName,p))}).catch(function(o){console.error("THREE.DeviceOrientationControls: Unable to use DeviceOrientation API:",o)}):(window.addEventListener("orientationchange",x),window.addEventListener(e.orientationChangeEventName,p)),e.enabled=!0},this.disconnect=function(){window.removeEventListener("orientationchange",x),window.removeEventListener(e.orientationChangeEventName,p),e.enabled=!1,e.initialOffset=!1,e.deviceOrientation=null},this.update=function({theta:o=0}={theta:0}){if(e.enabled===!1)return;const r=e.deviceOrientation;if(r){let c=r.alpha?n.MathUtils.degToRad(r.alpha)+e.alphaOffset:0,g=r.beta?n.MathUtils.degToRad(r.beta):0,d=r.gamma?n.MathUtils.degToRad(r.gamma):0;const U=e.screenOrientation?n.MathUtils.degToRad(e.screenOrientation):0;if(R){const A=new n.Quaternion;F(A,c,g,d,U);const C=new n.Euler().setFromQuaternion(A,"YXZ");console.log(C.x,C.y,C.z),C.y=n.MathUtils.degToRad(360-r.webkitCompassHeading),A.setFromEuler(C),e.object.quaternion.copy(A)}else{if(this.smoothingFactor<1){if(this.lastOrientation){const A=this.smoothingFactor;c=this._getSmoothedAngle(c,this.lastOrientation.alpha,A),g=this._getSmoothedAngle(g+Math.PI,this.lastOrientation.beta,A),d=this._getSmoothedAngle(d+this.HALF_PI,this.lastOrientation.gamma,A,Math.PI)}else g+=Math.PI,d+=this.HALF_PI;this.lastOrientation={alpha:c,beta:g,gamma:d}}F(e.object.quaternion,c+o,this.smoothingFactor<1?g-Math.PI:g,this.smoothingFactor<1?d-this.HALF_PI:d,U)}8*(1-h.dot(e.object.quaternion))>l&&(h.copy(e.object.quaternion),e.dispatchEvent(it))}},this._orderAngle=function(o,r,c=this.TWO_PI){return r>o&&Math.abs(r-o)<c/2||o>r&&Math.abs(r-o)>c/2?{left:o,right:r}:{left:r,right:o}},this._getSmoothedAngle=function(o,r,c,g=this.TWO_PI){const d=this._orderAngle(o,r,g),U=d.left,A=d.right;d.left=0,d.right-=U,d.right<0&&(d.right+=g);let C=A==r?(1-c)*d.right+c*d.left:c*d.right+(1-c)*d.left;return C+=U,C>=g&&(C-=g),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"),i=document.createElement("div"),e=document.createElement("div"),l=document.createElement("div");document.body.appendChild(t);const h={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"},x={width:"100%",height:"70%",display:"flex",justifyContent:"center",alignItems:"center"},F={display:"inline-flex",width:"100%",height:"30%",justifyContent:"center",alignItems:"center"};for(let c in h)t.style[c]=h[c];for(let c in p)i.style[c]=p[c];for(let c in x)e.style[c]=x[c];for(let c in F)l.style[c]=F[c];t.appendChild(i),i.appendChild(e),i.appendChild(l),e.innerHTML='<div style="font-size: 24pt; margin: 1rem;">This immersive website requires access to your device motion sensors.</div>';const o=()=>{this.connect(),t.style.display="none"},r=document.createElement("button");r.addEventListener("click",o),r.style.width="50%",r.style.height="80%",r.style.fontSize="20pt",r.appendChild(document.createTextNode("OK")),l.appendChild(r),document.body.appendChild(t)}}class st{constructor(t){this.raycaster=new m.Raycaster,this.normalisedMousePosition=new m.Vector2(null,null),t.domElement.addEventListener("click",i=>{this.normalisedMousePosition.set(i.clientX/t.domElement.clientWidth*2-1,-(i.clientY/t.domElement.clientHeight*2)+1)})}raycast(t,i){if(this.normalisedMousePosition.x!==null&&this.normalisedMousePosition.y!==null){this.raycaster.setFromCamera(this.normalisedMousePosition,t);const e=this.raycaster.intersectObjects(i.children,!1);return this.normalisedMousePosition.set(null,null),e}return[]}}const ot="0.0.10-noaframe-1";a.ClickHandler=st,a.DeviceOrientationControls=nt,a.LocationBased=K,a.SphMercProjection=W,a.Webcam=$,a.version=ot,Object.defineProperty(a,Symbol.toStringTag,{value:"Module"})});
|
|
1
|
+
(function(d,c){typeof exports=="object"&&typeof module<"u"?c(exports,require("three")):typeof define=="function"&&define.amd?define(["exports","three"],c):(d=typeof globalThis<"u"?globalThis:d||self,c(d.locar={},d.THREE))})(this,(function(d,c){"use strict";function E(u){const t=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(u){for(const i in u)if(i!=="default"){const e=Object.getOwnPropertyDescriptor(u,i);Object.defineProperty(t,i,e.get?e:{enumerable:!0,get:()=>u[i]})}}return t.default=u,Object.freeze(t)}const v=E(c);class A{constructor(){this.EARTH=4007501668e-2,this.HALF_EARTH=2003750834e-2}project(t,i){return[this.#t(t),this.#l(i)]}unproject(t){return[this.#e(t[0]),this.#s(t[1])]}#t(t){return t/180*this.HALF_EARTH}#l(t){var i=Math.log(Math.tan((90+t)*Math.PI/360))/(Math.PI/180);return i*this.HALF_EARTH/180}#e(t){return t/this.HALF_EARTH*180}#s(t){var i=t/this.HALF_EARTH*180;return i=180/Math.PI*(2*Math.atan(Math.exp(i*Math.PI/180))-Math.PI/2),i}getID(){return"epsg:3857"}}class y{constructor(){this.eventHandlers={}}on(t,i){this.eventHandlers[t]=i}emit(t,...i){this.eventHandlers[t]?.call(this,...i)}}class C extends y{#t;#l;#e;#s;#c;#o;#i;#r;#a;#n;constructor(t,i,e={},l=null){super(),this.scene=t,this.camera=i,this.#t=new A,this.#e=null,this.#s=0,this.#c=100,this.#o=null,this.setGpsOptions(e),this.#i=null,this.#r=0,this.#a=0,this.#n=l}setProjection(t){this.#t=t}setGpsOptions(t={}){t.gpsMinDistance!==void 0&&(this.#s=t.gpsMinDistance),t.gpsMinAccuracy!==void 0&&(this.#c=t.gpsMinAccuracy)}async startGps(){if(this.#n){const i=await(await this.#n.sendData("/gps/start",{gpsMinDistance:this.#s,gpsMinAccuracy:this.#c})).json();this.#a=i.session}return this.#o===null?(this.#o=navigator.geolocation.watchPosition(t=>{this.#h(t)},t=>{this.emit("gpserror",t)},{enableHighAccuracy:!0}),!0):!1}stopGps(){return this.#o!==null?(navigator.geolocation.clearWatch(this.#o),this.#o=null,!0):!1}fakeGps(t,i,e=null,l=0){e!==null&&this.setElevation(e),this.#h({coords:{longitude:t,latitude:i,accuracy:l}})}lonLatToWorldCoords(t,i){const e=this.#t.project(t,i);if(this.#i)e[0]-=this.#i[0],e[1]-=this.#i[1];else throw"No initial position determined";return[e[0],-e[1]]}add(t,i,e,l,m={}){t.properties=m,this.#d(t,i,e,l),this.scene.add(t),this.#n?.sendData("/object/new",{position:t.position,x:t.position.x,z:t.position.z,session:this.#a,properties:m})}#d(t,i,e,l){const m=this.lonLatToWorldCoords(i,e);l!==void 0&&(t.position.y=l),[t.position.x,t.position.z]=m}setElevation(t){this.camera.position.y=t}#u(t,i){this.#i=this.#t.project(t,i)}#h(t){let i=Number.MAX_VALUE;this.#r++,this.#n?.sendData("/gps/new",{gpsCount:this.#r,lat:t.coords.latitude,lon:t.coords.longitude,acc:t.coords.accuracy,session:this.#a}),t.coords.accuracy<=this.#c&&(this.#e===null?this.#e={latitude:t.coords.latitude,longitude:t.coords.longitude}:i=this.#m(this.#e,t.coords),i>=this.#s&&(this.#e.longitude=t.coords.longitude,this.#e.latitude=t.coords.latitude,this.#i||(this.#u(t.coords.longitude,t.coords.latitude),this.#n?.sendData("/worldorigin/new",{gpsCount:this.#r,lat:t.coords.latitude,lon:t.coords.longitude,session:this.#a,initialPosition:this.#i})),this.#d(this.camera,t.coords.longitude,t.coords.latitude),this.#n?.sendData("/gps/accepted",{gpsCount:this.#r,cameraX:this.camera.position.x,cameraZ:this.camera.position.z,session:this.#a,distMoved:i}),this.emit("gpsupdate",{position:t,distMoved:i})))}#m(t,i){const e=v.MathUtils.degToRad(i.longitude-t.longitude),l=v.MathUtils.degToRad(i.latitude-t.latitude),m=Math.sin(l/2)*Math.sin(l/2)+Math.cos(v.MathUtils.degToRad(t.latitude))*Math.cos(v.MathUtils.degToRad(i.latitude))*(Math.sin(e/2)*Math.sin(e/2));return 2*Math.atan2(Math.sqrt(m),Math.sqrt(1-m))*6371e3}}class _ extends y{#t;constructor(t={video:{facingMode:"environment"}},i){super(),this.sceneWebcam=new v.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 v.VideoTexture(this.#t),navigator.mediaDevices&&navigator.mediaDevices.getUserMedia?navigator.mediaDevices.getUserMedia(t).then(e=>{this.#t.addEventListener("loadedmetadata",()=>{this.#t.setAttribute("width",this.#t.videoWidth),this.#t.setAttribute("height",this.#t.videoHeight),this.#t.play(),this.emit("webcamstarted",{texture:this.texture})}),this.#t.srcObject=e}).catch(e=>{this.emit("webcamerror",{code:e.name,message:e.message})}):this.emit("webcamerror",{code:"LOCAR_NO_MEDIA_DEVICES_API",message:"Media devices API not supported"})}dispose(){this.texture.dispose()}}const w=navigator.userAgent.match(/iPhone|iPad|iPod/i)||/Macintosh/i.test(navigator.userAgent)&&navigator.maxTouchPoints!=null&&navigator.maxTouchPoints>1,b=new c.Vector3(0,0,1),I=new c.Euler,D=new c.Quaternion,T=new c.Quaternion(-Math.sqrt(.5),0,0,Math.sqrt(.5));class L extends c.EventDispatcher{constructor(t,i={}){super(),this.eventEmitter=new y;const e=this;this.object=t,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=.5*Math.PI,this.orientationChangeEventName="ondeviceorientationabsolute"in window?"deviceorientationabsolute":"deviceorientation",console.log("Device Orientation Event Name:",this.orientationChangeEventName),this.smoothingFactor=i.smoothingFactor||1,this.enablePermissionDialog=i.enablePermissionDialog??!0;const l=function({alpha:n,beta:s,gamma:a,webkitCompassHeading:r}){if(w){const o=360-r;e.alphaOffset=c.MathUtils.degToRad(o-n),e.deviceOrientation={alpha:n,beta:s,gamma:a,webkitCompassHeading:r}}else n<0&&(n+=360),e.deviceOrientation={alpha:n,beta:s,gamma:a};window.dispatchEvent(new CustomEvent("camera-rotation-change",{detail:{cameraRotation:t.rotation}}))},m=function(){e.screenOrientation=window.orientation||0,w&&(e.screenOrientation===90?e.orientationOffset=-e.HALF_PI:e.screenOrientation===-90?e.orientationOffset=e.HALF_PI:e.orientationOffset=0)},P=function(n,s,a,r,o){I.set(a,s,-r,"YXZ"),n.setFromEuler(I),n.multiply(T),n.multiply(D.setFromAxisAngle(b,-o))};this.connect=function(){m(),window.addEventListener("orientationchange",m),window.addEventListener(e.orientationChangeEventName,l),e.enabled=!0},this.disconnect=function(){window.removeEventListener("orientationchange",m),window.removeEventListener(e.orientationChangeEventName,l),e.enabled=!1,e.initialOffset=!1,e.deviceOrientation=null},this.requestOrientationPermissions=function(){window.DeviceOrientationEvent!==void 0&&typeof window.DeviceOrientationEvent.requestPermission=="function"?window.DeviceOrientationEvent.requestPermission().then(n=>{n==="granted"?this.eventEmitter.emit("deviceorientationgranted",{target:this}):this.eventEmitter.emit("deviceorientationerror",{code:"LOCAR_DEVICE_ORIENTATION_PERMISSION_DENIED",message:"Permission for device orientation denied - AR will not work correctly"})}).catch(function(n){this.eventEmitter.emit("deviceorientationerror",{code:"LOCAR_DEVICE_ORIENTATION_PERMISSION_FAILED",message:"Permission request for device orientation failed - AR will not work correctly"})}):this.eventEmitter.emit("deviceorientationerror",{code:"LOCAR_DEVICE_ORIENTATION_INTERNAL_ERROR",message:"Internal error: no requestPermission() found although requestOrientationPermissions() was called - please raise an issue on GitHub"})},this.update=function({theta:n=0}={theta:0}){if(e.enabled===!1)return;const s=e.deviceOrientation;if(s){let a=s.alpha?c.MathUtils.degToRad(s.alpha)+e.alphaOffset:0,r=s.beta?c.MathUtils.degToRad(s.beta):0,o=s.gamma?c.MathUtils.degToRad(s.gamma):0;const p=e.screenOrientation?c.MathUtils.degToRad(e.screenOrientation):0;if(e.smoothingFactor<1){if(e.lastOrientation){const h=e.smoothingFactor;a=e._getSmoothedAngle(a,e.lastOrientation.alpha,h),r=e._getSmoothedAngle(r+Math.PI,e.lastOrientation.beta,h),o=e._getSmoothedAngle(o+e.HALF_PI,e.lastOrientation.gamma,h,Math.PI)}else r+=Math.PI,o+=e.HALF_PI;e.lastOrientation={alpha:a,beta:r,gamma:o}}if(w){const h=new c.Quaternion;P(h,a,e.smoothingFactor<1?r-Math.PI:r,e.smoothingFactor<1?o-Math.PI/2:o,p);const f=new c.Euler().setFromQuaternion(h,"YXZ");let O=c.MathUtils.degToRad(360-s.webkitCompassHeading);e.smoothingFactor<1&&e.lastCompassY!==void 0&&(O=e._getSmoothedAngle(O,e.lastCompassY,e.smoothingFactor)),e.lastCompassY=O,f.y=O+(e.orientationOffset||0),h.setFromEuler(f),e.object.quaternion.copy(h)}else P(e.object.quaternion,w?a+e.alphaOffset:a,e.smoothingFactor<1?r-Math.PI:r,e.smoothingFactor<1?o-Math.PI/2:o,p)}},this.getCorrectedHeading=function(){const{deviceOrientation:n}=e;if(!n)return 0;let s=0;return w?(s=360-n.webkitCompassHeading,e.orientationOffset&&(s+=e.orientationOffset*(180/Math.PI),s=(s+360)%360)):(n.absolute===!0||e.orientationChangeEventName,s=n.alpha?n.alpha:0,s=(360-s)%360,s<0&&(s+=360)),s},this._orderAngle=function(n,s,a=e.TWO_PI){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}},this._getSmoothedAngle=function(n,s,a,r=e.TWO_PI){const o=e._orderAngle(n,s,r),p=o.left,h=o.right;o.left=0,o.right-=p,o.right<0&&(o.right+=r);let f=h==s?(1-a)*o.right+a*o.left:a*o.right+(1-a)*o.left;return f+=p,f>=r&&(f-=r),f},this.updateAlphaOffset=function(){e.initialOffset=!1},this.dispose=function(){e.disconnect()},this.getAlpha=function(){const{deviceOrientation:n}=e;return n&&n.alpha?c.MathUtils.degToRad(n.alpha)+e.alphaOffset:0},this.getBeta=function(){const{deviceOrientation:n}=e;return n&&n.beta?c.MathUtils.degToRad(n.beta):0},this.getGamma=function(){const{deviceOrientation:n}=e;return n&&n.gamma?c.MathUtils.degToRad(n.gamma):0},this.obtainPermissionGesture=function(){const n=document.createElement("div"),s=document.createElement("div"),a=document.createElement("div"),r=document.createElement("div");document.body.appendChild(n);const o={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"},h={width:"100%",height:"70%",display:"flex",justifyContent:"center",alignItems:"center"},f={display:"inline-flex",width:"100%",height:"30%",justifyContent:"center",alignItems:"center"};for(let g in o)n.style[g]=o[g];for(let g in p)s.style[g]=p[g];for(let g in h)a.style[g]=h[g];for(let g in f)r.style[g]=f[g];n.appendChild(s),s.appendChild(a),s.appendChild(r),a.innerHTML='<div style="font-size: 24pt; margin: 1rem;">This immersive website requires access to your device motion sensors.</div>';const O=()=>{this.requestOrientationPermissions(),n.style.display="none"},M=document.createElement("button");M.addEventListener("click",O),M.style.width="50%",M.style.height="80%",M.style.fontSize="20pt",M.appendChild(document.createTextNode("OK")),r.appendChild(M),document.body.appendChild(n)}}on(t,i){this.eventEmitter.on(t,i)}init(){window.DeviceOrientationEvent===void 0?this.eventEmitter.emit("deviceorientationerror",{code:"LOCAR_DEVICE_ORIENTATION_NOT_SUPPORTED",message:"Device orientation API not supported"}):window.isSecureContext===!1?this.eventEmitter.emit("deviceorientationerror",{code:"LOCAR_DEVICE_ORIENTATION_NO_HTTPS",message:"DeviceOrientationEvent is only available in secure contexts (https)"}):typeof window.DeviceOrientationEvent.requestPermission=="function"&&this.enablePermissionDialog?this.obtainPermissionGesture():this.eventEmitter.emit("deviceorientationgranted",{target:this})}}class R{constructor(t){this.raycaster=new v.Raycaster,this.normalisedMousePosition=new v.Vector2(null,null),t.domElement.addEventListener("click",i=>{this.normalisedMousePosition.set(i.clientX/t.domElement.clientWidth*2-1,-(i.clientY/t.domElement.clientHeight*2)+1)})}raycast(t,i){if(this.normalisedMousePosition.x!==null&&this.normalisedMousePosition.y!==null){this.raycaster.setFromCamera(this.normalisedMousePosition,t);const e=this.raycaster.intersectObjects(i.children,!1);return this.normalisedMousePosition.set(null,null),e}return[]}}const S="0.1.0";d.ClickHandler=R,d.DeviceOrientationControls=L,d.EventEmitter=y,d.LocationBased=C,d.SphMercProjection=A,d.Webcam=_,d.version=S,Object.defineProperty(d,Symbol.toStringTag,{value:"Module"})}));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "locar",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "0.1.0",
|
|
4
4
|
"description": "Location-based AR from AR.js.",
|
|
5
5
|
"files": [
|
|
6
6
|
"dist"
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
},
|
|
20
20
|
"devDependencies": {
|
|
21
21
|
"jsdoc": "^4.0.4",
|
|
22
|
-
"vite": "^
|
|
22
|
+
"vite": "^7.1.3"
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
25
|
"three": "^0.175.0"
|