便利ページ：JavascriptでHTML5をサクッと試す

[便利ページ：Javascriptでちょっとした便利な機能を作ってみた]( https://qiita.com/poruruba/items/6c67c7eef34ed302feb3) のシリーズです。

HTML5になって久しいですが、スマホの普及もあって、たくさんの機能がブラウザだけで実現できるようになっています。
そこで、以下の機能を、ブラウザ上からサクッと使えるようにしました。(HTML5の範疇ではないものもありますが。。。)

・Audio
・Video
・Image
・GeoLocation
・加速度センサ
・端末オリエンテーション
・バッテリー
・WebUsb
・WebBluetooth
・バイブレーション
・音声発話
・音声認識
・WebCam録画

ソースコードは以下のGitHubに上げてあります。

https://github.com/poruruba/utilities

ブラウザから体験したい場合は以下にアクセスしてください。右上からHTML5を選択してください。
　https://poruruba.github.io/utilities/

主に、以下のファイルを追加しました。

``` js\comp\comp_html5.js ```

#Audio

音声ファイルを選択して、再生します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261826/5033c803-455a-70bc-a3a6-f50ab39c1501.png)

```js
    audio_read: function (files) {
      if (files.length <= 0){
        this.audio_type = "";
        return;
      }
      var file = files[0];
      this.audio_type = file.type;
      var reader = new FileReader();
      reader.onload = () => {
        var audio = document.querySelector("#html5_audio_player");
        audio.src = reader.result;
        audio.play();
      };
      reader.readAsDataURL(file);
    },
```

#Video

ビデオファイルを指定して、再生します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261826/834d3730-bf72-93c4-93d0-ec31a6edc3ca.png)

```js
    video_read: function (files) {
      if (files.length <= 0){
        this.video_type = "";
        return;
      }
      var file = files[0];
      this.video_type = file.type;
      var reader = new FileReader();
      reader.onload = () => {
        var video = document.querySelector("#html5_video_player");
        video.src = reader.result;
        video.play();
      };
      reader.readAsDataURL(file);
    },
```

#Image

画像ファイルを指定して表示します。（HTML5ではないですが。。。）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261826/e5bd5dcb-3d0c-be87-aa13-427848186594.png)

```js
    image_read: function (files) {
      if (files.length <= 0) {
        this.image_type = "";
        this.image_src = null;
        return;
      }
      var file = files[0];
      this.image_type = file.type;
      var reader = new FileReader();
      reader.onload = () => {
        this.image_src = reader.result;
      };
      reader.readAsDataURL(file);
    },
```

#GeoLocation

いわゆるGPSを取得して表示します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261826/7fbe9a2c-5c33-d73d-997a-d416ee3d2c56.png)

```js
    location_get: function(){
      navigator.geolocation.getCurrentPosition((position) =>{
        this.location = position.coords;
      }, (error) =>{
        console.error(error);
        alert(error);
      });
    },
```

#加速度センサ

端末に搭載されている加速度センサの測定値を表示します。主にスマホ用です。

```js
    motion_start: function () {
      if (!this.motion_running) {
        this.motion_running = true;
        window.addEventListener("devicemotion", this.motion_handler);
      } else {
        window.removeEventListener("devicemotion", this.motion_handler);
        this.motion_running = false;
      }
    },
    motion_handler: function(event){
      if (event.accelerationIncludingGravity.x === null ){
        window.removeEventListener("devicemotion", this.motion_handler);
        this.motion_running = false;
        this.motion_supported = false;
        return;
      }
      this.accelerationIncludingGravity = event.accelerationIncludingGravity;
      this.motion_supported = true;
    },
```

#端末オリエンテーション

端末の向きを表示します。

```js
    orientation_start: function () {
      if (!this.orientation_running) {
        this.orientation_running = true;
        window.addEventListener("deviceorientation", this.orientation_handler);
      } else {
        window.removeEventListener("deviceorientation", this.orientation_handler);
        this.orientation_running = false;
      }
    },
    orientation_handler: function (event) {
      if (event.alpha === null) {
        window.removeEventListener("deviceorientation", this.orientation_handler);
        this.orientation_running = false;
        this.orientation_supported = false;
        return;
      }
      this.orientation = event;
      this.orientation_supported = true;
    },
```

#バッテリ

バッテリの残容量等を表示します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261826/ab3aa79e-0e7f-2ead-bc86-9c8bfd431c7f.png)

```js
    battery_refresh: function(){
      navigator.getBattery()
        .then(battery => {
          this.battery = battery;
        });
    }
```

#WebUSB

WebUSBで、PCに接続されているUSBデバイスを表示します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261826/8b1f5684-8309-762a-17f2-3c120b44e147.png)

```js
    usb_request: async function () {
      try{
        var device = await navigator.usb.requestDevice({ filters: [] });
        this.usbdevice = device;
      }catch(error){
        alert(error);
      }
    },
```

#WebBluetooth

WebBluetoothで、PCの周りにあるBLEデバイスを表示します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261826/34cfde7f-b03d-dcba-8f18-50748c25c7ad.png)

