Andorid のブラウザで加速度の値を取得してグラフ表示したりローカルなファイルにセーブしたりする

# やること

タイトルそのままです。Chrome でしか動作は確認していません。多分 iOS + Safari でも動きます。下記サイトで動作を見れます。

- https://royalcrab.github.io/sample/acc_graph.html

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266247/88f05891-eb64-8903-a56f-6af001982be4.png" alt="image" height="400"/>

正常に動くと上のような感じになります。加速度センサがついてない PC などでは、加速度の値やグラフは表示されません。

# ソースコード

全体のコードは下記に置いてます。

- https://github.com/royalcrab/royalcrab.github.io/blob/master/sample/acc_graph.html

# 要点

## 加速度データの取得

下記のコードで、加速度を取得するたびに arr に加速度データを記録していきます、
- https://kkblab.com/make/javascript/acc.html
上記サイトのコードほぼそのままです。

```acc.js
     var aX = 0, aY = 0, aZ = 0; // 加速度データの記録用
     var startTime = Date.now(); // 開始時間の記録
     var arr = []; // セーブする用

     // 加速度データを取得する
     window.addEventListener("devicemotion", (dat) => {
         aX = dat.accelerationIncludingGravity.x;
         aY = dat.accelerationIncludingGravity.y;
         aZ = dat.accelerationIncludingGravity.z;
        
          arr.push( {"t": Date.now() - startTime, "x": aX, "y": aY, "z": aZ }); 
     }); 
```
## データをローカルなファイルにセーブする

arr を json に変換して、Blob を使ってダウンロードできるようにします。
- https://qiita.com/wadahiro/items/eb50ac6bbe2e18cf8813
上記ページのコードを json でダウンロードできるように変更したものです。

アンカーではなく、ボタンを押したらセーブするようにするには、少し複雑なコードを書く必要あり。

```save.js
    function handleDownload() {
        
        var blob = new Blob([ JSON.stringify(arr) ], { "type" : "application/json" });

        if (window.navigator.msSaveBlob) {
            window.navigator.msSaveBlob(blob, "acc.json");
            window.navigator.msSaveOrOpenBlob(blob, "acc.json");
        } else {
            document.getElementById("download").href = window.URL.createObjectURL(blob);
        }

        // セーブしたらデータをリセットする。リセットしたくなければ下記2行をコメントアウトする。
        arr = [];
        startTime = Date.now();
    }
```

## グラフを表示する

arr の末尾から canvas の幅と同じ pixel 分だけデータを取りだして、頭から順に線をつないで引いていっているだけです。縦方向の座標値は適当なので、端末によっては縦幅を越えて描画されるかもしれません。

```graph.js
    var canvas;
    var ctx;
    var preX = 0, preY = 0, preZ = 0; // 描画用
    // 加速度データをグラフ表示する displayData
    function displayData() {
        
        // 加速度の値を文字で表示する
        var txt = document.getElementById("txt");
        txt.innerHTML = "x: " + aX + "<br/>" + "y: " + aY + "<br/>" + "z: " + aZ;

        // canvas の背景をグレーで塗る
        if ( ! canvas || ! canvas.getContext ) { return false; }
        ctx.fillStyle = "gray";
        ctx.fillRect( 0, 0, canvas.clientWidth, canvas.clientHeight );
        ctx.lineWidth = 1 ;

        // 最新から 300px 分のデータを取りだす。
        var varr = [];
        if ( arr.length > canvas.clientWidth){
            varr = arr.slice(-canvas.clientWidth,-1);
        }else{
            varr = arr;
        }

        for ( idx in varr ){
            if ( idx > canvas.clientWidth ) break;
            var dat = varr[idx];

            // X 軸加速度を赤の線で表示する
            var dy1 = canvas.clientHeight/2 + dat.x * 10.0;
            var dx = idx;
            ctx.strokeStyle = "red";
            ctx.beginPath();
            ctx.moveTo(dx,dy1);
            ctx.lineTo(dx-1,preX);
            ctx.stroke();

            // Y 軸加速度を青の線で表示する
            var dy2 = 50 + dat.y * 10.0;
            ctx.strokeStyle = "blue";
            ctx.beginPath();
            ctx.moveTo(dx,dy2);
            ctx.lineTo(dx-1,preY);
            ctx.stroke();
            
            // Z 軸加速度を緑の線で表示する
            var dy3 = 50 + dat.z * 10.0;
            ctx.strokeStyle = "green";
            ctx.beginPath();
            ctx.moveTo(dx,dy3);
            ctx.lineTo(dx-1,preZ);
            ctx.stroke();

            // 次のデータを表示するときに前のデータから線を描く用
            preX = dy1;
            preY = dy2;
            preZ = dy3;
        }
    }
```

端末にもよりますが、それなりに高速にデータ取りつつ描画ができるので、最近のスマフォはすごいなーと思ったり。