スマホの傾きを可視化する

Milkcocoaをメッセージブローカーとして、エッジ(今回はスマホ)の情報を可視化（ブラウザに表示）してみたいと思います。

今回は、スマホの傾き情報を送り、板（スマホ本体をイメージ）を回転させて、傾きを表現したいと思います。

# メッセージブローカーの準備
[Milkcocoa](https://mlkcca.com/)にアプリを用意し、ここを経由して情報のやり取りをします。
![image1.png](https://qiita-image-store.s3.amazonaws.com/0/130771/f94f9b2b-61e5-1e5a-974b-ebd8757364a8.png)
特別なことをする必要はなく、単純にアプリを作成します。
とりあえずここでは「rotate」という名前で作っておきます。
![image1.png](https://qiita-image-store.s3.amazonaws.com/0/130771/ef92263c-b8d5-5556-2f4a-fc40cce92676.png)

# 可視化の準備
スマホから送られてきた情報を可視化する方法として、今回は[A-Frame](https://aframe.io/)を使用します。
![image2.png](https://qiita-image-store.s3.amazonaws.com/0/130771/cabb0e1f-336e-27c0-de2f-7d68378cd4f7.png)

ここではA-Frameの詳しい説明は省きますが、HTMLチックに3Dモデリング＆レンダリングができる言語と思っていただければよいかと思います。

まずは簡単な長方形を表示させます。

```index.html
<!doctype html>
<html>
  <head>
    <title>My first VR site</title>
    <script src="https://aframe.io/releases/latest/aframe.min.js"></script>
  </head>
  <body>
    <a-scene>
      <a-cube width="0.65" height="1.25" depth="0.05" position="0 0 0" rotation="0 0 0"></a-cube>
    </a-scene>
  </body>
</html>
```
![image3.png](https://qiita-image-store.s3.amazonaws.com/0/130771/ac7e9933-68ed-1b85-47c5-85619aba4074.png)

ここに、Milckcocoaとのやり取りに関するスクリプトを追加します。

```index.html
<!doctype html>
<html>
  <head>
    <title>My first VR site</title>
    <script src='https://cdn.mlkcca.com/v0.6.0/milkcocoa.js'></script>
    <script src="https://aframe.io/releases/latest/aframe.min.js"></script>
    <script>
        window.onload = function(){
            var milkcocoa = MilkCocoa.connectWithApiKey('app_id.mlkcca.com', 'API_Key', 'API_Secret');
            var ds = milkcocoa.dataStore('rotate');

            ds.on('send', changeViewFromSentRotate);

            var cube = document.querySelector('a-cube');

            function changeViewFromSentRotate(sent){
               cube.setAttribute('rotation', sent.value.x+90 + ' ' + sent.value.y + ' ' + sent.value.z*-1);
            }
        };
    </script>
  </head>
  <body>
    <a-scene>
      <a-cube width="0.65" height="1.25" depth="0.05" position="0 0 0" rotation="0 0 0"></a-cube>
    </a-scene>
  </body>
</html>
```
「'app_id.mlkcca.com', 'API_Key', 'API_Secret'」のところは各自の設定に書き換えてください。

なお、スマホと描画を一致させるため、姑息な回転処理をしています。

# スマホ側の準備

スマホ側は、専用アプリではなくWebブラウザからスマホの情報を送るようにします。
デバイスの情報をJavaScriptで取得するには「Device Orientation Event」てやつを利用します。
また、秒単位の変位ではなく絶対的な回転情報が欲しいので、「devicemotion」ではなく「deviceorientation」イベントで値を取得します。

```index.html
<body>
<div id="output"></div>
<script src='https://cdn.mlkcca.com/v0.6.0/milkcocoa.js'></script>
<script>
window.onload = function(){
  var output = document.getElementById('output');

  var milkcocoa = MilkCocoa.connectWithApiKey('app_id.mlkcca.com', 'API_Key', 'API_Secret');
  var ds = milkcocoa.dataStore('rotate');

  window.addEventListener('deviceorientation', function(e){
    output.innerHTML
    = 'z方向: '+e.alpha
    + '<br>x方向: '+e.beta
    + '<br>y方向: '+e.gamma;

    sendModeFromGravityValue(e);
  },true);

  function sendModeFromGravityValue(r){
    ds.send({x: r.beta, y:r.gamma, z:r.alpha});
  }
};
</script>
</body>
```
こちらも「'app_id.mlkcca.com', 'API_Key', 'API_Secret'」のところは各自の設定に書き換えてください。

また、どの値がどの回転軸の値か、またプラスマイナスはどっち方向かに注意してください。
ちなみに単位は「度」です。

# Webサーバに配置

ここまでに作成した、PC側、および、スマホ側のHTMLをWebサーバに置きます。
今回は無料のホスティングサービスである[BitBalloon](https://www.bitballoon.com/)を使用します。
![image5.png](https://qiita-image-store.s3.amazonaws.com/0/130771/5279ec5b-39bb-be51-20ed-d53bfb87f932.png)

アカウントを作っておけば、アップロードしたファイルがちゃんと保存されます。
![image4.png](https://qiita-image-store.s3.amazonaws.com/0/130771/db0a6aca-dcb5-5ae8-ae0e-ae79e2fcde81.png)

こちらのPC用／スマホ用のHTMLを置いておきます。
なお、スマホ用のHTMLのURLは、QRコードにしておくと後でアクセスが楽になります。

# 実行結果

実行した結果がこちらです。

・スマホ画面
![Screenshot_20170218-144304.png](https://qiita-image-store.s3.amazonaws.com/0/130771/3f0c5245-c6e8-fb03-f1d4-733c50854706.png)

・PC画面
![image6.png](https://qiita-image-store.s3.amazonaws.com/0/130771/5cc08682-e87e-9be0-d5f0-a924c8aa6898.png)

ちゃんと同期して動きます。
（少しづつズレていくのはご愛嬌 ^^;）

# まとめ

結構簡単にスマホとPCがブローカーを経由してつながります。
もうちょっと見た目を工夫（大きさとかテクスチャとか）すれば、結構いけてる感じになるような気がします。

さらに、実はA-FrameはWebVRのためのものですので、Occulus等で見ると、もっとリアルに感じるかも？！