この記事では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部分)に分かれています。
どうでしょうか?
動きましたか?加速度センサーを利用して何が出来るか考えてみるのも面白いですよ!
ぜひプログラミングを楽しんで下さい。


コメント