クリックもタップもピンチも、入力のしくみの話
今回は、StitchPress の入力処理をどう設計したのか、その技術的な中身に踏み込んでみます。言ってみれば、設計の「分解レポート」のようなものです。とはいえ、専門用語はできるだけ使わずに書いたので、コードや技術の話はちょっと苦手…という方にも、何かしら発見があるはず。開発日誌のようなつもりで、操作することの多い StitchPress の使い心地を、私たちがどれだけ真剣に考えて作っているのかをお伝えできればと思います。
どのデバイスでも使えるように
StitchPress では、できるだけ多くの環境で使ってもらえるようにしたいと考えています。パソコン、スマートフォン、タブレットといったデバイスはもちろん、macOS、Windows、Android、iOS などの OS やプラットフォームについても同じです。そのための方法は、大きく分けて2つありました。
- プラットフォームごとに、ネイティブのコードを書く。
- Web の技術を使い、いまやほとんどのデバイスに入っているもの、つまりブラウザの上で動かす。
私たちが選んだのは2つ目です。理由はシンプルで、対応したいプラットフォームすべてに向けてネイティブのコードを書くだけの余力が、いまの私たちにはないからです。とはいえ、2つ目の方法も決して楽な道ではありません。それでも、まだ手の届く範囲ではあります。
現在の StitchPress は、主要なデスクトップ OS(Windows、macOS、Linux)のブラウザで、キーボードとマウス、キーボードとトラックパッドの組み合わせに対応しています(Linux はディストリビューションによって追加の確認が必要かもしれませんが、Ubuntu と Arch Linux では動作を確認済みです)。Android や iOS のタブレット、スマートフォンといったタッチデバイスでも使えます。ただ、こうした対応は、ブラウザが最初から面倒を見てくれるものではありません。とくに無限キャンバスのような細やかな入力処理には、コードの土台となるきちんとした設計と、根気のいる細かな調整の積み重ねが欠かせないのです。
舞台裏をのぞいてみると
StitchPress を作っている小さなチーム、Kinnet Studio では、無限キャンバスを使った Web アプリをいくつも開発してきました。その中から生まれたのが、ue-too という名前のオープンソースのパッケージ群です。無限キャンバスのアプリ作り、とくにビューポート(画面に映っているキャンバスの範囲)を操作に合わせて動かす部分を手助けしてくれます。開発者の方は、ぜひのぞいてみてください。ソースコードは GitHub で公開していて、パッケージは npm からインストールできます。ビューポートを受け持っているのは @ue-too/board です。StitchPress も、この ue-too を土台にして作られています。
で、実際どうなっているの?
StitchPress が操作をどう処理しているのかを知るには、まずブラウザの「イベント」のしくみからお話しする必要があります。マウスのボタンをクリックしたり、ホイールを回したり、キーボードのキーを押したりするたびに、ブラウザはページ上で動いているスクリプトにイベントを送ります。ただし、スクリプトはブラウザが用意しているイベントをすべて受け取るわけではありません。「このイベントが起きたら知らせてね」とイベントリスナーを登録して、必要なものだけを受け取るしくみになっています。たとえば、マウスの左ボタンが押されたことを知りたければ、mousedown というイベントを受け取るように登録します。スクリプトが受け取れるイベントの種類はとても多く、StitchPress に必要な操作は、すべてこの組み合わせで作ることができます。
ブラウザのイベントのしくみは柔軟にできていますが、そのぶん複雑になりやすいという代償があります。というのも、イベントは組み合わせて使うことがあるからです。たとえば、Figma(をはじめ、多くの無限キャンバスのアプリ)のように、スペースキーを押したままマウスをドラッグして画面を動かせるようにしたいとします。そのためには、キーボードのイベントとマウスのイベントの両方を受け取らなければなりません。厄介なのは、ほしいイベントをひとつの窓口にまとめて受け取れないことです。イベントごとに窓口が分かれていて、ちょうどいいタイミングで画面が動き出すように、それぞれを連携させる必要があります。扱うイベントが増えれば増えるほど、全体をまとめるのはどんどん難しくなっていきます。
この複雑さに立ち向かうために、StitchPress(土台は @ue-too/board です)では「ステートマシン(状態機械)」という考え方を使っています。ざっくり言うと、ステートマシンはいくつかの「状態」を持つしくみです。同じイベントでも、状態によって対応が変わります(まったく反応しないこともあります)。そして、イベントをきっかけに、ある状態から別の状態へと移り変わります。これを「遷移」と呼びます。百聞は一見にしかず、ということで、下に小さな見本を用意しました。無限キャンバスが操作をどう処理しているのかを示すもので、その中で入力を受け持っているステートマシンを、無限キャンバスの上にそのまま図として描いています。図はリアルタイムで反応するので、キャンバスを動かしたり拡大・縮小したりすると(お使いの入力方法に合わせて、ドロップダウンで切り替えてください)、状態の遷移とイベントが起きる様子を、その場で目で追うことができます。この見本では、画面の移動や拡大・縮小といった、基本的なビューポートの操作だけに絞っています。
StitchPress では、目的に応じていくつものステートマシンを使い分けていますが、基本の考え方は同じです。ほかの人が作った既存のステートマシンを拡張するといった、もう一歩進んだ使い方もあり、StitchPress でも実際に取り入れていますが、それはまた別のお話。ステートマシンのパッケージ @ue-too/being にはドキュメントサイトがあり、より詳しい解説と使い方のガイドを載せています(ガイドの本文は、今のところ英語のみです)。ご自身のプロジェクトでステートマシンを使ってみたい方は、ぜひのぞいてみてください。
今回はこのあたりで締めくくりたいと思います。いつもの記事にくらべると、かぎ針編みや手芸の話からは少し離れて、開発者寄りの内容になりました。それでも、Kinnet Studio が StitchPress を作るうえで使い心地をとても大切にしていて、そこには決して手を抜いていないことを、みなさんに知ってもらえたらうれしいです。
StitchPress は現在プレアルファ版です。いっしょに使い心地を作り上げてくださる、かぎ針編みの編み図デザイナーさんを募集しています。興味はあるけれど、まだ私たちから連絡が届いていないという方は、contact@kinnet.studio までメールをお寄せください。アルファ版・ベータ版のテストの様子を追いかけたい方は、ウェイトリストへどうぞ。