-
-
Save msurguy/a42df496e06b91a8f60384ee62ab69b5 to your computer and use it in GitHub Desktop.
[html5][devicemotion]live demo of devicemoton event
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!doctype html> | |
<html> | |
<head> | |
<meta charset="utf-8" /> | |
<title>devicemotion event</title> | |
<script src="script.js"></script> | |
</head> | |
<body> | |
<h1>devicemotion event demo</h1> | |
<p> | |
Unit of value is m/s^2(g = +9.8). | |
The device orientation is not effect axes and values. | |
</p> | |
<p> | |
Axes of portrait device, x: right(-) to left(+), y: top(-) to bottom(+), | |
z: front(-) to rear(+) | |
</p> | |
<div><h2>Acceleration (w/o Gravity)</h2> | |
<ul> | |
<li>x: <input id="x1" type="range" max="20.0" min="-20.0" | |
readonly="readonly"/> | |
<input id="x1n" type="number" max="20.0" min="-20.0" | |
readonly="readonly"/> | |
</li> | |
<li>y: <input id="y1" type="range" max="20.0" min="-20.0" | |
readonly="readonly"/> | |
<input id="y1n" type="number" max="20.0" min="-20.0" | |
readonly="readonly"/> | |
</li> | |
<li>z: <input id="z1" type="range" max="20.0" min="-20.0" | |
readonly="readonly"/> | |
<input id="z1n" type="number" max="20.0" min="-20.0" | |
readonly="readonly"/> | |
</li> | |
<li>abs: <input id="abs1" type="range" max="20.0" min="-20.0" | |
readonly="readonly"/> | |
<input id="abs1n" type="number" max="20.0" min="-20.0" | |
readonly="readonly"/> | |
</li> | |
</ul> | |
</div> | |
<div><h2>Acceleration (w/ Gravity)</h2> | |
<ul> | |
<li>x: <input id="x2" type="range" max="20.0" min="-20.0" | |
readonly="readonly"/> | |
<input id="x2n" type="number" max="20.0" min="-20.0" | |
readonly="readonly"/> | |
</li> | |
<li>y: <input id="y2" type="range" max="20.0" min="-20.0" | |
readonly="readonly"/> | |
<input id="y2n" type="number" max="20.0" min="-20.0" | |
readonly="readonly"/> | |
</li> | |
<li>z: <input id="z2" type="range" max="20.0" min="-20.0" | |
readonly="readonly"/> | |
<input id="z2n" type="number" max="20.0" min="-20.0" | |
readonly="readonly"/> | |
</li> | |
<li>abs: <input id="abs2" type="range" max="20.0" min="-20.0" | |
readonly="readonly"/> | |
<input id="abs2n" type="number" max="20.0" min="-20.0" | |
readonly="readonly"/> | |
</li> | |
</ul> | |
</div> | |
<div><h2>Acceleration (vertical/horizontal)</h2> | |
<ul> | |
<li>v: <input id="v" type="range" max="20.0" min="-20.0" | |
readonly="readonly"/> | |
<input id="vn" type="number" max="20.0" min="-20.0" | |
readonly="readonly"/> | |
</li> | |
<li>h: <input id="h" type="range" max="20.0" min="-20.0" | |
readonly="readonly"/> | |
<input id="hn" type="number" max="20.0" min="-20.0" | |
readonly="readonly"/> | |
</li> | |
</ul> | |
</div> | |
<div> | |
Walk counter: <span id="counter">0</span> | |
steps | |
<button id="reset" style="padding: 5px 30px; border-radius: 10px;" | |
>reset</button> | |
</div> | |
<div> | |
<canvas id="xyview" | |
style="width: 200px; height: 200px; background-color: lightgray" | |
width="200" height="200"></canvas> | |
<canvas id="zview" | |
style="width: 600px; height: 200px; background-color: lightgray" | |
width="600" height="200"></canvas> | |
</div> | |
<div> | |
<ul> | |
<li><span style="color: red">raw value</span></li> | |
<li><span style="color: blue">low-pass filtered value</span></li> | |
</ul> | |
</div> | |
<div id="log"></div> | |
<div><a href="https://gist.github.com/bellbind/c885f85a0dd0e4681ee5"> | |
gist source</a></div> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;window.addEventListener("load", function () { | |
"use strict"; | |
// vec math | |
var add = function (a, b) { | |
return {x: a.x + b.x, y: a.y + b.y, z: a.z + b.z}; | |
}; | |
var sub = function (a, b) { | |
return {x: a.x - b.x, y: a.y - b.y, z: a.z - b.z}; | |
}; | |
var dot = function (a, b) { | |
return a.x*b.x + a.y*b.y + a.z*b.z; | |
}; | |
var cross = function (a, b) { | |
return {x: a.y*b.z-a.z*b.y, y: a.z*b.x-a.x*b.z, z: a.x*b.y-a.y*b.x}; | |
}; | |
var mul = function (r, v) { | |
return {x: r * v.x, y: r * v.y, z: r *v.z}; | |
}; | |
var abs = function (a) { | |
return Math.sqrt(dot(a, a)); | |
}; | |
// split vertical/horizontal elements of acceleration | |
var splitVH = function (ev) { | |
var acc = ev.acceleration, accg = ev.accelerationIncludingGravity; | |
// calc gravity element | |
var g = sub(accg, acc); | |
var gl = abs(g); | |
var ez = mul(1/gl, g); // unit vector | |
// calc vertical(= gravity direction) part | |
var vl = dot(acc, ez); | |
var v = mul(vl, ez); | |
// split horizontal(= orthogonal plane of gravity) part | |
var h = sub(acc, v); | |
// orthogonal plane elements(y: top-bottom, x: right->left) | |
// (as left hand system) | |
var ex = cross({x: 0, y: 1, z: 0}, ez); | |
var ey = cross(ez, ex); | |
var yl = dot(h, ey); | |
var xl = dot(h, ex); | |
return { | |
a: {x: acc.x, y: acc.y, z: acc.z}, | |
ag: {x: accg.x, y: accg.y, z: accg.z}, | |
v: v, h: h, ez: ez, vl: vl, ex: ex, ey: ey, xl: xl, yl: yl | |
}; | |
}; | |
// Record acceleration data at devicemotion event for views | |
// NOTE: not drawing in "devicemotion" event handlers because of delaying | |
var lastvh = null; | |
var xl = 0.0; | |
var yl = 0.0; | |
var zlsize = 300; | |
var zl1s = new Array(zlsize); | |
var zl2s = new Array(zlsize); | |
for (var i = 0; i < zlsize; i++) zl1s[i] = zl2s[i] = 0.0; | |
var cur = 0; | |
var recordXYZ = function (vh) { | |
lastvh = vh; | |
xl = 0.9 * xl + 0.1 * vh.xl; | |
yl = 0.9 * yl + 0.1 * vh.yl; | |
cur = (cur + 1) % zlsize; | |
zl1s[cur] = vh.vl; | |
zl2s[cur] = 0.9 * zl2s[(zlsize + cur - 1) % zlsize] + 0.1 * vh.vl; | |
}; | |
// view of direct event acceleration values | |
var v1 = { | |
x: document.getElementById("x1"), | |
y: document.getElementById("y1"), | |
z: document.getElementById("z1"), | |
abs: document.getElementById("abs1"), | |
xn: document.getElementById("x1n"), | |
yn: document.getElementById("y1n"), | |
zn: document.getElementById("z1n"), | |
absn: document.getElementById("abs1n"), | |
}; | |
var v2 = { | |
x: document.getElementById("x2"), | |
y: document.getElementById("y2"), | |
z: document.getElementById("z2"), | |
abs: document.getElementById("abs2"), | |
xn: document.getElementById("x2n"), | |
yn: document.getElementById("y2n"), | |
zn: document.getElementById("z2n"), | |
absn: document.getElementById("abs2n"), | |
}; | |
var showAccel = function (v, accel) { | |
v.x.value = v.xn.value = accel.x; | |
v.y.value = v.yn.value = accel.y; | |
v.z.value = v.zn.value = accel.z; | |
v.abs.value = v.absn.value = abs(accel); | |
}; | |
// view of vertical/horizontal elements in acceleration | |
var vhview = { | |
v: document.getElementById("v"), | |
vn: document.getElementById("vn"), | |
h: document.getElementById("h"), | |
hn: document.getElementById("hn"), | |
}; | |
var showVH = function (vh) { | |
vhview.v.value = vhview.vn.value = Math.abs(vh.vl); | |
vhview.h.value = vhview.hn.value = abs(vh.h); | |
}; | |
// x-y accel view | |
var xyview = document.getElementById("xyview"); | |
var drawXY = function (vh) { | |
var c2d = xyview.getContext("2d"); | |
var w = xyview.width, h = xyview.height, unit = w / 20; | |
c2d.clearRect(0, 0, w, h); | |
c2d.save(); | |
c2d.beginPath(); | |
c2d.arc(w/2, h/2, unit * 5, 0, 2*Math.PI); | |
c2d.strokeStyle = "black"; | |
c2d.lineWidth = 3; | |
c2d.stroke(); | |
c2d.restore(); | |
c2d.save(); | |
c2d.translate(w/2, h/2); | |
c2d.beginPath(); | |
c2d.moveTo(0, 0); | |
c2d.lineTo(vh.xl * -unit, vh.yl * unit); | |
c2d.strokeStyle = "red"; | |
c2d.lineWidth = 3; | |
c2d.stroke(); | |
c2d.beginPath(); | |
c2d.moveTo(0, 0); | |
c2d.lineTo(xl * -unit, yl * unit); | |
c2d.strokeStyle = "blue"; | |
c2d.lineWidth = 3; | |
c2d.stroke(); | |
c2d.restore(); | |
}; | |
// z accel view | |
var zview = document.getElementById("zview"); | |
var drawZ = function (vh) { | |
var c2d = zview.getContext("2d"); | |
var w = zview.width, h = zview.height; | |
c2d.clearRect(0, 0, w, h); | |
c2d.lineWidth = 2; | |
c2d.beginPath(); | |
c2d.moveTo(0, h/2); | |
c2d.lineTo(w, h/2); | |
c2d.strokeStyle = "black"; | |
c2d.stroke(); | |
drawChart(c2d, zl1s, "red"); | |
drawChart(c2d, zl2s, "blue"); | |
}; | |
var drawChart = function (c2d, data, stroke) { | |
var start = (cur + 1) % zlsize; | |
var x = 0; | |
var dx = zview.width / zlsize; | |
var unit = zview.height / 20, center = zview.height / 2; | |
c2d.beginPath(); | |
c2d.moveTo(x, center + data[start] * -unit); | |
for (var i = (start + 1) % zlsize; i < zlsize; i++) { | |
x += dx; | |
c2d.lineTo(x, center + data[i] * -unit); | |
} | |
for (var i = 0; i < start; i++) { | |
x += dx; | |
c2d.lineTo(x, center + data[i] * -unit); | |
} | |
c2d.strokeStyle = stroke; | |
c2d.stroke(); | |
}; | |
// Example Application: Simple Walk Counter | |
// (state) | |
var vl = 0.0; // noise filtered value | |
var count = 0; | |
var updown = 0; | |
var thresholds = {up: 0.25, down: -0.25}; | |
// (event handler) | |
var walking = function (vh) { | |
vl = 0.9 * vl + 0.1 * vh.vl; //low-pass filtering | |
switch (updown) { | |
case -1: | |
if (vl > thresholds.up) { | |
updown = +1; | |
count += 1; | |
} | |
break; | |
case +1: | |
if (vl < thresholds.down) { | |
updown = -1; | |
} | |
break; | |
default: | |
if (vl < 0) updown = -1; | |
if (vl >= 0) updown = +1; | |
break; | |
} | |
}; | |
// (view) | |
var counter = document.getElementById("counter"); | |
var updateWalking = function () { | |
counter.textContent = count; | |
}; | |
var reset = document.getElementById("reset"); | |
reset.addEventListener("click", function () { | |
vl = 0.0; | |
count = 0; | |
updown = 0; | |
}, false); | |
// Event Handlers | |
// see: http://www.w3.org/TR/orientation-event/ | |
window.addEventListener("devicemotion", function (ev) { | |
try { | |
var vh = splitVH(ev); | |
walking(vh); | |
recordXYZ(vh); | |
} catch (ex) { | |
document.getElementById("log").textContent = ex.toString(); | |
} | |
}, false); | |
requestAnimationFrame(function loop() { | |
updateWalking(); | |
if (lastvh) { | |
showAccel(v1, lastvh.a); | |
showAccel(v2, lastvh.ag); | |
showVH(lastvh); | |
drawXY(lastvh); | |
drawZ(lastvh); | |
} | |
requestAnimationFrame(loop); | |
}); | |
}, false); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment