この記事ではJavaScriptから加速度センサーを利用する例として、スマートフォンやタブレットなどの端末の傾きに応じて画面上のボールを動かす処理のコード例を示します。
イメージ
サンプル
端末の傾きに応じてボールを動かす
※注)上記サンプルは、スマートフォンまたはタブレットで確認できます。
最新のスマホならかなりスムーズに動くと思います。
ちなみにスマホを家の床に置いてこのサンプルを実行すれば、家の傾きも検出できるかも。(我が家は傾いていました!)
加速度センサー値取得の基本をご覧になりたい方は、以下を参考にして下さい。
ボールが動いているように見せる考え方
今回のプログラムは以下のイメージで動いているように見せています。
プログラム自体は、大きく3つに分けました。
1.加速度センサー値を取得する部分(deviceorientationイベント)
2.ボールクラス(Ballクラス)
3.ボールをアニメーションさせる部分(関数mainLoop)
ボールのアニメーション処理は、requestAnimationFrame関数を利用してゲームループ(無限ループ)にします。
加速度センサーのイベント(deviceorientationイベント)で取得した値をBallクラスで定義されたボールのxy座標に加算して動いているように見せます。
以下でそれぞれ詳しく説明します。
加速度センサー値を取得する部分(deviceorientationイベント)
加速度センサー値の取得は、deviceorientationイベントを利用します。
加速度センサー値のプロパティには3方向あり、alpha, beta, gammaとなります。
今回のボールを端末の傾きに応じて動かす処理の場合だと、betaとgammaプロパティだけで十分です。
また、取得した加速度センサーの値を別の関数やクラスから利用するため、xとyのプロパティを持つグローバル変数vecを定義してdeviceorientationイベント発生時に加速度センサー値を変数vecに代入するようにします。
実際のJavaScript部分です。
/* * グローバル変数 */ var vec = {x: 0, y: 0 }; // 加速度センサー値格納用 /* * 加速度センサーの値を取得 */ window.addEventListener("deviceorientation", function(e){ vec.x = e.gamma; // x方向の移動量 vec.y = e.beta; // y方向の移動量 }, false);
ただ実際にボールを動かしてみるとかなり速い動きだったので、サンプルでは、取得した値を減らしてゆっくりとした動きに変えています。(単純にgammaとbetaを5で割って利用しているだけですが…)
こんな感じ。
/* * 加速度センサーの値を取得 */ window.addEventListener("deviceorientation", function(e){ vec.x = e.gamma / 5; // x方向の移動量: そのままでは大きい為、小さくする vec.y = e.beta / 5; // y方向の移動量: 〃 }, false);
ボールクラス(Ballクラス)
Ballクラスは、キャンバス上にボール(のようなただの塗りつぶし円)を表示するためのクラスです。
/* * ボールクラス */ class Ball{ constructor(x, y, r){ this.x = x; // x座標 this.y = y; // y座標 this.r = r; // 半径 } draw(){ // 位置を計算 this.x += vec.x; this.y += vec.y; // 円を描画(塗りつぶし円) g.beginPath(); g.fillStyle = "orange"; g.arc(this.x, this.y, this.r, 0, Math.PI*2, false); g.fill(); }; };
ボールの初期位置と半径をコンストラクタの引数x, y, rで設定しています。
constructor(x, y, r){ this.x = x; // x座標 this.y = y; // y座標 this.r = r; // 半径 }
ボールの表示は、drawメソッドを使います。
draw(){ // 位置を計算 this.x += vec.x; this.y += vec.y; // 円を描画(塗りつぶし円) g.beginPath(); g.fillStyle = "orange"; g.arc(this.x, this.y, this.r, 0, Math.PI*2, false); g.fill(); };
ポイントは、ボールの位置を計算している部分です。
HTMLのcanvasタグのx座標とy座標に加速度センサーのプロパティ値を照らし合わせると
x座標 | 加速度センサーのgammaプロパティ |
y座標 | 加速度センサーのbetaプロパティ |
がベストでした。
という訳で、
ボールのx座標 = 現在のx座標 + 加速度センサーのgamma値
ボールのy座標 = 現在のy座標 + 加速度センサーのbeta値
という計算をしてボールが加速度センサーの傾きに応じて動いているように見せることが出来ました。
ソースコードでは以下の部分です。
// 位置を計算 this.x += vec.x; this.y += vec.y;
ボールをアニメーションさせる部分(関数mainLoop)
最後にアニメーション処理をして、ボールの一定間隔での表示を行います。
アニメーション表示には、関数をブラウザのリフレッシュレートに合わせて実行させるrequestAnimationFrame関数を使います。
例えば、mainLoopという関数を一定間隔で実行したいときは、
function mainLoop(){ // 実行したい処理 // : // 再帰呼び出し requestAnimationFrame(mainLoop); }
といった再帰呼び出し(関数内で自らを呼び出す)という方法をとります。
今回この関数で実行したい処理は、
キャンバスの画面クリアとボールを描画する処理の2つです。
キャンバスの長方形塗りつぶし命令のfillRectとBallクラスのdrawメソッドを利用して以下のようにしています。
/* * ゲームループ */ function mainLoop(){ // 画面クリア g.fillStyle = "#ddd"; g.fillRect(0, 0, canvas.width, canvas.height); // ボールを描く ball.draw(); // 再帰呼び出し requestAnimationFrame(mainLoop); }
プログラム全体
プログラム全体を示します。
プログラムファイルは、index.html(HTML部分)とmain.js(JavaScript部分)に分かれています。
どうでしょうか?
動きましたか?加速度センサーを利用して何が出来るか考えてみるのも面白いですよ!
ぜひプログラミングを楽しんで下さい。
コメント