ツール
ツールは、キャンバス上のポインタ入力とキーボード入力を解釈するモジュールです。それぞれが自己登録された ToolModule(拡張アーキテクチャを参照)であり、packages/ から検出されます。このページでは、組み込みの 5 つのツールと、すべてのツールが実装するイベントルーティングの契約を解説します。
組み込みツール
| ツール | ショートカット | カーソル | 概要 |
|---|---|---|---|
| 選択 | V | default | 選択中のレイヤーを移動・リサイズ(8 個のハンドル)し、パスのアンカーやハンドルを編集する。 |
| ペン | P | crosshair | ベジェパスをアンカー単位で描く。閉じて塗りつぶし形状にするか、開いたストロークとして終える。 |
| テキスト | T | text | キャンバスをクリックして新しいテキストレイヤーを置き、選択ツールへ引き継ぐ。 |
| パン | H | grab | ドラッグでカメラをパンする。他のツールでも Space を押している間だけ一時的に呼び出せる。 |
| ズーム | Z | zoom-in | クリックでポインタ位置を基点にズームイン。Alt+クリックでズームアウト。 |
選択ツール(V)
tools/ はリファレンス実装となるツールです。ツール契約のあらゆる部分を使い切っており、新しいツールを作るときにコピー元とするファイルです。ポインタダウン時には、次の順で処理します。
すでにレイヤーが選択されていれば、そのレイヤー上のパスノードやベジェハンドルをつかもうとします(
tryGrabNode)。判定範囲はアンカーが 7px 以内、ハンドルが 6px 以内です。つかめなければ、選択範囲のバウンディングボックスにある 8 個のリサイズハンドルのいずれかをつかもうとします(
tryGrabResizeHandle)。これは回転していないshape/imageレイヤーにのみ提供されます(回転した bbox は軸に沿ったリサイズができないため)。それでもつかめなければ、ドキュメント全体を上から順にヒットテストし(
topmostHit)、当たったものを選択します。何にも当たらなければ選択を解除します。
ドラッグ中は ctx.replace() で変更をストリーミングし、undo エントリ(ctx.beginGesture())を開くのはドラッグが 0.1mm のスナップグリッドを越えて動いたときだけです。純粋なクリックや、スナップ未満のわずかなぶれで実質的な変化が生じない場合は、履歴は変更されません。pointerUp / onDeactivate はどちらもドラッグ状態をクリアするため、ドラッグの途中でツールを切り替えても、古いジェスチャーが開いたまま残ることはありません。
ペンツール(P)
tools/ はベジェパスを 1 アンカーずつ組み立てます。
クリック でグリッドにスナップしたコーナーアンカーを追加します。
直前に置いたアンカー上で クリックしてドラッグ すると、対称な
hout/hinのベジェハンドルが引き出され、スムーズアンカーに変わります。最初のアンカーの近くをクリック すると(パスに 3 個以上のアンカーが必要)、パスを閉じて塗りつぶし形状(
fill: gold、ストロークなし)にします。Enter を押すと、代わりにパスを開いたまま終えます(ストロークのみ、塗りなし)。アンカーが 2 個以上必要です。
Esc で作成中のドラフトをキャンセルします。
この複数クリックからなるジェスチャーは、パスが完成するまで ctx.doc にはいっさい触れません。選択ツールのライブドラッグとは異なり、ドキュメント内に途中経過が発生しないため、完成時にはちょうど 1 回の ctx.commit()(1 つの undo エントリ)にまとまります。フローティングのヒントバー(ツール契約にはクロム用のスロットがないため、ツール自身がマウントする独立した React ツリー)が、利用できる操作とその有効/無効の状態を表示します。作成中のパスは、メインのレンダラーではなくツールの renderDraft フックで描画されます。
テキストツール(T)
tools/ は意図的に最小のツールです。ポインタダウンでクリック位置に TextLayer を作成し(デフォルトの内容は "TEXT"、サイズ 6mm、色は白 — シルクスクリーンのレイヤー)、コミットして選択し、直ちにアクティブなツールを select に戻します。こうすることで、置いたばかりのテキストをすぐにドラッグ・リサイズ・編集できるようになります。
パンツール(H / Space ドラッグ)
tools/ はカメラの画面ピクセルのオフセットをドラッグで動かします。ツールを切り替えずに呼び出すこともできます。他のどのツールがアクティブでも Space を押している間は、Editor がポインタイベントを pan にルーティングします(後述の Space ドラッグのオーバーライド を参照)。これにより、たとえば作成中のペンパスを見失うことなく、編集の途中でパンできます。
ズームツール(Z)
tools/ は固定倍率(ズームインは 1.5 倍、ズームアウトは 1/1.5 倍)で、camera.zoomAt によりクリック位置を基点にズームします。ポインタの下にある mm 座標の点はその場に留まります。Alt+クリックではズームインの代わりにズームアウトします。
ツールを知る手がかり: ツールチップと Help パネル
ドキュメントを開かなくてもツールの役割が分かるように、2 つの表面が用意されています。どちらも ToolModule のデータからそのまま供給されます。
ツールバーのツールチップ。 各ツールバーボタン(
components/→toolbar. tsx ChromeButton)は、ツールのlabelとshortcutから組み立てたホバーツールチップを表示します(例:Select (V)、Pen (P))。このツールチップのテキストはボタンのaria-labelでもあるため、ボタンのアクセシブルネームにもなっています。ホバー後に短い遅延を置いて現れ、また(プレーンなフォーカスではなく):focus-visibleを基準にしているため、クリックしてボタンにフォーカスが残っても、ツールチップが開いたまま張り付くことはありません。追加アクションのボタンも、そのlabelから同じ扱いを受けます(こちらはショートカットを持ちません)。サイドバーの Help パネル。 固定された Help フッター(
components/)は、現在アクティブなツールの名前、ショートカットのバッジ、そしてより長いhelp- panel. tsx descriptionを表示します。descriptionは、そのツールが何をするか、主要なポインタ操作、そしてショートカットを説明する 2〜4 文です。組み込みの各ツールは、任意項目のToolModule.descriptionフィールドでこれを提供します(拡張アーキテクチャを参照)。省略したツールは、汎用的な「No description available」の行にフォールバックします。パネルはactiveToolIdに追従するため、Space を押して一時的にパンしても、表示される説明が入れ替わることはありません。
ポインタ/キーボードイベントの契約
Editor シェル(Editor.tsx)は、入力のルーティングについてただ 1 つのルールを持ちます。アクティブなツールに最初の受け取り権があり、その後にアプリレベルのフォールバックが動く というものです。
ポインタイベント
キャンバス上のすべてのポインタイベントは ToolPointerEvent(キャンバス基準の画面ピクセル、それに対応するドキュメントの mm、button / buttons、修飾キー、pointerId)に正規化され、その時点で 有効 なツールの onPointerDown / onPointerMove / onPointerUp / onDoubleClick に渡されます。
Space ドラッグのオーバーライド
有効なツールは通常 activeToolId ですが、Space が押されている間は、何がアクティブであるかにかかわらず強制的に 'pan' になります。これにより、activeToolId 自体を変えずに、どのツールからでも一時的なオーバーライドとしてパンが使えます。Space を離す(あるいはドラッグ中に Space が離れたことを捉える buttons === 0 の移動)と、直前にアクティブだったツールに戻ります。
キーボードイベント
keydown の際、シェルはまずアクティブなツールの onKeyDown(e, ctx) を呼び出します。それが true を返した場合に限り、ルーティングはそこで止まります。ツールがそのキーを要求したことになり、アプリレベルのフォールバックは動きません。これが、シェル側にすべてのツールが編集しなければならない共通のキーボード用 switch を持たせることなく、ペンがドラフトの確定/キャンセルのために Enter/Esc を所有できる仕組みです。
ツールが true を返さなかった場合、シェルは次の順でフォールバックを実行します。
⌘/Ctrl+Z(undo) /⌘/Ctrl+Shift+Z(redo)。単一キーのツールショートカット(
V/P/T/H/Z、大文字小文字は区別しない)。修飾キーが押されていないときにのみマッチするため、undo/redo の判定より先に発火することはありません。Esc— 選択解除。Delete/Backspace— 選択中のレイヤーを削除。矢印キー — 選択中のレイヤーを 0.1mm、Shift を押していれば 1mm 移動(ナッジ)。パターンレイヤー(パネル全体を覆う)はナッジできません。パスレイヤーは点集合全体を平行移動します。
<input> / <textarea> / <select> にフォーカスがある間(レイヤー名の変更フィールドやインスペクタの数値フィールドなど)は、キーボード入力はグローバルに無視されます。そのため、テキストボックスに "V" と入力してもツールが切り替わることはありません。
Tip
新しいツールを作るとき、シェルのフォールバックより先にキーを横取りする 唯一 の方法は onKeyDown で true を返すことです。編集すべき別の優先度リストは存在しません。ツールの追加を参照してください。