Web開発のしおりRepository

Webエンジニアリング関連の技術記事を掲載させていただいております。

Webページでマウスのシェイクイベント(ブルブルっと動かした)の検知 | TypeScript, RxJS

はじめに

ユーザーがマウスをブルブルっと動かした(シェイクした)時になんらかのタスクを実行したいと思ったことはありますか?ありませんよね。

こんなイメージです。マウスシェイク検知したらその旨をコンソールに出力します。

f:id:ponsea:20200601191158g:plain
マウスシェイク検知したらコンソールに出力

RxJSを使えばそこまで難しくはありません。

ちなみにRxJSとは非同期処理やストリーム処理のライブラリです。

実装コード

今回はマウスのシェイクイベントを、このように噛み砕きました。

"500ミリ秒以内に4回、マウスのX軸方向の動きが反転した"

それをRxJSで表現します。

// ↓最終的なマウスシェイクイベントのストリーム
const mouseShakeEvents$ = fromEvent<MouseEvent>(document, 'mousemove').pipe(
  // 上流はmousemoveイベントのストリーム
  // ↓マウスのx軸が動いたイベントだけにフィルタ
  filter(e => e.movementX !== 0),
  // マウスのx軸の動きが反転した時だけ流すように
  distinctUntilChanged((e1, e2) => Math.sign(e1.movementX) === Math.sign(e2.movementX)),
  // 直近の4件のイベントのまとまりで流すように
  bufferCount(4, 1),
  // 直近4件のイベントの、最初と最後の間の時間が500ms以下の場合に流すように
  filter(events => events.length === 4 && events[3].timeStamp - events[0].timeStamp < 500)
);

要点・補足:

  • RxJSのfromEventで、document (DOM)上のmousemoveイベントを、Observable<MouseEvent>に変換します。
    • Observableは端的に言うとストリームのようなオブジェクトです。
  • mousemoveイベントにはどの方向にどれだけ動いたかを示すmovementX, movementYプロパティがあります
  • RxJSのdistinctUntilChangedオペレーターは、流れてきた値と前回の値の等価性を検証する関数を取り、true(等価とみなした)場合はフィルタします。
    • Math.sign(e1.movementX) は、movementXの値がマイナスなら-1, プラスなら1を返します。
  • RxJSのbufferCountは値を指定個数分バッファして配列で流すオペレータです。
    • bufferCount(3, 2)とした時、1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 という値の流れは[1, 2, 3] -> [3, 4, 5] -> [5, 6, 7] のように変換されます。 (3つのまとまりで2つごとに流れる)

RxJSとっても便利です!