Hide Table of Contents
View Tilt gesture sample in sandbox
Tilt gesture

Description

This sample demonstrates how to take advantage a mobile device's built-in gyroscope to adjust a layer's opacity. There are a variety of touch events that can be used to track touch interactions. A touch event is triggered when a user's finger touches the device screen. This sample application listens for touch events in the upper right corner of the device's screen. Touch and hold the target area and while rotating the device around its x-axis, the layer's opacity is updated as the device's angle of rotation. Although the x angle of rotation extends 180 to -180 , this sample only uses an angle of rotation from 0 to 90 (0 making the layer completely transparent.)

Unlike the accelerometer, which measures the device's acceleration, the gyroscope provides precise information about the device's orientation in all three dimensions (i.e. x, y and z). The physical orientation and motion of the device can be determined by using the deviceorientation event. Whenever a change in device orientation occurs the deviceorientation event is fired. Properties of the event are alpha (z-axis), beta (x-axis) and gamma (y-axis) and specify the orientation of the device. More details about the DeviceOrientation Event Specification can be found here.

Code

<!DOCTYPE html>
<html>
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  
  <meta name="apple-mobile-web-app-capable" content="yes">
  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
  
  <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">

  <title>Tilt gesture sample</title>

  <link rel="stylesheet" href="https://js.arcgis.com/3.20/esri/css/esri.css" />
  <style>
    html, body {
      height: 100%;
      margin: 0px;
      padding: 0px;
      width: 100%;
    }
    #map {
      position: absolute;
      height: 100%;
      width: 100%;
      z-index: 1;
    }
    #output {
      margin-left: 10px;
      margin-top: 20px;
      height: 40px;
      width: 65px;
      background-color: #DDD;
      position: absolute;
      -webkit-border-radius: 10px;
      border-radius: 10px;
      z-index: 2;
      opacity: 0;
      -webkit-transition-property: opacity;
      -webkit-transition-duration: 1s;
    }
    #lyrOpacityValue {
      padding: 5px;
      font-family:"Times New Roman", Georgia, Serif;
      font-size: 1.1em;
      color: #222;
    }
    #touchCanvas {
      position: absolute;
      width: 10px;
      height: 10px;
      z-index: 2;
    }
  </style>

  <script src="https://js.arcgis.com/3.20compact/"></script>
  <script>
    require([
      "dojo/dom",
      "dojo/on",
      "dojo/parser",
      "dojo/ready",
      "dojo/touch",
      "esri/map",
      "esri/layers/ArcGISDynamicMapServiceLayer",
      "esri/layers/ImageParameters"
    ],
        function (dom, on, parser, ready, touch, Map, ArcGISDynamicMapServiceLayer, ImageParameters) {

          var map, dynamicMapServiceLayer, lyrOpacity, lyrOpacityFlag;

          ready(function() {
            parser.parse();

            var supportsOrientationChange = "onorientationchange" in window,
                orientationEvent = supportsOrientationChange ? "orientationchange" : "resize";

            window.addEventListener(orientationEvent, function () {
              orientationChanged();
            }, false);

            lyrOpacity = 1.0;
            lyrOpacityFlag = false;
            map = new Map("map", {
              basemap:"satellite",
              center :[-97.031, 37.638],
              zoom   :4,
              slider :false
            });

            var imageParameters = new ImageParameters();
            imageParameters.format = "PNG24";
            // load a non cached map service.
            dynamicMapServiceLayer = new ArcGISDynamicMapServiceLayer("https://server.arcgisonline.com/ArcGIS/rest/services/Demographics/USA_Median_Net_Worth/MapServer", {
              "opacity"        :lyrOpacity,
              "imageParameters":imageParameters
            });
            map.addLayer(dynamicMapServiceLayer);

            layerOpacityHandler();

            if (map.loaded) {
              mapLoadHandler(map);
            } else {
              on(map, "load", mapLoadHandler);
            }
          });

          function mapLoadHandler(map) {
            on(document, touch.press, function (event) {
              // handle a mousedown/touchstart event
              var touch = event.touches[0];
              // listen for touch events on a specific area of the screen
              if (touch.pageX > 250 && touch.pageY < 70 && touch.pageY > 0) {
                lyrOpacityFlag = true;
                dom.byId('output').style.opacity = "0";
                dom.byId('output').style.opacity = "1";
              }
            });

            on(document, touch.release, function (event) {
              lyrOpacityFlag = false;
              dom.byId('output').style.opacity = "1";
              dom.byId('output').style.opacity = "0";
            });
          }

          function layerOpacityHandler() {
            if (window.DeviceOrientationEvent) {
              // Listen for the deviceorientation event
              window.addEventListener('deviceorientation', function (eventData) {
                // check if user is touching the screen
                if (lyrOpacityFlag) {
                  // forward/back tilt
                  var tiltFB = eventData.beta;
                  tiltFB = tiltFB / 100;
                  tiltFB = +tiltFB + 0.13;
                  tiltFB = tiltFB.toFixed(2);
                  lyrOpacity = tiltFB;
                  var percentVal = (lyrOpacity * 100).toFixed(0) + ' %';
                  dom.byId('lyrOpacityValue').innerHTML = percentVal;
                  dynamicMapServiceLayer.setOpacity(lyrOpacity);
                }
              }, false);
            } else {
              alert("Device orientation is not supported on your browser");
            }
          }

          function orientationChanged() {
            if (map) {
              map.reposition();
              map.resize();
            }
          }
        }
    );

  </script>
</head>

<body>
  <div id="output">
    <div id="lyrOpacityValue"></div>
  </div>
  <canvas id="touchCanvas"></canvas>
  
  <div id="map"></div>
</body>
</html>