iOS4以降はsafariのJavaScriptから差速度センサの入力が取れるらしいので試してみた。
  • 参考1:http://d.hatena.ne.jp/nakamura001/20101128/1290942715
  • 参考2:http://blog.asial.co.jp/788

大雑把な使い方はこれだけ。

window.addEventListener("devicemotion", function(ev){ var g = ev.accelerationIncludingGravity; // == {x,y} 傾き var a = ev.acceleration; // == {x,y,z} 加速度 }, true);

第3パラメータの true はイベント優先度。 リアルタイム性が必要な時は指定した方が良い。

y軸は画面系の座標と±が逆になる。

値を数字で表示して見てもつまらないので画面上でビー玉を転がしてみた。

サンプル:ビー玉が転がるだけ

  • http://wsjs-gae.appspot.com/RollingMarble
    (iOS5のiPod4,iPhone4でしか確認してません)

    (ビー玉の画像は http://www.ritart.net/botan.html からお借りしました。)

結構リアルに転がってますw
反応も思いの他良くこれならちょっとしたゲームくらい作れそうです。

ソース:

<html> <head> <meta http-equiv="content-type" content="text/html; charset=utf-8"> <meta content="minimum-scale=1.0, width=device-width, maximum-scale=1.0, name="viewport"> <meta name="format-detection" content="telephone=no"> <meta name="apple-mobile-web-app-capable" content="yes"> <meta name="apple-mobile-web-app-status-bar-style" content="black"> <script> function onLoad() { RollingMarble.instance = new RollingMarble(); // 加速度センサ イベント登録 window.addEventListener("devicemotion", function(ev){ RollingMarble.instance.marble.accele(ev.accelerationIncludingGravity); }, true); // PCデバック用キー入力 イベント登録 document.onkeydown = function(ev){ var g = {x:0, y:0}; switch(ev.keyCode) { case 37: g={x:-0.5, y:0}; break; //← case 38: g={x:0, y:0.5}; break; //↑ case 39: g={x:0.5, y:0}; break; //→ case 40: g={x:0, y:-0.5}; break; //↓ default: } RollingMarble.instance.marble.accele(g); }; RollingMarble.instance.start(); } function RollingMarble() { this.instance = null; this.marble = new Marble("marble"); this.stage = new Stage("stage"); } (function(Class) { Class.prototype.start = function() { setTimeout(ticker, 25); } function ticker() { Class.instance.marble.action(); setTimeout(ticker, 25); } })(RollingMarble); function Marble(id) { this.img = document.getElementById(id); this.w = this.img.width; this.h = this.img.height; this.img.style.position = "absolute"; this.reset(); } (function(Class) { Class.prototype.reset = function() { this.isDropping = false; this.x = Stage.W/2; this.y = Stage.H/2; this.gx = 0; this.gy = 0; this.img.width = this.w; this.img.style.left = Math.floor(this.x-this.w/2)+"px"; this.img.style.top = Math.floor(this.y-this.h/2)+"px"; } Class.prototype.accele = function(grav) { this.gx += grav.x/2; this.gy -= grav.y/2; // 上下は逆 } Class.prototype.action = function() { if (this.isDropping) return this.dropping(); with (this) { x += gx; y += gy; if (x < 0) drop(-w/2, y); else if (x > Stage.W) drop(Stage.W+w/2, y); if (y < 0) drop(x, -h/2); else if (y > Stage.H) drop(x, Stage.H+h/2); img.style.left = Math.floor(x-w/2)+"px"; img.style.top = Math.floor(y-h/2)+"px"; } } Class.prototype.drop = function(x, y) { this.x = x; this.y = y; this.isDropping = true; } Class.prototype.dropping = function() { with (this) { img.width *= 0.9; img.style.left = Math.floor(x-(img.width/2))+"px"; img.style.top = Math.floor(y-(img.width/2))+"px"; if (img.width < 5) reset(); } } })(Marble); function Stage(id) { this.div = document.getElementById(id); this.div.style.width = Stage.W+"px"; this.div.style.height = Stage.H+"px"; this.div.style.left = "60px"; this.div.style.top = "60px"; this.div.style.position = "absolute"; this.div.style.backgroundColor = "white"; }; (function(Class) { Class.W = 600; Class.H = 600; })(Stage); </script> <style> body{ background: black; } </style> </head> <body onload="onLoad()"> <div id="stage"> <img id="marble" src="blue-ball.png" /> </div> </body> </html>