The Device Motion API

Introduction

This section presents the Device Motion API which is used in a similar manner to the device orientation API discussed earlier.

The deviceMotion API deals with accelerations instead of orientation only.

Use cases proposed by the specification are:

    • Controlling a game: a gaming Web application monitors the device’s orientation and interprets tilting in a certain direction as a means to control an on-screen sprite.
    • Gesture recognition: a Web application monitors the device’s acceleration and applies signal processing in order to recognize certain specific gestures. For example, using a shaking gesture to clear a web form.
    • Mapping: a mapping Web application uses the device’s orientation to correctly align the map with reality.

Basic Usage

  1. function handleMotionEvent(event) {
  2.    var x = event.accelerationIncludingGravity.x;
  3.    var y = event.accelerationIncludingGravity.y;
  4.    var z = event.accelerationIncludingGravity.z;
  5.    // Process …
  6. }
  7. window.addEventListener(“devicemotion”, handleMotionEvent, true);

Basics about acceleration

The deviceMotion API is rather straightforward and is very similar to the orientation API except that it returns more than just the rotationinformation, it also returns acceleration information reflecting the device’s actual movement.

The acceleration is in three parts:

  1. along the X axis
  2. along the Y axis
  3. along the Z axis

Each value is measured in meters per second squared (m/s2) – multiply by 3.281 if you’d prefer an approximation in feet per second per second.

The acceleration is returned by the API as an acceleration event. The two pertinent properties are: accelerationIncludingGravity and acceleration. The latter excludes the effects of gravity.

Why are there two different values? Because some devices have the capability of excluding the effects of gravity, eg if equipped with a gyroscope. Indeed there is acceleration due implicitly to gravity, see also this: Acceleration of Gravity on Earth… 

If the device doesn’t have a gyroscope, the acceleration property will be returned as null. In this case, you have no choice but to use the accelerationIncludingGravity property. Note that all IOS devices, so far, are equipped with a gyroscope.

So, the device motion event is a superset of the device orientation event; it returns rotation as well as acceleration information from the device. 

Example of acceleration values