```js
    ble_request: async function () {
      try{
        var device = await navigator.bluetooth.requestDevice({ acceptAllDevices: [] });
        this.bledevice = device;
      } catch (error) {
        alert(error);
      }
    },
```

#バイブレーション

端末のバイブレーションを振動させます。主にスマホ向けです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261826/ed4dd569-64cc-3b94-a70e-8847e274f5f9.png)

```js
    vibration_start: function(){
      navigator.vibrate(this.vibration_duration);
    },
```

#音声発話

入力した文章を音声でスピーカから発話します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261826/43c989bb-f656-3d5d-b434-cf9e9fc9a8fc.png)

```js
    speech_start: async function(){
      var result = await new Promise((resolve, reject) => {
        var utter = new window.SpeechSynthesisUtterance();
        utter.volume = this.speech_volume / 100;
        utter.rate = this.speech_rate / 100;
        utter.pitch = this.speech_pitch / 100;
        utter.text = this.speech_text;
        utter.lang = "ja-JP";

        var ok = false;
        var ng = false;
        utter.onend = function () {
          console.log('Event(Utter) : onend');
          if (!ok && !ng) {
            ok = true;
            resolve();
          }
        };
        utter.onstart = function () {
          console.log('Event(Utter) : onstart');
        };
        utter.onerror = function (error) {
          console.log('Event(Utter) : onerror');
          if (!ok && !ng) {
            ng = true;
            reject(error);
          }
        };

        window.speechSynthesis.cancel();
        return window.speechSynthesis.speak(utter);
      })
      .catch(error => {
        console.log(error);
      });
```

#音声認識

マイクから録音した音声から文章を認識します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261826/a037ab4e-698e-6457-ca4d-80860765d2a6.png)

```js
    speech_recognition: async function(){
      this.speech_recognized = await new Promise((resolve, reject) => {
        var recognition = new webkitSpeechRecognition();
        recognition.lang = "ja-JP";
        recognition.continuous = false;

        var match = false;
        var error = false;
        recognition.onresult = function (e) {
          console.log('Event(Recog) : onresult');
          if (!match && !error) {
            match = true;

            var text = '';
            for (var i = 0; i < e.results.length; ++i) {
              text += e.results[i][0].transcript;
            }

            resolve(text);
          }
        };
        recognition.onend = function () {
          console.log('Event(Recog) : onend');
          if (!match && !error) {
            match = true;
            reject(error);
          }
          recognition.stop();
        };
        recognition.onnomatch = function () {
          console.log('Event(Recog) : onnomatch');
          if (!match && !error) {
            error = true;
            reject('nomatch');
          }
        };
        recognition.onerror = function (e) {
          console.log('Event(Recog) : onerror : ' + JSON.stringify(e));
          if (!match && !error) {
            error = true;
            reject('onerror');
          }
        };

        recognition.start();
      })
      .catch(error => {
        console.log(error);
      });
    },
```

#WebCam録画

PCに接続されたWebCamやスマホにあるカメラで動画を録画し、ファイルに出力します。
一般的にwebm形式で保存されるようです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261826/6b4845b7-6ce5-ef66-a158-aca66a1a40da.png)

```js
    record_prepare: function(){
      this.record_dispose();

      this.record_previewing = true;
      var resolution = this.record_resolution_list[this.record_resolution];
      navigator.mediaDevices.getUserMedia({ video: { facingMode: this.record_facing, width: resolution.width, height: resolution.height }, audio: true })
        .then((stream) => {
          g_stream = stream;
          this.record_preview.srcObject = stream;
        })
        .catch(error =>{
          this.record_previewing = false;
          alert(error);
        });
    },
    record_dispose: function(){
      if( g_recorder ){
        this.record_recording = false;
        g_recorder.stop();
        g_recorder = null;
      }
      this.record_preview.pause();
      this.record_preview.srcObject = null;
      g_stream = null;
      this.record_previewing = false;
    },
    record_start: function(){
      if (g_recorder) {
        g_recorder.stop();
        g_recorder = null;
      }

      this.record_recording = true;
      this.record_chunks = [];
      g_recorder = new MediaRecorder(g_stream);
      g_recorder.ondataavailable = this.record_onavailable;
      g_recorder.onstop = this.record_onstop;
      g_recorder.start();
    },
    record_stop: function(){
      console.log('stop');
      g_recorder.stop();
    },
    record_onavailable: function (e) {
      console.log('ondataavailable');
      this.record_chunks.push(e.data);
    },
    record_onstop: function () {
      if( !this.record_recording )
        return;

      console.log('onstop');
      var blob = new Blob(this.record_chunks, { type: g_recorder.mimeType });
      this.chunks = [];
      var mimeType = g_recorder.mimeType;
      g_recorder = null;
      this.record_recording = false;

      var url = window.URL.createObjectURL(blob);
      var a = document.createElement("a");
      a.href = url;
      a.target = '_blank';
      if (mimeType.startsWith('video/x-matroska') )
        a.download = "record.webm";
      else
        a.download = "record.bin";
      a.click();
    },
```

以上