toioで電子ピアノを奏でる

## はじめに

[toio](https://toio.io/)が手元に届き[こちら](https://qiita.com/shinsuke-noguchi/items/037d729327232b6c0d33)で[toio.js](https://github.com/toio/toio.js)をブラウザで動かされている方がいらっしゃったので
参考にさせていただいてtoioで電子ピアノを奏でてみました。

![piano.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/485398/3e28c190-06be-5b0e-8a81-8668e0f3157f.png)

## toioとの接続

[こちら](https://qiita.com/shinsuke-noguchi/items/037d729327232b6c0d33)で紹介されていた開発環境を利用させていただきました。

```html:piano.html
<!DOCTYPE html>
<html>
<head>
	<script src="piano.js"></script>
	<title>Piano | toio</title>
</head>

<body>
	<button id="connect" >connect</button><br />
</body>
</html>
```
```javascript:piano.js
import './android-ble-patch';
import { NearestScanner } from '@toio/scanner';

window.onload = function () {

	let cube = null;

	document.getElementById('connect').addEventListener('click', async () => {
		cube = await new NearestScanner().start();
		document.getElementById('connect').innerHTML = 'connecting...';
		document.getElementById('connect').disabled = true;
		await cube.connect();
		document.getElementById('connect').innerHTML = 'connected';
	});

};
```

## 電子ピアノ

CSSは[Pure CSS3 Piano](http://cssdeck.com/labs/pure-css3-piano)を利用させていただいております。

```html:piano.html
	<div id="p-wrapper">
		<ul id="piano">
			<li><div class="anchor" data-note-name="G4"></div></li>
			<li><div class="anchor" data-note-name="A4"></div><span data-note-name="GS4"></span></li>
			<li><div class="anchor" data-note-name="B4"></div><span data-note-name="AS4"></span></li>
			<li><div class="anchor" data-note-name="C5"></div></li>
			<li><div class="anchor" data-note-name="D5"></div><span data-note-name="CS5"></span></li>
			<li><div class="anchor" data-note-name="E5"></div><span data-note-name="DS5"></span></li>
			<li><div class="anchor" data-note-name="F5"></div></li>
			<li><div class="anchor" data-note-name="G5"></div><span data-note-name="FS5"></span></li>
			<li><div class="anchor" data-note-name="A5"></div><span data-note-name="GS5"></span></li>
			<li><div class="anchor" data-note-name="B5"></div><span data-note-name="AS5"></span></li>
			<li><div class="anchor" data-note-name="C6"></div></li>
			<li><div class="anchor" data-note-name="D6"></div><span data-note-name="CS6"></span></li>
			<li><div class="anchor" data-note-name="E6"></div><span data-note-name="DS6"></span></li>
			<li><div class="anchor" data-note-name="F6"></div></li>
			<li><div class="anchor" data-note-name="G6"></div><span data-note-name="FS6"></span></li>
			<li><div class="anchor" data-note-name="A6"></div><span data-note-name="GS6"></span></li>
			<li><div class="anchor" data-note-name="B6"></div><span data-note-name="AS6"></span></li>
			<li><div class="anchor" data-note-name="C7"></div></li>
			<li><div class="anchor" data-note-name="D7"></div><span data-note-name="CS7"></span></li>
			<li><div class="anchor" data-note-name="E7"></div><span data-note-name="DS7"></span></li>
			<li><div class="anchor" data-note-name="F7"></div></li>
			<li><div class="anchor" data-note-name="G7"></div><span data-note-name="FS7"></span></li>
			<li><div class="anchor" data-note-name="A7"></div><span data-note-name="GS7"></span></li>
			<li><div class="anchor" data-note-name="B7"></div><span data-note-name="AS7"></span></li>
			<li><div class="anchor" data-note-name="C8"></div></li>
			<li><div class="anchor" data-note-name="D8"></div><span data-note-name="CS8"></span></li>
			<li><div class="anchor" data-note-name="E8"></div><span data-note-name="DS8"></span></li>
			<li><div class="anchor" data-note-name="F8"></div></li>
			<li><div class="anchor" data-note-name="G8"></div><span data-note-name="FS8"></span></li>
			<li><div class="anchor" data-note-name="A8"></div><span data-note-name="GS8"></span></li>
			<li><div class="anchor" data-note-name="B8"></div><span data-note-name="AS8"></span></li>
			<li><div class="anchor" data-note-name="C9"></div></li>
		</ul>
	</div>
```
```javascript:piano.js
	import { Note } from '@toio/cube';

	function sleepByPromise( msec ){
	  return new Promise( resolve => setTimeout( resolve, msec ));
	}

	async function playPiano( noteName ){
		if( cube && noteName ){
			await cube.playSound([{ durationMs:  2550, noteName: Note[ noteName ] }]);
		}
	}

	async function stopPiano() {
		if( cube ){
			await sleepByPromise(200);
			await cube.stopSound();
		}
	}

	document.getElementById('piano').addEventListener('touchstart', async event => {
		event.preventDefault();
		playPiano( event.target.dataset.noteName );
	});

	document.getElementById('piano').addEventListener('touchend', async event => {
		event.preventDefault();
		stopPiano();
	});
```

:information_source: 回避策をまだ検討できておりませんが `cube` を連続で叩くと反応されないため遅延を挟んでおります

## 自動演奏

最後は力技で自動演奏させてみました。
<a href="https://techlab-dev-public.s3-ap-northeast-1.amazonaws.com/toio/piano/piano.MP4">![piano_mp4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/485398/9ea4f097-7216-5a5c-09a1-c8c90e91c752.png)</a>

## お試しください

toioにアクセスできるAndroidタブレットなどで[こちら](https://techlab-dev-public.s3-ap-northeast-1.amazonaws.com/toio/piano/piano.html)をお試しください。
(toioで誕生日を祝われてみてはいかがでしょうか)