UNPKG

@hughsk/fulltilt

Version:

Standalone device orientation + device motion normalization and conversion library

290 lines (173 loc) 6.14 kB
///// FULLTILT.DeviceOrientation ////// FULLTILT.DeviceOrientation = function (options) { this.options = options || {}; // by default use UA deviceorientation 'type' ("game" on iOS, "world" on Android) var tries = 0; var maxTries = 200; var successCount = 0; var successThreshold = 10; this.alphaOffsetScreen = 0; this.alphaOffsetDevice = undefined; // Create a game-based deviceorientation object (initial alpha === 0 degrees) if (this.options.type === "game") { var setGameAlphaOffset = function(evt) { if (evt.alpha !== null) { // do regardless of whether 'evt.absolute' is also true this.alphaOffsetDevice = new FULLTILT.Euler(evt.alpha, 0, 0); this.alphaOffsetDevice.rotateZ( -screenOrientationAngle ); // Discard first {successThreshold} responses while a better compass lock is found by UA if(++successCount >= successThreshold) { window.removeEventListener( 'deviceorientation', setGameAlphaOffset, false ); return; } } if(++tries >= maxTries) { window.removeEventListener( 'deviceorientation', setGameAlphaOffset, false ); } }.bind(this); window.addEventListener( 'deviceorientation', setGameAlphaOffset, false ); // Create a compass-based deviceorientation object (initial alpha === compass degrees) } else if (this.options.type === "world") { var setCompassAlphaOffset = function(evt) { if (evt.absolute !== true && evt.webkitCompassAccuracy !== undefined && evt.webkitCompassAccuracy !== null && +evt.webkitCompassAccuracy >= 0 && +evt.webkitCompassAccuracy < 50) { this.alphaOffsetDevice = new FULLTILT.Euler(evt.webkitCompassHeading, 0, 0); this.alphaOffsetDevice.rotateZ( screenOrientationAngle ); this.alphaOffsetScreen = screenOrientationAngle; // Discard first {successThreshold} responses while a better compass lock is found by UA if(++successCount >= successThreshold) { window.removeEventListener( 'deviceorientation', setCompassAlphaOffset, false ); return; } } if(++tries >= maxTries) { window.removeEventListener( 'deviceorientation', setCompassAlphaOffset, false ); } }.bind(this); window.addEventListener( 'deviceorientation', setCompassAlphaOffset, false ); } // else... use whatever orientation system the UA provides ("game" on iOS, "world" on Android) }; FULLTILT.DeviceOrientation.prototype = { constructor: FULLTILT.DeviceOrientation, start: function ( callback ) { if ( callback && Object.prototype.toString.call( callback ) == '[object Function]' ) { sensors.orientation.callbacks.push( callback ); } if( !screenActive ) { if ( hasScreenOrientationAPI ) { window.screen.orientation.addEventListener( 'change', handleScreenOrientationChange, false ); } else { window.addEventListener( 'orientationchange', handleScreenOrientationChange, false ); } } if ( !sensors.orientation.active ) { window.addEventListener( 'deviceorientation', handleDeviceOrientationChange, false ); sensors.orientation.active = true; } }, stop: function () { if ( sensors.orientation.active ) { window.removeEventListener( 'deviceorientation', handleDeviceOrientationChange, false ); sensors.orientation.active = false; } }, listen: function( callback ) { this.start( callback ); }, getFixedFrameQuaternion: (function () { var euler = new FULLTILT.Euler(); var matrix = new FULLTILT.RotationMatrix(); var quaternion = new FULLTILT.Quaternion(); return function() { var orientationData = sensors.orientation.data || { alpha: 0, beta: 0, gamma: 0 }; var adjustedAlpha = orientationData.alpha; if (this.alphaOffsetDevice) { matrix.setFromEuler( this.alphaOffsetDevice ); matrix.rotateZ( - this.alphaOffsetScreen ); euler.setFromRotationMatrix( matrix ); if (euler.alpha < 0) { euler.alpha += 360; } euler.alpha %= 360; adjustedAlpha -= euler.alpha; } euler.set( adjustedAlpha, orientationData.beta, orientationData.gamma ); quaternion.setFromEuler( euler ); return quaternion; }; })(), getScreenAdjustedQuaternion: (function () { var quaternion; return function() { quaternion = this.getFixedFrameQuaternion(); // Automatically apply screen orientation transform quaternion.rotateZ( - screenOrientationAngle ); return quaternion; }; })(), getFixedFrameMatrix: (function () { var euler = new FULLTILT.Euler(); var matrix = new FULLTILT.RotationMatrix(); return function () { var orientationData = sensors.orientation.data || { alpha: 0, beta: 0, gamma: 0 }; var adjustedAlpha = orientationData.alpha; if (this.alphaOffsetDevice) { matrix.setFromEuler( this.alphaOffsetDevice ); matrix.rotateZ( - this.alphaOffsetScreen ); euler.setFromRotationMatrix( matrix ); if (euler.alpha < 0) { euler.alpha += 360; } euler.alpha %= 360; adjustedAlpha -= euler.alpha; } euler.set( adjustedAlpha, orientationData.beta, orientationData.gamma ); matrix.setFromEuler( euler ); return matrix; }; })(), getScreenAdjustedMatrix: (function () { var matrix; return function () { matrix = this.getFixedFrameMatrix(); // Automatically apply screen orientation transform matrix.rotateZ( - screenOrientationAngle ); return matrix; }; })(), getFixedFrameEuler: (function () { var euler = new FULLTILT.Euler(); var matrix; return function () { matrix = this.getFixedFrameMatrix(); euler.setFromRotationMatrix( matrix ); return euler; }; })(), getScreenAdjustedEuler: (function () { var euler = new FULLTILT.Euler(); var matrix; return function () { matrix = this.getScreenAdjustedMatrix(); euler.setFromRotationMatrix( matrix ); return euler; }; })(), isAbsolute: function () { if ( sensors.orientation.data && sensors.orientation.data.absolute === true ) { return true; } return false; }, getLastRawEventData: function () { return sensors.orientation.data || {}; }, ALPHA: 'alpha', BETA: 'beta', GAMMA: 'gamma' };