If a laptop is in its normal position with the screen facing up, the data returned would be (info taken from:http://www.html5rocks.com/en/tutorials/device/orientation):

acceleration values 1

A mobile phone rotated along the x-axis so the screen is perpendicular to its normal position would return:

acceleration values 2

Remember the coordinate system for a mobile phone:

telephone coordinates system

Common steps

The principles arethe same as for the orientation API:

    1. Test if the API is supported by the browser,
    2. Add a listener for ‘devicemotion‘ events,
    3. Get the acceleration values from the DOM event that has been passed to the listener,
    4. Process the data.

Common processing with acceleration values

Test the value of the acceleration.z property: If > 0 then the device is facing up, otherwise it is facing down. This would be useful if you wanted to play heads or tails with your phone 😉

  1. // For example, if acceleration.z is > 0 then the phone is facing up
  2. var facingUp = 1;
  3. if (acceleration.z > 0) {
  4.    facingUp = +1;
  5. }

Compute the angle corresponding to the Left / Right and Front / Back tilts. This example was taken from http://www.html5rocks.com/en/tutorials/device/orientation and uses the accelerationIncludingGravity property of the event.

  1. function deviceMotionHandler(eventData) {
  2.    // Grab the acceleration including gravity from the results
  3.    var acceleration = eventData.accelerationIncludingGravity;
  4.    // Convert the value from acceleration to degrees
  5.    // acceleration.x|y is the acceleration according
  6.    //  to gravity, we’ll assume we’re on  Earth and divide
  7.    // by 9.81 (earth gravity) to get a percentage value, 
  8.    // and then multiply that by 90 to convert to degrees.
  9.    var tiltLR = Math.round(((acceleration.x) / 9.81) * 90);
  10.    var tiltFB = Math.round(((acceleration.y + 9.81) / 9.81) * 90 * facingUp);
  11.    // … do something
  12. }

Compute the vertical (direction of the sky) – this extract comes from a complete example further down this page…

  1. var angle = Math.atan2(accel.y,accel.x);
  2. var canvas = document.getElementById(‘myCanvas’);
  3. var ctx = canvas.getContext(‘2d’);
  4. ctx.moveTo(50,50);
  5. // Draw sky direction in the canvas
  6. ctx.lineTo(5050*Math.cos(angle),50+50*Math.sin(angle));
  7. ctx.stroke();

Use acceleration values to move a ball on the screen of a tablet when the tablet is tilted front / back or left / right (complete example later on)…

  1. ball.x += acceleration.x;
  2. ball.y += acceleration.y;

Complete examples

Move the HTML5 logo

Online example at JsBin. 

Devicemotion API example

Code from this example:

  1. <!doctype html>
  2. <html>
  3.    <head></head>
  4.    <body>
  5.       <h2>Device Orientation with HTML5</h2>
  6.       You need to be on a mobile device or use a laptop with accelerometer/orientation
  7.       device.
  8.       <p>
  9.       
     id=“rawAccel”>
  10.       
     id=“tiltFB”>
  11.       
     id=“tiltLR”>
  12.       
     id=“upDown”>
  13.       <img src=http://www.html5rocks.com/en/tutorials/device/orientation/html5_logo.png&#8221; id=“imgLogo”class=“logo”>
  14.        type=“text/javascript”>
  15.          if (window.DeviceMotionEvent != undefined) {
  16.          console.log(“DeviceMotion is supported”);
  17.          window.addEventListener(‘devicemotion’, function(eventData) {
  18.             // Grab the acceleration including gravity from the results
  19.             var acceleration = eventData.accelerationIncludingGravity;
  20.             // Display the raw acceleration data
  21.             var rawAcceleration = “[“ + Math.round(acceleration.x) + “, “ + Math.round(acceleration.y
  22.             + “, “ + Math.round(acceleration.z) + “]”;
  23.             // Z is the acceleration in the Z axis, and if the device
  24.             // is facing up or down
  25.             var facingUp = 1;
  26.             if (acceleration.z > 0) {
  27.                facingUp = +1;
  28.             }
  29.             // Convert the value from acceleration to degrees
  30.             // acceleration.x|y is the acceleration according to gravity,
  31.             //  we’ll assume we’re on Earth and divide
  32.             // by 9.81 (earth gravity) to get a percentage value,  
  33.             // and then multiply that by 90 to convert to degrees.
  34.             var tiltLR = Math.round(((acceleration.x) / 9.81) * 90);
  35.             var tiltFB = Math.round(((acceleration.y + 9.81) / 9.81) * 90 * facingUp);
  36.             document.querySelector(“#rawAccel”).innerHTML =
  37.                                “Raw acceleration” + rawAcceleration;
  38.             document.querySelector(“#tiltFB”).innerHTML =
  39.                                “Tilt front/back : “ + tiltFB;
  40.             document.querySelector(“#tiltLR”).innerHTML =
  41.                                “Tilt left/right : “ + tiltLR;
  42.             document.querySelector(“#upDown”).innerHTML =
  43.                                “Face Up:Down : “ + facingUp;
  44.             updateLogoOrientation(tiltLR, tiltFB);
  45.          }, false);
  46.       } else {
  47.         alert(“Not supported on your device or browser. Sorry.”);
  48.       }
  49.       function updateLogoOrientation(tiltLR, tiltFB) {
  50.          // USE CSS3 rotations for rotating the HTML5 logo
  51.          //for webkit browser
  52.          document.getElementById(“imgLogo”).style.webkitTransform =
  53.          “rotate(“ + tiltLR + “deg) rotate3d(1,0,0, “ + (tiltFB * 1) + “deg)”;
  54.          //for HTML5 standard-compliance
  55.          document.getElementById(“imgLogo”).style.transform =
  56.          “rotate(“ + tiltLR + “deg) rotate3d(1,0,0, “ + (tiltFB * 1) + “deg)”;
  57.       }
  58.    
  59.   </body>
  60. </html>

Interesting example that uses jQuery mobile

This example comes from: http://www.emanueleferonato.com/2011/09/05/playing-with-javascript-iphone-and-devicemotion-event-listener/

It shows how the X and Y acceleration values can be used for indicating the sky’s direction (vertical), and how the Z acceleration is, in fact, an indicator for the face up / face down orientation of the device.

This example has been adapted and put on jsbin.com so that you can tweak it: https://jsbin.com/uyuqek/4/edit

devicemotion API

Code from the example:

  1. <html>
  2.    <head>
  3.      <meta http-equiv=“content-type” content=“text/html; charset=utf-8”>
  4.      <meta name=“viewport” content=“user-scalable=no, width=device-width” />
  5.      <link rel=“stylesheet”
  6.            href=http://code.jquery.com/mobile/1.0b2/jquery.mobile-1.0b2.min.css&#8221; />
  7.       type=“text/javascript”
  8.              src = http://code.jquery.com/jquery-1.6.2.min.js&#8221;>
  9.      
  10.       type=“text/javascript”
  11.              src = http://code.jquery.com/mobile/1.0b2/jquery.mobile-1.0b2.min.js&#8221;>
  12.      
  13.       type=“text/javascript”>
  14.         $(document).ready(function(){
  15.             window.addEventListener(“devicemotion”,onDeviceMotion,false);
  16.         });
  17.         function onDeviceMotion(event){
  18.             var ctx = document.getElementById(“c”).getContext(“2d”);
  19.             var accel = event.accelerationIncludingGravity;
  20.             $(“#sliderX”).val(Math.round(accel.x)).slider(“refresh”);
  21.             $(“#sliderY”).val(Math.round(accel.y)).slider(“refresh”);
  22.             $(“#sliderZ”).val(Math.round(accel.z)).slider(“refresh”);
  23.             // sky direction
  24.             var angle = Math.atan2(accel.y,accel.x)
  25.             ctx.clearRect(0,0,100,100);
  26.             ctx.beginPath();
  27.             ctx.arc(50,50,5,0,2*Math.PI,false);
  28.             ctx.moveTo(50,50);
  29.             // Draw sky direction
  30.             ctx.lineTo(5050*Math.cos(angle),50+50*Math.sin(angle));
  31.             ctx.stroke();
  32.         }
  33.      
  34.    </head>
  35.    <body>
  36.      
     data-role=“page” id = “intropage”>
  37.         
     data-role=“header”>
  38.            

    Accelerometer

  39.         
  •         
     data-role=“content”>
  •             for=“sliderX”>X Acceleration (Roll)
  •             type=“range” name=“sliderX” id=“sliderX”
  •                   value=“0” min=“-10” max=“10” data-theme=“a” />
  •             for=“sliderY”>Y Acceleration (Pitch)
  •             type=“range” name=“sliderY” id=“sliderY”
  •                   value=“0” min=“-10” max=“10” data-theme=“b” />
  •             for=“sliderZ”>Z Acceleration (Yaw
  •               Face up/down)
  •            
  •             type=“range” name=“sliderZ” id=“sliderZ”
  •                   value=“0” min=“-10” max=“10” data-theme=“c” />
  •         
  •         <p style = textalign:center>SKY direction:
  •                                       follow this line:</p>
  •         
     style = textalign:center;margintop:10px;>
  •             id=“c” width=“100” height=“100”>
  •