diff --git a/DeviceOrientationEmulator.js b/DeviceOrientationEmulator.js index 124fea1..138c9f2 100644 --- a/DeviceOrientationEmulator.js +++ b/DeviceOrientationEmulator.js @@ -12,95 +12,98 @@ * */ -(function() { +( function() { - var rootUrl = 'https://richtr.github.io/deviceorientationemulator'; + var emulatorUrl = new URL('https://richtr.github.io/deviceorientationemulator/emulator'); - function runDetection() { + function runDetection() { - var checkTimeout = 1000; + var checkTimeout = 1000; - var deviceOrientationCheck = window.setTimeout(function() { + var deviceOrientationCheck = window.setTimeout( function() { - var swalCSSEl = document.createElement('link'); - swalCSSEl.href = 'https://cdnjs.cloudflare.com/ajax/libs/sweetalert/1.0.1/sweetalert.min.css'; - swalCSSEl.type = 'text/css'; - swalCSSEl.rel = 'stylesheet'; - document.getElementsByTagName('head')[0].appendChild(swalCSSEl); + var swalCSSEl = document.createElement( 'link' ); + swalCSSEl.href = 'https://cdnjs.cloudflare.com/ajax/libs/sweetalert/1.0.1/sweetalert.min.css'; + swalCSSEl.type = 'text/css'; + swalCSSEl.rel = 'stylesheet'; + document.getElementsByTagName( 'head' )[ 0 ].appendChild( swalCSSEl ); - var swalJSEl = document.createElement('script'); - swalJSEl.src = 'https://cdnjs.cloudflare.com/ajax/libs/sweetalert/1.0.1/sweetalert.min.js'; - swalJSEl.type = 'text/javascript'; + var swalJSEl = document.createElement( 'script' ); + swalJSEl.src = 'https://cdnjs.cloudflare.com/ajax/libs/sweetalert/1.0.1/sweetalert.min.js'; + swalJSEl.type = 'text/javascript'; - swalJSEl.onload = function() { - swal({ - title: "No compass detected.", - text: "This page is built for devices that emit device orientation events. If you would still like to try this page you can use an emulator.", - type: "error", - showCancelButton: true, - confirmButtonColor: "#DD6B55", - confirmButtonText: "Open in the emulator", - cancelButtonText: "Cancel", - closeOnConfirm: true - }, - function(){ - // Open the mobile emulator with the current URL - var selfUrl = encodeURIComponent(window.location); - window.location = rootUrl + '/emulator/?url=' + selfUrl; - }); - }; + swalJSEl.onload = function() { + swal( { + title: "No compass detected.", + text: "This page is built for devices that emit device orientation events. If you would still like to try this page you can use an emulator.", + type: "error", + showCancelButton: true, + confirmButtonColor: "#DD6B55", + confirmButtonText: "Open in the emulator", + cancelButtonText: "Cancel", + closeOnConfirm: true + }, + function() { + // Open the mobile emulator with the current URL + var pageUrl = encodeURIComponent( window.location ); + window.location = emulatorUrl.toString() + '/?url=' + pageUrl; + } ); + }; - document.getElementsByTagName('head')[0].appendChild(swalJSEl); + document.getElementsByTagName( 'head' )[ 0 ].appendChild( swalJSEl ); - }, checkTimeout); + }, checkTimeout ); - var isFirstEvent = true; + var isFirstEvent = true; - window.addEventListener('deviceorientation', function check() { - // Discard first event (false positive on Chromium Desktop browsers) - if (isFirstEvent) { - isFirstEvent = false; - return; - } + window.addEventListener( 'deviceorientation', function check() { + // Discard first event (false positive on Chromium Desktop browsers) + if ( isFirstEvent ) { + isFirstEvent = false; + return; + } - // Prevent emulator from kicking in - window.clearTimeout(deviceOrientationCheck); - // Remove self - window.removeEventListener('deviceorientation', check, false); - }, false); + // Prevent emulator alert from kicking in + window.clearTimeout( deviceOrientationCheck ); + // Remove this device orientation check + window.removeEventListener( 'deviceorientation', check, false ); + }, false ); - } + } - function runEmulation() { - var url = new URL(rootUrl); + function runEmulation() { - var listener = function(event) { - if (event.origin !== url.origin) return; + var listener = function( event ) { + if ( event.origin !== emulatorUrl.origin ) return; - try { - var json = JSON.parse(event.data); + try { + var json = JSON.parse( event.data ); - var event = document.createEvent('Event'); - event.initEvent('deviceorientation', true, true); + var event = document.createEvent( 'Event' ); + event.initEvent( 'deviceorientation', true, true ); - for(var key in json) event[key] = json[key]; - event['simulation'] = true; // add 'simulated event' flag + for ( var key in json ) event[ key ] = json[ key ]; + event[ 'simulation' ] = true; // add 'simulated event' flag - window.dispatchEvent(event); - } catch(e) { - console[console.error ? 'error' : 'log'](e); - } - }; + window.dispatchEvent( event ); + } catch ( e ) { + console[ console.error ? 'error' : 'log' ]( e ); + } + }; - window.addEventListener('message', listener, false); - } + window.addEventListener( 'message', listener, false ); - runEmulation(); + } - if (document.readyState === 'complete') { - runDetection(); - } else { - window.addEventListener('load', runDetection, false); - } + // Listen for proxied device orientation events + runEmulation(); -})(); + // Check if device orientation events are supported. + // If not, show the emulator alert message. + if ( document.readyState === 'complete' ) { + runDetection(); + } else { + window.addEventListener( 'load', runDetection, false ); + } + +} )(); diff --git a/emulator/css/resizer.css b/emulator/css/resizer.css index 1223903..c31a903 100644 --- a/emulator/css/resizer.css +++ b/emulator/css/resizer.css @@ -1,112 +1,101 @@ html, body { - width: 100%; - height: 100%; - text-align: center; - background: #333 url('../images/black_linen_v2.png') center repeat; - overflow: hidden; - color: #fff; - font-family: Helvetica, Arial, sans-serif; + width: 100%; + height: 100%; + text-align: center; + background: #333 url('../images/black_linen_v2.png') center repeat; + overflow: hidden; + color: #fff; + font-family: Helvetica, Arial, sans-serif; +} +.resizer-page { + display: block; + height: 100%; } - -.resizer-page { display: block; height: 100%; } - a, a:visited { - color: inherit; + color: inherit; } - #resizerFrame { - width: 100%; - max-width: 320px; - height: 100%; - max-height: 640px; - margin: 0 auto; - background: #fff; - box-shadow: 0 0 50px #000; - border-top: 20px solid #008000; - border-bottom: 20px solid #CC0000; + width: 100%; + max-width: 320px; + height: 100%; + max-height: 640px; + margin: 0 auto; + background: #fff; + box-shadow: 0 0 50px #000; + border-top: 20px solid #008000; + border-bottom: 20px solid #CC0000; } - #resizerFrame::before { - content: "TOP"; - margin-top: -1em; + content: "TOP"; + margin-top: -1em; } - #resizerFrameWrapper { - position: relative; - height: 100%; + position: relative; + height: 100%; } - #resizer { - text-align: center; - line-height: 1; - position: fixed; - top: 0; - right: 0; + text-align: center; + line-height: 1; + position: fixed; + top: 0; + right: 0; } - #controller { - position: fixed; - top: 0; - left: 0; - width: 300px; - height: 300px; - text-align: center; - background: #383636; - z-index:3; + position: fixed; + top: 0; + left: 0; + width: 300px; + height: 300px; + text-align: center; + background: #383636; + z-index: 3; } - #resizer ul { - font-size: 13px; - display: inline-block; - margin: -0.2em auto 0.2em; - -webkit-filter: drop-shadow(0 1px 5px rgba(0,0,0,.25)); - -moz-filter: drop-shadow(0 1px 5px rgba(0,0,0,.25)); - -ms-filter: drop-shadow(0 1px 5px rgba(0,0,0,.25)); - -o-filter: drop-shadow(0 1px 5px rgba(0,0,0,.25)); - filter: drop-shadow(0 1px 5px rgba(0,0,0,.25)); - -ms-transform: translateZ(0); - -o-transform: translateZ(0); - -moz-transform: translateZ(0); - -webkit-transform: translateZ(0); - transform: translateZ(0); + font-size: 13px; + display: inline-block; + margin: -0.2em auto 0.2em; + -webkit-filter: drop-shadow(0 1px 5px rgba(0, 0, 0, .25)); + -moz-filter: drop-shadow(0 1px 5px rgba(0, 0, 0, .25)); + -ms-filter: drop-shadow(0 1px 5px rgba(0, 0, 0, .25)); + -o-filter: drop-shadow(0 1px 5px rgba(0, 0, 0, .25)); + filter: drop-shadow(0 1px 5px rgba(0, 0, 0, .25)); + -ms-transform: translateZ(0); + -o-transform: translateZ(0); + -moz-transform: translateZ(0); + -webkit-transform: translateZ(0); + transform: translateZ(0); } - button.rotate i:before, button[data-rotate] i:before { - -webkit-transition: all 0.15s linear; - -moz-transition: all 0.15s linear; - -ms-transition: all 0.15s linear; - -o-transition: all 0.15s linear; - transition: all 0.15s linear; + -webkit-transition: all 0.15s linear; + -moz-transition: all 0.15s linear; + -ms-transition: all 0.15s linear; + -o-transition: all 0.15s linear; + transition: all 0.15s linear; } - .landscape i:before { - -webkit-transform: rotate(-90deg); - -moz-transform: rotate(-90deg); - -ms-transform: rotate(-90deg); - -o-transform: rotate(-90deg); - transform: rotate(-90deg); + -webkit-transform: rotate(-90deg); + -moz-transform: rotate(-90deg); + -ms-transform: rotate(-90deg); + -o-transform: rotate(-90deg); + transform: rotate(-90deg); } - [data-max="150"] { - font-size: 150px; + font-size: 150px; } - [data-max="95"] { - font-size: 95px; + font-size: 95px; } - [data-max="30"] { - font-size: 30px; + font-size: 30px; } - @media (max-width: 480px) { - [data-min="60"] { - font-size: 60px; - } - [data-min="52"] { - font-size: 52px; - } - [data-min="20"] { - font-size: 20px; - } + [data-min="60"] { + font-size: 60px; + } + [data-min="52"] { + font-size: 52px; + } + [data-min="20"] { + font-size: 20px; + } } diff --git a/emulator/index.html b/emulator/index.html index f0ee6c4..29dc9ba 100755 --- a/emulator/index.html +++ b/emulator/index.html @@ -1,38 +1,47 @@ - + + - - - Device Orientation Emulator - - + + + Device Orientation Emulator - - + + + - + - + -
- -
- -
- -
+
  • + +
  • +
  • + +
  • +
  • + +
  • +
  • + +
  • + + + + +
    + +
    + diff --git a/emulator/js/resizer.js b/emulator/js/resizer.js index beafa6c..baeaa63 100644 --- a/emulator/js/resizer.js +++ b/emulator/js/resizer.js @@ -1,104 +1,99 @@ -function getParameterByName(name) { - name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]"); - var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"), - results = regex.exec(location.search); - return results === null ? "" : decodeURIComponent(results[1].replace(/\+/g, " ")); +function getParameterByName( name ) { + name = name.replace( /[\[]/, "\\[" ).replace( /[\]]/, "\\]" ); + var regex = new RegExp( "[\\?&]" + name + "=([^&#]*)" ), + results = regex.exec( location.search ); + return results === null ? "" : decodeURIComponent( results[ 1 ].replace( /\+/g, " " ) ); } -window.addEventListener('load', function() { +window.addEventListener( 'load', function() { - var urlParam = getParameterByName('url'); - var url; - var resizerFrame = document.querySelector('iframe#resizerFrame'); + var urlParam = getParameterByName( 'url' ); + var url; - if(urlParam.length > 0) { - if(urlParam.substr(0,4) != 'http') { - urlParam = 'http://' + urlParam; - } + var resizerFrame = document.querySelector( 'iframe#resizerFrame' ); - url = new URL(urlParam); + if ( urlParam.length > 0 ) { + if ( urlParam.substr( 0, 4 ) != 'http' ) { + urlParam = 'http://' + urlParam; + } + url = new URL( urlParam ); + // Load url in iframe + resizerFrame.src = urlParam; + } - // Load url in iframe - resizerFrame.src = urlParam; - } + $( 'body' ).on( 'click', 'button[data-viewport-width]', function( e ) { + if ( $( this ).attr( 'data-viewport-width' ) == '100%' ) { + newWidth = '100%'; + } else { + newWidth = $( this ).attr( 'data-viewport-width' ); + } + if ( $( this ).attr( 'data-viewport-height' ) == '100%' ) { + newHeight = '100%'; + } else { + newHeight = $( this ).attr( 'data-viewport-height' ); + } + $( 'button[data-viewport-width]' ).removeClass( 'asphalt active' ).addClass( 'charcoal' ); + $( this ).addClass( 'asphalt active' ).removeClass( 'charcoal' ); + $( '#resizerFrame' ).css( { + 'max-width': newWidth, + 'max-height': newHeight + } ); + e.preventDefault(); + return false; + } ); - $('body').on('click', 'button[data-viewport-width]', function(e) { - if($(this).attr('data-viewport-width') == '100%') { - newWidth = '100%'; - }else{ - newWidth = $(this).attr('data-viewport-width'); - } - if($(this).attr('data-viewport-height') == '100%') { - newHeight = '100%'; - }else{ - newHeight = $(this).attr('data-viewport-height'); - } - $('button[data-viewport-width]').removeClass('asphalt active').addClass('charcoal'); - $(this).addClass('asphalt active').removeClass('charcoal'); + $( 'body' ).on( 'click', 'button.rotate', function( e ) { + $( 'button[data-rotate=true]' ).each( function() { + $( this ).toggleClass( 'landscape' ); + width = $( this ).attr( 'data-viewport-width' ); + height = $( this ).attr( 'data-viewport-height' ); + $( this ).attr( 'data-viewport-width', height ); + $( this ).attr( 'data-viewport-height', width ); + if ( $( this ).hasClass( 'active' ) ) { + $( this ).trigger( 'click' ); + } + } ); + } ); - $('#resizerFrame').css({ - 'max-width': newWidth, - 'max-height': newHeight - }); - e.preventDefault(); - return false; - }); + $( document ).on( 'keyup', function( e ) { + switch ( e.keyCode ) { + case 49: + $( '[data-device="fullscreen"]' ).trigger( 'click' ); + break; + case 50: + $( '[data-device="desktop"]' ).trigger( 'click' ); + break; + case 51: + $( '[data-device="macbook"]' ).trigger( 'click' ); + break; + case 52: + $( '[data-device="ipad"]' ).trigger( 'click' ); + break; + case 53: + $( '[data-device="tablet"]' ).trigger( 'click' ); + break; + case 54: + $( '[data-device="android"]' ).trigger( 'click' ); + break; + case 55: + $( '[data-device="iphone"]' ).trigger( 'click' ); + break; + case 32: + case 56: + case 82: + $( '.rotate' ).trigger( 'click' ); + break; + } + } ); - $('body').on('click', 'button.rotate', function(e) { - $('button[data-rotate=true]').each(function() { - $(this).toggleClass('landscape'); - width = $(this).attr('data-viewport-width'); - height = $(this).attr('data-viewport-height'); - $(this).attr('data-viewport-width', height); - $(this).attr('data-viewport-height', width); - if($(this).hasClass('active')) { - $(this).trigger('click'); - } - }); - }); + // Relay deviceorientation events on to content iframe + window.addEventListener( 'message', function( event ) { + var json = JSON.parse( event.data ); + var roll = json[ 'roll' ] || 0; + delete json[ 'roll' ]; // remove roll attribute - $(document).on('keyup', function(e) { - switch(e.keyCode) { - case 49: - $('[data-device="fullscreen"]').trigger('click'); - break; - case 50: - $('[data-device="desktop"]').trigger('click'); - break; - case 51: - $('[data-device="macbook"]').trigger('click'); - break; - case 52: - $('[data-device="ipad"]').trigger('click'); - break; - case 53: - $('[data-device="tablet"]').trigger('click'); - break; - case 54: - $('[data-device="android"]').trigger('click'); - break; - case 55: - $('[data-device="iphone"]').trigger('click'); - break; - case 32: - case 56: - case 82: - $('.rotate').trigger('click'); - break; - } - }); + resizerFrame.contentWindow.postMessage( JSON.stringify( json ), url.origin ); + resizerFrame.style.transform = 'rotate(' + roll + 'deg)'; + }, false ); - // Relay deviceorientation events on to content iframe - window.addEventListener('message', function(event) { - var json = JSON.parse(event.data); - - var roll = json['roll'] || 0; - - delete json['roll']; // remove roll attribute - - resizerFrame.contentWindow.postMessage(JSON.stringify(json), url.origin); - resizerFrame.style.transform = 'rotate(' + roll + 'deg)'; - - }, false); - -}, false); +}, false ); diff --git a/popup/css/controls.css b/popup/css/controls.css index 1ede843..86aae87 100644 --- a/popup/css/controls.css +++ b/popup/css/controls.css @@ -1,36 +1,33 @@ body { - margin: 0px; - overflow: hidden; - background-color: #ffffff; + margin: 0px; + overflow: hidden; + background-color: #ffffff; } - #info { - position: fixed; - top: 0; - left: 0; - right: 0; - display: block; - overflow: hidden; - font-family: Arial, Helvetica, sans-serif; - margin:0; - color: #ddd; - background-color: #383636; - padding: 5px; - font-family: Monospace; - font-size: 13px; - font-weight: bold; - text-align: center; - z-index: 10; + position: fixed; + top: 0; + left: 0; + right: 0; + display: block; + overflow: hidden; + font-family: Arial, Helvetica, sans-serif; + margin: 0; + color: #ddd; + background-color: #383636; + padding: 5px; + font-family: Monospace; + font-size: 13px; + font-weight: bold; + text-align: center; + z-index: 10; } - .small { - font-size: 0.8em; - text-align: center; + font-size: 0.8em; + text-align: center; } - .data_output { - display:inline-block; - position:relative; - width: 40px; - overflow:hidden; + display: inline-block; + position: relative; + width: 40px; + overflow: hidden; } diff --git a/popup/index.html b/popup/index.html index 750bb5e..d6149b8 100644 --- a/popup/index.html +++ b/popup/index.html @@ -1,61 +1,26 @@ - - Device Orientation Controller - - - - - - - - - - - - + + Device Orientation Controller + + + + + + + + + - -
    -
    - Alpha: - Beta: - Gamma: -
    -
    - - + +
    +
    Alpha: + Beta: + Gamma: +
    +
    + diff --git a/popup/js/DeviceOrientationEmulatorControls.js b/popup/js/DeviceOrientationEmulatorControls.js index 07c6be4..4137e4e 100644 --- a/popup/js/DeviceOrientationEmulatorControls.js +++ b/popup/js/DeviceOrientationEmulatorControls.js @@ -6,9 +6,9 @@ * Author: Rich Tibbett (http://github.com/richtr) * License: The MIT License * -**/ + **/ -var DeviceOrientationEmulatorControls = function ( object, domElement ) { +var DeviceOrientationEmulatorControls = function( object, domElement ) { this.object = object; this.element = domElement || document; @@ -21,16 +21,19 @@ var DeviceOrientationEmulatorControls = function ( object, domElement ) { this.screenOrientation = window.orientation || 0; // Manual rotate override components - var startX = 0, startY = 0, - currentX = 0, currentY = 0, - scrollSpeedX, scrollSpeedY, - tmpQuat = new THREE.Quaternion(); + var startX = 0, + startY = 0, + currentX = 0, + currentY = 0, + scrollSpeedX, scrollSpeedY, + tmpQuat = new THREE.Quaternion(); // Manual zoom override components - var zoomStart = 1, zoomCurrent = 1, - zoomP1 = new THREE.Vector2(), - zoomP2 = new THREE.Vector2(), - tmpFOV; + var zoomStart = 1, + zoomCurrent = 1, + zoomP1 = new THREE.Vector2(), + zoomP2 = new THREE.Vector2(), + tmpFOV; var CONTROLLER_STATE = { AUTO: 0, @@ -42,22 +45,22 @@ var DeviceOrientationEmulatorControls = function ( object, domElement ) { var CONTROLLER_EVENT = { SCREEN_ORIENTATION: 'orientationchange', - MANUAL_CONTROL: 'userinteraction', // userinteractionstart, userinteractionend - ZOOM_CONTROL: 'zoom', // zoomstart, zoomend - ROTATE_CONTROL: 'rotate', // rotatestart, rotateend + MANUAL_CONTROL: 'userinteraction', // userinteractionstart, userinteractionend + ZOOM_CONTROL: 'zoom', // zoomstart, zoomend + ROTATE_CONTROL: 'rotate', // rotatestart, rotateend }; // Consistent Object Field-Of-View fix components var startClientHeight = window.innerHeight, - startFOVFrustrumHeight = 2000 * Math.tan( THREE.Math.degToRad( ( this.object.fov || 75 ) / 2 ) ), - relativeFOVFrustrumHeight, relativeVerticalFOV; + startFOVFrustrumHeight = 2000 * Math.tan( THREE.Math.degToRad( ( this.object.fov || 75 ) / 2 ) ), + relativeFOVFrustrumHeight, relativeVerticalFOV; var deviceQuat = new THREE.Quaternion(); - var fireEvent = function () { + var fireEvent = function() { var eventData; - return function ( name ) { + return function( name ) { eventData = arguments || {}; eventData.type = name; @@ -67,7 +70,7 @@ var DeviceOrientationEmulatorControls = function ( object, domElement ) { }.bind( this ); }.bind( this )(); - this.constrainObjectFOV = function () { + this.constrainObjectFOV = function() { relativeFOVFrustrumHeight = startFOVFrustrumHeight * ( window.innerHeight / startClientHeight ); relativeVerticalFOV = THREE.Math.radToDeg( 2 * Math.atan( relativeFOVFrustrumHeight / 2000 ) ); @@ -75,13 +78,13 @@ var DeviceOrientationEmulatorControls = function ( object, domElement ) { this.object.fov = relativeVerticalFOV; }.bind( this ); - this.onScreenOrientationChange = function () { + this.onScreenOrientationChange = function() { this.screenOrientation = window.orientation || 0; fireEvent( CONTROLLER_EVENT.SCREEN_ORIENTATION ); }.bind( this ); - this.onDocumentMouseDown = function ( event ) { + this.onDocumentMouseDown = function( event ) { event.preventDefault(); appState = CONTROLLER_STATE.MANUAL_ROTATE; @@ -102,12 +105,12 @@ var DeviceOrientationEmulatorControls = function ( object, domElement ) { fireEvent( CONTROLLER_EVENT.ROTATE_CONTROL + 'start' ); }.bind( this ); - this.onDocumentMouseMove = function ( event ) { + this.onDocumentMouseMove = function( event ) { currentX = event.pageX; currentY = event.pageY; }.bind( this ); - this.onDocumentMouseUp = function ( event ) { + this.onDocumentMouseUp = function( event ) { this.element.removeEventListener( 'mousemove', this.onDocumentMouseMove, false ); this.element.removeEventListener( 'mouseup', this.onDocumentMouseUp, false ); @@ -117,7 +120,7 @@ var DeviceOrientationEmulatorControls = function ( object, domElement ) { fireEvent( CONTROLLER_EVENT.ROTATE_CONTROL + 'end' ); }.bind( this ); - this.onDocumentTouchStart = function ( event ) { + this.onDocumentTouchStart = function( event ) { event.preventDefault(); event.stopPropagation(); @@ -164,8 +167,8 @@ var DeviceOrientationEmulatorControls = function ( object, domElement ) { } }.bind( this ); - this.onDocumentTouchMove = function ( event ) { - switch( event.touches.length ) { + this.onDocumentTouchMove = function( event ) { + switch ( event.touches.length ) { case 1: currentX = event.touches[ 0 ].pageX; currentY = event.touches[ 0 ].pageY; @@ -178,7 +181,7 @@ var DeviceOrientationEmulatorControls = function ( object, domElement ) { } }.bind( this ); - this.onDocumentTouchEnd = function ( event ) { + this.onDocumentTouchEnd = function( event ) { this.element.removeEventListener( 'touchmove', this.onDocumentTouchMove, false ); this.element.removeEventListener( 'touchend', this.onDocumentTouchEnd, false ); @@ -201,7 +204,7 @@ var DeviceOrientationEmulatorControls = function ( object, domElement ) { } }.bind( this ); - var createQuaternion = function () { + var createQuaternion = function() { var finalQuaternion = new THREE.Quaternion(); @@ -209,17 +212,17 @@ var DeviceOrientationEmulatorControls = function ( object, domElement ) { var screenTransform = new THREE.Quaternion(); - var worldTransform = new THREE.Quaternion( - Math.sqrt(0.5), 0, 0, Math.sqrt(0.5) ); // - PI/2 around the x-axis + var worldTransform = new THREE.Quaternion( -Math.sqrt( 0.5 ), 0, 0, Math.sqrt( 0.5 ) ); // - PI/2 around the x-axis var minusHalfAngle = 0; - return function ( alpha, beta, gamma, screenOrientation ) { + return function( alpha, beta, gamma, screenOrientation ) { - deviceEuler.set( beta, alpha, - gamma, 'YXZ' ); + deviceEuler.set( beta, alpha, -gamma, 'YXZ' ); finalQuaternion.setFromEuler( deviceEuler ); - minusHalfAngle = - screenOrientation / 2; + minusHalfAngle = -screenOrientation / 2; screenTransform.set( 0, Math.sin( minusHalfAngle ), 0, Math.cos( minusHalfAngle ) ); @@ -233,28 +236,28 @@ var DeviceOrientationEmulatorControls = function ( object, domElement ) { }(); - var createRotationMatrix = function () { + var createRotationMatrix = function() { var finalMatrix = new THREE.Matrix4(); var deviceEuler = new THREE.Euler(); var screenEuler = new THREE.Euler(); - var worldEuler = new THREE.Euler( - Math.PI / 2, 0, 0, 'YXZ' ); // - PI/2 around the x-axis + var worldEuler = new THREE.Euler( -Math.PI / 2, 0, 0, 'YXZ' ); // - PI/2 around the x-axis var screenTransform = new THREE.Matrix4(); var worldTransform = new THREE.Matrix4(); - worldTransform.makeRotationFromEuler(worldEuler); + worldTransform.makeRotationFromEuler( worldEuler ); - return function (alpha, beta, gamma, screenOrientation) { + return function( alpha, beta, gamma, screenOrientation ) { - deviceEuler.set( beta, alpha, - gamma, 'YXZ' ); + deviceEuler.set( beta, alpha, -gamma, 'YXZ' ); finalMatrix.identity(); finalMatrix.makeRotationFromEuler( deviceEuler ); - screenEuler.set( 0, - screenOrientation, 0, 'YXZ' ); + screenEuler.set( 0, -screenOrientation, 0, 'YXZ' ); screenTransform.identity(); @@ -270,7 +273,7 @@ var DeviceOrientationEmulatorControls = function ( object, domElement ) { }(); - this.updateManualMove = function () { + this.updateManualMove = function() { var lat, lon; var phi, theta; @@ -284,7 +287,7 @@ var DeviceOrientationEmulatorControls = function ( object, domElement ) { var zoomFactor, minZoomFactor = 1; // maxZoomFactor = Infinity - return function () { + return function() { objQuat.copy( tmpQuat ); @@ -293,14 +296,14 @@ var DeviceOrientationEmulatorControls = function ( object, domElement ) { lat = ( startY - currentY ) * scrollSpeedY; lon = ( startX - currentX ) * scrollSpeedX; - phi = THREE.Math.degToRad( lat ); + phi = THREE.Math.degToRad( lat ); theta = THREE.Math.degToRad( lon ); - // Apply y-based quaternion rotation + // Apply y-based quaternion rotation rotQuat.set( 0, Math.sin( theta / 2 ), 0, Math.cos( theta / 2 ) ); objQuat.multiply( rotQuat ); - // Apply z-based quaternion rotation + // Apply z-based quaternion rotation rotQuat.set( Math.sin( phi / 2 ), 0, 0, Math.cos( phi / 2 ) ); objQuat.multiply( rotQuat ); @@ -324,7 +327,7 @@ var DeviceOrientationEmulatorControls = function ( object, domElement ) { if ( deviceQuat ) { - tmpZ = rotation.setFromQuaternion( tmpQuat, 'YXZ' ).z; + tmpZ = rotation.setFromQuaternion( tmpQuat, 'YXZ' ).z; realZ = rotation.setFromQuaternion( deviceQuat, 'YXZ' ).z; rotQuat.set( 0, 0, Math.sin( ( realZ - tmpZ ) / 2 ), Math.cos( ( realZ - tmpZ ) / 2 ) ); @@ -341,13 +344,13 @@ var DeviceOrientationEmulatorControls = function ( object, domElement ) { }(); - this.update = function () { + this.update = function() { if ( appState !== CONTROLLER_STATE.AUTO ) { this.updateManualMove(); } }; - this.connect = function () { + this.connect = function() { window.addEventListener( 'resize', this.constrainObjectFOV, false ); window.addEventListener( 'orientationchange', this.onScreenOrientationChange, false ); @@ -356,7 +359,7 @@ var DeviceOrientationEmulatorControls = function ( object, domElement ) { this.element.addEventListener( 'touchstart', this.onDocumentTouchStart, false ); }; - this.disconnect = function () { + this.disconnect = function() { window.removeEventListener( 'resize', this.constrainObjectFOV, false ); window.removeEventListener( 'orientationchange', this.onScreenOrientationChange, false ); diff --git a/popup/js/app.js b/popup/js/app.js index c1d8c56..c150cae 100644 --- a/popup/js/app.js +++ b/popup/js/app.js @@ -1,10 +1,6 @@ -/** - * @author mrdoob / http://mrdoob.com/ - */ - var APP = { - Player: function () { + Player: function() { var scope = this; @@ -20,9 +16,11 @@ var APP = { this.width = 500; this.height = 500; - this.load = function ( json ) { + this.load = function( json ) { - renderer = new THREE.WebGLRenderer( { antialias: true } ); + renderer = new THREE.WebGLRenderer( { + antialias: true + } ); renderer.setClearColor( 0xFFFFFF, 1 ); renderer.setPixelRatio( window.devicePixelRatio ); this.dom = renderer.domElement; @@ -40,7 +38,7 @@ var APP = { var scripts = json.scripts[ uuid ]; - for ( var i = 0; i < scripts.length; i ++ ) { + for ( var i = 0; i < scripts.length; i++ ) { var script = scripts[ i ]; @@ -67,7 +65,7 @@ var APP = { }; - this.setCamera = function ( value ) { + this.setCamera = function( value ) { camera = value; camera.aspect = this.width / this.height; @@ -75,29 +73,29 @@ var APP = { }; - this.setScene = function ( value ) { + this.setScene = function( value ) { - scene = value; + scene = value; - }, + }, - this.setSize = function ( width, height ) { + this.setSize = function( width, height ) { - if ( renderer._fullScreen ) return; + if ( renderer._fullScreen ) return; - this.width = width; - this.height = height; + this.width = width; + this.height = height; - camera.aspect = this.width / this.height; - camera.updateProjectionMatrix(); + camera.aspect = this.width / this.height; + camera.updateProjectionMatrix(); - renderer.setSize( width, height ); + renderer.setSize( width, height ); - }; + }; - var dispatch = function ( array, event ) { + var dispatch = function( array, event ) { - for ( var i = 0, l = array.length; i < l; i ++ ) { + for ( var i = 0, l = array.length; i < l; i++ ) { array[ i ]( event ); @@ -109,68 +107,52 @@ var APP = { var fulltiltEuler = new FULLTILT.Euler(); - var worldQuat = new THREE.Quaternion( - Math.sqrt( 0.5 ), 0, 0, Math.sqrt( 0.5 ) ); + var worldQuat = new THREE.Quaternion( -Math.sqrt( 0.5 ), 0, 0, Math.sqrt( 0.5 ) ); var camQuat = new THREE.Quaternion(); var rotQuat = new THREE.Quaternion(); var rotation = new THREE.Euler( 0, 0, 0, 'YXZ' ); - var rotZ = 0; - var animate = function ( time ) { + var animate = function( time ) { request = requestAnimationFrame( animate ); - dispatch( events.update, { time: time, delta: time - prevTime } ); + dispatch( events.update, { + time: time, + delta: time - prevTime + } ); controls.update(); - renderer.render( scene, camera ); - - // *** Calculate current "device orientation" using Full-Tilt library - + // *** Calculate device orientation quaternion (without affecting rendering) camQuat.copy( controls.object.quaternion ); - - // Position device to reflect real world space camQuat.inverse(); camQuat.multiply( worldQuat ); camQuat.inverse(); - // Remove device roll on request - /*if(scope.removeDeviceRoll) { - rotZ = rotation.setFromQuaternion( controls.object.quaternion, 'YXZ' ).z; - rotQuat.set( 0, 0, Math.sin( ( - rotZ ) / 2 ), Math.cos( ( - rotZ ) / 2 ) ); - camQuat.multiply( rotQuat ); - }*/ - - // Derive Tait-Bryan angles from calculated orientation quaternion - fulltiltEuler.setFromQuaternion(camQuat); + // Derive Tait-Bryan angles from calculated device orientation quaternion + fulltiltEuler.setFromQuaternion( camQuat ); - // Store device orientation data for dispatch to opener window - window.deviceOrientation = fulltiltEuler; + // Calculate required emulator screen roll compensation required + var rollZ = rotation.setFromQuaternion( controls.object.quaternion, 'YXZ' ).z; + fulltiltEuler.roll = THREE.Math.radToDeg( -rollZ ); - rotZ = rotation.setFromQuaternion( controls.object.quaternion, 'YXZ' ).z; + // Dispatch a new 'deviceorientation' event based on derived device orientation + dispatchDeviceOrientationEvent( fulltiltEuler ); - window.deviceOrientation.roll = THREE.Math.radToDeg( -rotZ ); - - // DEBUG - orientationAlpha.value = printDataValue(window.deviceOrientation.alpha); - orientationBeta.value = printDataValue(window.deviceOrientation.beta); - orientationGamma.value = printDataValue(window.deviceOrientation.gamma); + // Render the controller + renderer.render( scene, camera ); prevTime = time; }; - this.play = function (url) { + this.play = function( url ) { + // Rotate the phone in the scene, not the camera as usual var phoneMesh = scene.getObjectByProperty( 'uuid', '33A20938-78BD-4994-8180-E10EC6876880', true ); // Set up device orientation emulator controls - /*controls = new THREE.TrackballControls( camera, scope.dom ); - controls.target.set(0,0,0); - controls.noPan = true; - controls.noZoom = true;*/ - controls = new DeviceOrientationEmulatorControls( phoneMesh, scope.dom ); controls.enableManualZoom = false; controls.connect(); @@ -180,7 +162,7 @@ var APP = { }; - this.stop = function () { + this.stop = function() { cancelAnimationFrame( request ); diff --git a/popup/js/controls.js b/popup/js/controls.js index b9fc629..dfd8d82 100644 --- a/popup/js/controls.js +++ b/popup/js/controls.js @@ -1,20 +1,44 @@ -window.addEventListener('load', function() { +window.addEventListener( 'load', function() { - var loader = new THREE.XHRLoader(); - loader.load( 'data/app.json', function ( text ) { + var loader = new THREE.XHRLoader(); - var player = new APP.Player(); - player.load( JSON.parse( text ) ); - player.setSize( window.innerWidth, window.innerHeight ); + loader.load( 'data/app.json', function( text ) { - document.body.appendChild( player.dom ); + var player = new APP.Player(); + player.load( JSON.parse( text ) ); + player.setSize( window.innerWidth, window.innerHeight ); - player.play(); + document.body.appendChild( player.dom ); - window.addEventListener( 'resize', function () { - player.setSize( window.innerWidth, window.innerHeight ); - } ); + player.play(); - } ); + window.addEventListener( 'resize', function() { + player.setSize( window.innerWidth, window.innerHeight ); + } ); -}, false); + var orientationAlpha = document.querySelector( '#orientationAlpha' ); + var orientationBeta = document.querySelector( '#orientationBeta' ); + var orientationGamma = document.querySelector( '#orientationGamma' ); + + // Listen for device orientation events fired from the emulator + // and dispatch them on to the parent window + window.addEventListener( 'deviceorientation', function( event ) { + if ( !window.parent ) return; + + var data = {}; + data[ "alpha" ] = event.alpha; + data[ "beta" ] = event.beta; + data[ "gamma" ] = event.gamma; + data[ "absolute" ] = event.absolute; + data[ "roll" ] = event.roll; + + window.parent.postMessage( JSON.stringify( data ), "*" ); + + // Print deviceorientation data values in GUI + orientationAlpha.value = printDataValue( data[ "alpha" ] ); + orientationBeta.value = printDataValue( data[ "beta" ] ); + orientationGamma.value = printDataValue( data[ "gamma" ] ); + }, false ); + + } ); +}, false ); diff --git a/popup/js/utils.js b/popup/js/utils.js index fb2391b..1d56133 100644 --- a/popup/js/utils.js +++ b/popup/js/utils.js @@ -1,14 +1,36 @@ -function printDataValue(input) { - if( input === undefined ) +function printDataValue( input ) { + if ( input === undefined ) return "undefined"; - if( input === null ) + if ( input === null ) return "null"; - if( input === true ) + if ( input === true ) return "true"; - if( input === false ) + if ( input === false ) return "false"; - if( Object.prototype.toString.call(input) === "[object Number]" ) - return Math.round((input + 0.00001) * 100) / 100; // return to 2 decimal places + if ( Object.prototype.toString.call( input ) === "[object Number]" ) + return Math.round( ( input + 0.00001 ) * 100 ) / 100; // return to 2 decimal places - return (input + ""); // force stringify + return ( input + "" ); // force stringify +} + +function dispatchDeviceOrientationEvent( values ) { + var data = values || {}; + + // Create and dispatch an emulated device orientation event at window + // object + var event = document.createEvent( 'Event' ); + event.initEvent( 'deviceorientation', true, true ); + + var eventData = { + 'alpha': data.alpha || 0, + 'beta': data.beta || 90, + 'gamma': data.gamma || 0, + 'absolute': true, + 'roll': data.roll || 0 // custom attribute for emulator roll adjustment + }; + + for ( var key in eventData ) event[ key ] = eventData[ key ]; + event[ 'simulation' ] = true; // add 'simulated event' flag + + window.dispatchEvent( event ); }