From eb2bdbef18f24f633373f35fd725a7519d01bdc8 Mon Sep 17 00:00:00 2001 From: mistic100 Date: Sat, 18 May 2024 15:22:05 +0200 Subject: [PATCH] Fix #1300 gyroscope: better support of "absolutePosition" option --- docs/plugins/gyroscope.md | 2 +- .../src/DeviceOrientationControls.d.ts | 2 +- .../src/DeviceOrientationControls.js | 23 ++++++++++++++++++- .../gyroscope-plugin/src/GyroscopePlugin.ts | 15 +++++------- packages/gyroscope-plugin/src/model.ts | 2 ++ 5 files changed, 32 insertions(+), 12 deletions(-) diff --git a/docs/plugins/gyroscope.md b/docs/plugins/gyroscope.md index a9e09b396..995de4323 100644 --- a/docs/plugins/gyroscope.md +++ b/docs/plugins/gyroscope.md @@ -53,7 +53,7 @@ Applies camera roll (rotation on Z axis). - type: `boolean` - default: `false` -- updatable: yes +- updatable: no By default the camera will keep its current horizontal position when the gyroscope is enabled. Turn this option `true` to enable absolute positionning and only use the device orientation. diff --git a/packages/gyroscope-plugin/src/DeviceOrientationControls.d.ts b/packages/gyroscope-plugin/src/DeviceOrientationControls.d.ts index 0738b13ba..a96186d20 100644 --- a/packages/gyroscope-plugin/src/DeviceOrientationControls.d.ts +++ b/packages/gyroscope-plugin/src/DeviceOrientationControls.d.ts @@ -6,7 +6,7 @@ export class DeviceOrientationControls { screenOrientation: number; alphaOffset: number; - constructor(object: Object3D); + constructor(object: Object3D, preferAbsolute: boolean); connect(); diff --git a/packages/gyroscope-plugin/src/DeviceOrientationControls.js b/packages/gyroscope-plugin/src/DeviceOrientationControls.js index faf8d9c27..c9012940b 100644 --- a/packages/gyroscope-plugin/src/DeviceOrientationControls.js +++ b/packages/gyroscope-plugin/src/DeviceOrientationControls.js @@ -11,7 +11,7 @@ const _q1 = new Quaternion(-Math.sqrt(0.5), 0, 0, Math.sqrt(0.5)); // - PI/2 aro * @internal */ export class DeviceOrientationControls { - constructor(object) { + constructor(object, preferAbsolute) { if (window.isSecureContext === false) { console.error( 'THREE.DeviceOrientationControls: DeviceOrientationEvent is only available in secure contexts (https)' @@ -23,6 +23,8 @@ export class DeviceOrientationControls { const EPS = 0.000001; const lastQuaternion = new Quaternion(); + let nonAbsoluteListener = false; + this.object = object; this.object.rotation.reorder('YXZ'); @@ -37,6 +39,15 @@ export class DeviceOrientationControls { scope.deviceOrientation = event; }; + const onDeviceOrientationAbsoluteChangeEvent = function (event) { + // if the 'deviceorientationabsolute' event is supported, automatically remove the 'deviceorientation' listener + if (nonAbsoluteListener) { + window.removeEventListener('deviceorientation', onDeviceOrientationChangeEvent); + nonAbsoluteListener = false; + } + scope.deviceOrientation = event; + }; + const onScreenOrientationChangeEvent = function () { scope.screenOrientation = window.orientation || 0; }; @@ -67,6 +78,10 @@ export class DeviceOrientationControls { if (response == 'granted') { window.addEventListener('orientationchange', onScreenOrientationChangeEvent); window.addEventListener('deviceorientation', onDeviceOrientationChangeEvent); + if (preferAbsolute) { + window.addEventListener('deviceorientationabsolute', onDeviceOrientationAbsoluteChangeEvent); + nonAbsoluteListener = true; + } } }) .catch(function (error) { @@ -75,6 +90,10 @@ export class DeviceOrientationControls { } else { window.addEventListener('orientationchange', onScreenOrientationChangeEvent); window.addEventListener('deviceorientation', onDeviceOrientationChangeEvent); + if (preferAbsolute) { + window.addEventListener('deviceorientationabsolute', onDeviceOrientationAbsoluteChangeEvent); + nonAbsoluteListener = true; + } } scope.enabled = true; @@ -83,6 +102,8 @@ export class DeviceOrientationControls { this.disconnect = function () { window.removeEventListener('orientationchange', onScreenOrientationChangeEvent); window.removeEventListener('deviceorientation', onDeviceOrientationChangeEvent); + window.removeEventListener('deviceorientationabsolute', onDeviceOrientationAbsoluteChangeEvent); + nonAbsoluteListener = false; scope.enabled = false; }; diff --git a/packages/gyroscope-plugin/src/GyroscopePlugin.ts b/packages/gyroscope-plugin/src/GyroscopePlugin.ts index 12374bc99..1b7f1ee4a 100644 --- a/packages/gyroscope-plugin/src/GyroscopePlugin.ts +++ b/packages/gyroscope-plugin/src/GyroscopePlugin.ts @@ -3,7 +3,7 @@ import { AbstractConfigurablePlugin, events, utils } from '@photo-sphere-viewer/ import { Object3D, Vector3 } from 'three'; import { DeviceOrientationControls } from './DeviceOrientationControls'; import { GyroscopePluginEvents, GyroscopeUpdatedEvent } from './events'; -import { GyroscopePluginConfig } from './model.js'; +import { GyroscopePluginConfig, UpdatableGyroscopePluginConfig } from './model.js'; const getConfig = utils.getConfigParser( { @@ -32,12 +32,13 @@ const direction = new Vector3(); export class GyroscopePlugin extends AbstractConfigurablePlugin< GyroscopePluginConfig, GyroscopePluginConfig, - GyroscopePluginConfig, + UpdatableGyroscopePluginConfig, GyroscopePluginEvents > { static override readonly id = 'gyroscope'; static override readonly VERSION = PKG_VERSION; static override readonly configParser = getConfig; + static override readonly readonlyOptions: Array = ['absolutePosition']; private readonly state = { isSupported: this.__checkSupport(), @@ -74,6 +75,7 @@ export class GyroscopePlugin extends AbstractConfigurablePlugin< this.stop(); + this.controls?.disconnect(); delete this.controls; super.destroy(); @@ -138,13 +140,10 @@ export class GyroscopePlugin extends AbstractConfigurablePlugin< // enable gyro controls if (!this.controls) { - this.controls = new DeviceOrientationControls(new Object3D()); - } else { - this.controls.connect(); + this.controls = new DeviceOrientationControls(new Object3D(), this.config.absolutePosition); } - // force reset - this.controls.deviceOrientation = null; + // reset this.controls.alphaOffset = 0; this.state.alphaOffset = this.config.absolutePosition ? 0 : null; @@ -159,8 +158,6 @@ export class GyroscopePlugin extends AbstractConfigurablePlugin< */ stop() { if (this.isEnabled()) { - this.controls.disconnect(); - this.state.enabled = false; this.viewer.config.moveInertia = this.state.config_moveInertia; diff --git a/packages/gyroscope-plugin/src/model.ts b/packages/gyroscope-plugin/src/model.ts index 030a16e87..8bb54a1b4 100644 --- a/packages/gyroscope-plugin/src/model.ts +++ b/packages/gyroscope-plugin/src/model.ts @@ -20,3 +20,5 @@ export type GyroscopePluginConfig = { */ moveMode?: 'smooth' | 'fast'; }; + +export type UpdatableGyroscopePluginConfig = Omit;