2019/04/04
画面を撫でる(ドラッグ, スワイプ)で画面のXY軸に対応した音が出るWebアプリを作りました。
NadeNadeSynth ( https://nadenadesynth.herokuapp.com/ )
X軸(左右)が音程、Y軸(上下)が音量に対応しています。
(本当は上下はフィルターに対応させたかったんだけど、うまく行かなかった)
適当に画面を触ると適当な音が出るというオモチャ的アプリです。
Mac, iOS, Androidでは確認しました(肝心のWinがまだという…)
本記事はその開発記になります。
実のところ、このアプリは過去に一度作ったもののドメイン引っ越しの際に消えたアプリのリベンジ版です。
(だからバージョン番号が0.0.2)
前に作ったものはスマホスワイプに対応していなかったので、そこをやりたかったのと、
今風な開発にしたかったので再挑戦しました。
再挑戦なので機能を決めるところはすんなりできました。
X軸音程、Y軸がフィルターで、その部分はグラデーション背景になっている、というものです。
ライブラリなどの選定は
nuxt generate をかまさないと行けない(あるいはCircleCI?)ので開発時のストレスの無さで選定こんな感じで、ここまではすんなり来ました。
コーディング時に気を使ったのは、 new Tone.MonoSynth() する タイミングです。
Tone.MonoSynth はその名の通りシンセサイザーのクラスです。
使い回すのでnuxtの mounted() に入れられたらいいのですが、
Web Audio APIはユーザーの動作を起点に発動しなければならないという(妥当な)制限があるようで、
mounted() ではまずいのでちょっと苦労しました。
最終的には nadeZone (撫でるゾーン)の@clickで呼ばれるイベントに置きましたが、
そこまでせずともよかったかもしれません。
(画面読み込み時に出るボタンを押したタイミングでよかったかも)
触っているときだけ音を出すというアプリなのですが、
マウスイベントから常に周波数を送っているという関係上、
シンセクラスを作ったり捨てたりするのは現実的ではないなと思い、使いまわしています。
しかしそれでは音が出っぱなしになるので、
音量を、
にしました。
つまり結局音は出っぱなしということです…。
撫でるというコンセプト上、やはりスマホ対応はしたかったのです。
そこでたぶん知っている人は知っているけれど自分は知らなかったスマホ独特のイベントオブジェクトについて書いておきます。
PCブラウザの場合、mousemoveに渡されるeventは直にclientX, clientYを持っているけれど、
スマホは複数タッチが可能な関係上、XY軸の情報は@touchmoveのevent直下にはありません。
event.touches という配列の下に格納されています。
{
  event: {
    // 略
    touches: [ // ここに配列として含まれる
      { // 最初の指がtouches[0]
        // 略
        clientX: 100,
        clientY: 100
      },
      {
        // 略
        clientX: 50,
        clientY: 50
      }
    ]
  }
}
だいたいこんな感じです。
なので event.touches が undefined ではなく、なおかつ event.touches.length が1個以上のときという条件分岐を組みました。
単純に読み込んだだけではうまく使えません。
(おそらく、参照しているWeb Audio APIが別のものになっている)
@sKawashimaさんの記事を参考に、
importではなくrequireを使うno-ssrを使う(サーバーサイドレンダリングしない)という対処をすれば読み込めました。
それでは、 Let's NadeNade!