diff --git a/build.py b/build.py
index 7a57df8ad7..01f46c8939 100755
--- a/build.py
+++ b/build.py
@@ -312,6 +312,7 @@ def examples_star_json(name, match):
'../externs/oli.js',
'../externs/proj4js.js',
'../externs/tilejson.js',
+ '../externs/w3c_device_sensor_event.js',
],
})
with open(t.name, 'w') as f:
diff --git a/buildcfg/base.json b/buildcfg/base.json
index 557581927e..f5588857ed 100644
--- a/buildcfg/base.json
+++ b/buildcfg/base.json
@@ -44,7 +44,8 @@
"../externs/geojson.js",
"../externs/oli.js",
"../externs/proj4js.js",
- "../externs/tilejson.js"
+ "../externs/tilejson.js",
+ "../externs/w3c_device_sensor_event.js"
],
"level": "VERBOSE",
diff --git a/buildcfg/ol-all.json b/buildcfg/ol-all.json
index 340936188c..a57165cf21 100644
--- a/buildcfg/ol-all.json
+++ b/buildcfg/ol-all.json
@@ -9,7 +9,8 @@
"../externs/geojson.js",
"../externs/oli.js",
"../externs/proj4js.js",
- "../externs/tilejson.js"
+ "../externs/tilejson.js",
+ "../externs/w3c_device_sensor_event.js"
],
"inherits": "base.json",
diff --git a/buildcfg/ol-simple.json b/buildcfg/ol-simple.json
index c21ae1528e..f0c6054618 100644
--- a/buildcfg/ol-simple.json
+++ b/buildcfg/ol-simple.json
@@ -18,7 +18,8 @@
"../externs/geojson.js",
"../externs/oli.js",
"../externs/proj4js.js",
- "../externs/tilejson.js"
+ "../externs/tilejson.js",
+ "../externs/w3c_device_sensor_event.js"
],
"inherits": "ol.json",
diff --git a/buildcfg/ol-whitespace.json b/buildcfg/ol-whitespace.json
index fb99f44cc3..63bc208d88 100644
--- a/buildcfg/ol-whitespace.json
+++ b/buildcfg/ol-whitespace.json
@@ -19,7 +19,8 @@
"../externs/geojson.js",
"../externs/oli.js",
"../externs/proj4js.js",
- "../externs/tilejson.js"
+ "../externs/tilejson.js",
+ "../externs/w3c_device_sensor_event.js"
],
"inherits": "ol.json",
diff --git a/buildcfg/ol.json b/buildcfg/ol.json
index cb689bbddc..670eb4c8ac 100644
--- a/buildcfg/ol.json
+++ b/buildcfg/ol.json
@@ -19,7 +19,8 @@
"../externs/geojson.js",
"../externs/oli.js",
"../externs/proj4js.js",
- "../externs/tilejson.js"
+ "../externs/tilejson.js",
+ "../externs/w3c_device_sensor_event.js"
],
"inherits": "base.json",
diff --git a/examples/device-orientation.html b/examples/device-orientation.html
new file mode 100644
index 0000000000..dd1bb6215d
--- /dev/null
+++ b/examples/device-orientation.html
@@ -0,0 +1,62 @@
+
+
+
+
+
+
+
+
+
+ Device-Orientation example
+
+
+
+
+
+
+
+
+
+
+
+
+
Device orientation example
+
+
α :
+
β :
+
γ :
+
heading :
+
Listen to DeviceOrientation events
+
+
orientation, openstreetmap
+
+
+
+
+
+
+
+
+
+
+
diff --git a/examples/device-orientation.js b/examples/device-orientation.js
new file mode 100644
index 0000000000..8e5b5b7f49
--- /dev/null
+++ b/examples/device-orientation.js
@@ -0,0 +1,46 @@
+goog.require('ol.DeviceOrientation');
+goog.require('ol.Map');
+goog.require('ol.RendererHints');
+goog.require('ol.View2D');
+goog.require('ol.dom.Input');
+goog.require('ol.layer.TileLayer');
+goog.require('ol.source.OSM');
+
+var map = new ol.Map({
+ layers: [
+ new ol.layer.TileLayer({
+ source: new ol.source.OSM()
+ })
+ ],
+ renderers: ol.RendererHints.createFromQueryData(),
+ target: 'map',
+ view: new ol.View2D({
+ center: [0, 0],
+ zoom: 2
+ })
+});
+var view = map.getView();
+
+var deviceOrientation = new ol.DeviceOrientation();
+var track = new ol.dom.Input(document.getElementById('track'));
+track.bindTo('checked', deviceOrientation, 'tracking');
+
+deviceOrientation.on('change', function(event) {
+ document.getElementById('alpha').innerHTML = event.target.getAlpha();
+ document.getElementById('beta').innerHTML = event.target.getBeta();
+ document.getElementById('gamma').innerHTML = event.target.getGamma();
+ document.getElementById('heading').innerHTML = event.target.getHeading();
+});
+
+// tilt the map
+deviceOrientation.on(['change:beta', 'change:gamma'], function(event) {
+ var center = view.getCenter();
+ var resolution = view.getResolution();
+ var beta = event.target.getBeta() || 0;
+ var gamma = event.target.getGamma() || 0;
+
+ center[0] -= resolution * gamma * 25;
+ center[1] += resolution * beta * 25;
+
+ view.setCenter(center);
+});
diff --git a/externs/w3c_device_sensor_event.js b/externs/w3c_device_sensor_event.js
new file mode 100644
index 0000000000..ee3fba15b4
--- /dev/null
+++ b/externs/w3c_device_sensor_event.js
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2013 The Closure Compiler Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @fileoverview Definitions for W3C's device orientation and device motion
+ * events specification.
+ * This file depends on w3c_event.js.
+ * The whole file has been partially type annotated.
+ * Created from http://dev.w3.org/geo/api/spec-source-orientation.
+ *
+ * @externs
+ */
+
+/**
+ * @constructor
+ * @extends {Event}
+ */
+function DeviceOrientationEvent() {}
+
+/** @type {?number} */
+DeviceOrientationEvent.prototype.alpha;
+
+/** @type {?number} */
+DeviceOrientationEvent.prototype.beta;
+
+/** @type {?number} */
+DeviceOrientationEvent.prototype.gamma;
+
+/** @type {boolean} */
+DeviceOrientationEvent.prototype.absolute;
+
+/**
+ * @constructor
+ */
+function DeviceAcceleration() {}
+
+/** @type {?number} */
+DeviceAcceleration.prototype.x;
+
+/** @type {?number} */
+DeviceAcceleration.prototype.y;
+
+/** @type {?number} */
+DeviceAcceleration.prototype.z;
+
+/**
+ * @constructor
+ */
+function DeviceRotationRate() {}
+
+/** @type {?number} */
+DeviceOrientationEvent.prototype.alpha;
+
+/** @type {?number} */
+DeviceOrientationEvent.prototype.beta;
+
+/** @type {?number} */
+DeviceOrientationEvent.prototype.gamma;
+
+/**
+ * @constructor
+ * @extends {Event}
+ */
+function DeviceMotionEvent() {}
+
+/** @type {?DeviceAcceleration} */
+DeviceMotionEvent.prototype.acceleration;
+
+/** @type {?DeviceAcceleration} */
+DeviceMotionEvent.prototype.accelerationIncludingGravity;
+
+/** @type {?DeviceRotationRate} */
+DeviceMotionEvent.prototype.rotationRate;
+
+/** @type {?number} */
+DeviceMotionEvent.prototype.interval;
diff --git a/src/objectliterals.jsdoc b/src/objectliterals.jsdoc
index 47630acd77..f5be363af5 100644
--- a/src/objectliterals.jsdoc
+++ b/src/objectliterals.jsdoc
@@ -1,3 +1,8 @@
+/**
+ * @typedef {Object} ol.DeviceOrientationOptions
+ * @property {boolean|undefined} tracking Tracking.
+ */
+
/**
* @typedef {Object} ol.GeolocationOptions
* @property {boolean|undefined} tracking Tracking.
diff --git a/src/ol/deviceorientation.exports b/src/ol/deviceorientation.exports
new file mode 100644
index 0000000000..05be8f4887
--- /dev/null
+++ b/src/ol/deviceorientation.exports
@@ -0,0 +1,2 @@
+@exportClass ol.DeviceOrientation ol.DeviceOrientationOptions
+@exportSymbol ol.DeviceOrientation.SUPPORTED
diff --git a/src/ol/deviceorientation.js b/src/ol/deviceorientation.js
new file mode 100644
index 0000000000..cd1126d76d
--- /dev/null
+++ b/src/ol/deviceorientation.js
@@ -0,0 +1,180 @@
+goog.provide('ol.DeviceOrientation');
+goog.provide('ol.DeviceOrientation.SUPPORTED');
+goog.provide('ol.DeviceOrientationProperty');
+
+goog.require('goog.events');
+goog.require('goog.math');
+goog.require('ol.Object');
+
+
+/**
+ * @enum {string}
+ */
+ol.DeviceOrientationProperty = {
+ ALPHA: 'alpha',
+ BETA: 'beta',
+ GAMMA: 'gamma',
+ HEADING: 'heading',
+ TRACKING: 'tracking'
+};
+
+
+
+/**
+ * @constructor
+ * @extends {ol.Object}
+ * @param {ol.DeviceOrientationOptions=} opt_options Options.
+ */
+ol.DeviceOrientation = function(opt_options) {
+
+ /**
+ * @private
+ * @type {?number}
+ */
+ this.listenerKey_ = null;
+
+ goog.events.listen(this,
+ ol.Object.getChangeEventType(ol.DeviceOrientationProperty.TRACKING),
+ this.handleTrackingChanged_, false, this);
+
+ goog.base(this, goog.isDef(opt_options) ? opt_options : {});
+
+};
+goog.inherits(ol.DeviceOrientation, ol.Object);
+
+
+/**
+ * @inheritDoc
+ */
+ol.DeviceOrientation.prototype.disposeInternal = function() {
+ this.setTracking(false);
+ goog.base(this, 'disposeInternal');
+};
+
+
+/**
+ * Is supported.
+ * @const
+ * @type {boolean}
+ */
+ol.DeviceOrientation.SUPPORTED = 'DeviceOrientationEvent' in window;
+
+
+/**
+ * @private
+ * @param {goog.events.BrowserEvent} browserEvent Event.
+ */
+ol.DeviceOrientation.prototype.orientationChange_ = function(browserEvent) {
+ var event = /** @type {DeviceOrientationEvent} */
+ (browserEvent.getBrowserEvent());
+ if (goog.isDefAndNotNull(event.alpha)) {
+ var alpha = goog.math.toRadians(event.alpha);
+ this.set(ol.DeviceOrientationProperty.ALPHA, alpha);
+ // event.absolute is undefined in iOS.
+ if (goog.isBoolean(event.absolute) && event.absolute) {
+ this.set(ol.DeviceOrientationProperty.HEADING, alpha);
+ }
+ }
+ if (goog.isDefAndNotNull(event.beta)) {
+ this.set(ol.DeviceOrientationProperty.BETA,
+ goog.math.toRadians(event.beta));
+ }
+ if (goog.isDefAndNotNull(event.gamma)) {
+ this.set(ol.DeviceOrientationProperty.GAMMA,
+ goog.math.toRadians(event.gamma));
+ }
+};
+
+
+/**
+ * @return {number|undefined} alpha.
+ */
+ol.DeviceOrientation.prototype.getAlpha = function() {
+ return /** @type {number} */ (
+ this.get(ol.DeviceOrientationProperty.ALPHA));
+};
+goog.exportProperty(
+ ol.DeviceOrientation.prototype,
+ 'getAlpha',
+ ol.DeviceOrientation.prototype.getAlpha);
+
+
+/**
+ * @return {number|undefined} beta.
+ */
+ol.DeviceOrientation.prototype.getBeta = function() {
+ return /** @type {number} */ (
+ this.get(ol.DeviceOrientationProperty.BETA));
+};
+goog.exportProperty(
+ ol.DeviceOrientation.prototype,
+ 'getBeta',
+ ol.DeviceOrientation.prototype.getBeta);
+
+
+/**
+ * @return {number|undefined} gamma.
+ */
+ol.DeviceOrientation.prototype.getGamma = function() {
+ return /** @type {number} */ (
+ this.get(ol.DeviceOrientationProperty.GAMMA));
+};
+goog.exportProperty(
+ ol.DeviceOrientation.prototype,
+ 'getGamma',
+ ol.DeviceOrientation.prototype.getGamma);
+
+
+/**
+ * @return {number|undefined} heading.
+ */
+ol.DeviceOrientation.prototype.getHeading = function() {
+ return /** @type {number} */ (
+ this.get(ol.DeviceOrientationProperty.HEADING));
+};
+goog.exportProperty(
+ ol.DeviceOrientation.prototype,
+ 'getHeading',
+ ol.DeviceOrientation.prototype.getHeading);
+
+
+/**
+ * @return {boolean|undefined} tracking.
+ */
+ol.DeviceOrientation.prototype.getTracking = function() {
+ return /** @type {boolean} */ (
+ this.get(ol.DeviceOrientationProperty.TRACKING));
+};
+goog.exportProperty(
+ ol.DeviceOrientation.prototype,
+ 'getTracking',
+ ol.DeviceOrientation.prototype.getTracking);
+
+
+/**
+ * @private
+ */
+ol.DeviceOrientation.prototype.handleTrackingChanged_ = function() {
+ if (ol.DeviceOrientation.SUPPORTED) {
+ var tracking = this.getTracking();
+ if (tracking && goog.isNull(this.listenerKey_)) {
+ this.listenerKey_ = goog.events.listen(window, 'deviceorientation',
+ this.orientationChange_, false, this);
+ } else if (!tracking && !goog.isNull(this.listenerKey_)) {
+ goog.events.unlistenByKey(this.listenerKey_);
+ this.listenerKey_ = null;
+ }
+ }
+};
+
+
+/**
+ * @param {boolean} tracking Enable or disable tracking.
+ */
+ol.DeviceOrientation.prototype.setTracking = function(tracking) {
+ this.set(ol.DeviceOrientationProperty.TRACKING, tracking);
+};
+goog.exportProperty(
+ ol.DeviceOrientation.prototype,
+ 'setTracking',
+ ol.DeviceOrientation.prototype.setTracking);