UIXHERO

Spatial Canvas(スペーシャルキャンバス)

無限の2D空間でノード・カード・図形を自由に配置・接続・拡大縮小するインタラクティブキャンバスUI。Figma・Miro・Excalidraw・React Flowのようなホワイトボード・フロービルダーのパン・ズーム・ノードドラッグ・コネクター線の設計パターンを解説する。

2026年3月3日
更新: 2026年9月3日
22
by Dengen Yosho(DGYS)

無限(または広大)な2D空間上でノード・カード・図形を自由に配置・移動・接続・拡大縮小するインタラクティブキャンバスFigma(デザインキャンバス)・Miro(ホワイトボード)・Excalidraw(作図)・React Flow(フロービルダー)・Notion Canvas など、空間的な情報整理やフロー設計に使われる。パン(画面移動)・ズーム・ノードドラッグ・コネクター(矢印線)・複数選択が基本的なインタラクションセット。

この記事を読むと、transform: translate + scale によるパン・ズームの実装・座標変換(スクリーン座標⇔キャンバス座標)・ノードのドラッグ移動・SVGコネクター線の描画・ミニマップの設計・パフォーマンス最適化が自分でできるようになります。


1. UI例(Preview / Live)

実装で見る(GunjoUI)

この部品を、デザインシステム GUNJO の実装で確かめられます。

2. 定義(Definition)

CSS transformtranslatescale を組み合わせて、仮想2D空間上でパン(移動)とズームを実現するUIパターン。キャンバス上のオブジェクトはスクリーン座標ではなくキャンバス座標系で位置を管理し、ユーザーインタラクションのたびに座標変換を行う。

主要な座標変換

スクリーン座標 → キャンバス座標:
canvasX = (screenX - offsetX) / scale
canvasY = (screenY - offsetY) / scale

キャンバス座標 → スクリーン座標:
screenX = canvasX * scale + offsetX
screenY = canvasY * scale + offsetY

3. 使い分け(When to use / When NOT to use)

3.1 When to use

  • フロービルダー・ワークフロー設計:ノードとエッジで処理フローをする
  • ホワイトボード・ブレインストーミング:アイデアを空間的に整理する
  • ネットワーク・依存関係の可視化構成図・組織図
  • デザインツール・作図:グラフィックの配置・整列

3.2 When NOT to use

  • データが少ない(10件未満):通常のリストやグリッドの方が認知コストが低い
  • スクロール一覧で十分な場合:Spatial Canvas は学習コストが高いため、単純な一覧には不向き
  • モバイルのみ対応:パン・ズームのマルチタッチ操作は複雑で、デスクトップ向けUIとして設計する方が安全

4. 設計判断の核(Decision Principles)

Spatial Canvasの核は「座標変換の正確な実装」——パン・ズームはすべて offset(translate)scale の2変数で管理し、ユーザーのすべてのインタラクション(クリック・ドラッグ・ホイール)はスクリーン座標からキャンバス座標に変換してから処理する。この変換が1px でもズレると、ノードのドラッグ・配置がすべてズレる。

判断の優先順位:① 座標変換の正確な実装 → ② ズームの中心点(マウス位置)→ ③ パフォーマンス(大量ノード)→ ④ ミニマップ

  • ズームはマウス位置を中心に行う:単純に scale を変更すると原点(左上)を中心に拡大縮小されてしまい、操作感が不自然。offset を同時に更新することでマウス位置を中心に拡大縮小する:newOffset.x = mouseX - (mouseX - offset.x) * (newScale / scale)
  • ノードのドラッグはポインターキャプチャを使うonMouseMove をドキュメント全体で受け取るか、setPointerCapture を使うことで、ノードの外にカーソルが出てもドラッグが続く実装が必要
  • 大量ノードは仮想化(表示範囲外を非レンダリング)する:100件以上のノードを持つキャンバスでは、現在のビューポートに表示されているノードのみレンダリングするビューポートカリングが必要。パフォーマンスが劣化すると使い物にならない
  • キーボード操作を提供する:矢印キーでパン、+/- でズーム、0 でリセット。ノード選択中は矢印キーで微調整移動を提供することで、キーボードユーザーも操作可能にする

5. 状態設計(States)

状態カーソル説明
アイドルgrab何もしていない状態
キャンバスパン中grabbingマウスダウンしてキャンバスを移動中
ノードドラッグ中grabbingノードを移動中
ノード選択中defaultノードがアクティブ
ズーム中スクロールでズームイン/アウト
接続線描画中crosshairエッジを引く操作中

6. バリエーション設計(Variants)

バリアント特徴使用例
フロービルダーノード+有向エッジワークフロー・BPMNダイアグラム
ホワイトボード自由配置・図形・付箋Miro・FigJam
マインドマップ階層的なノードツリーブレインストーミング
依存グラフ有向グラフ(DAG)パイプライン・データリネージ
デザインキャンバス図形・テキスト・画像Figma・Sketch

7. パターン集(Good / Bad / How to fix)

7.0 よく崩れる設計パターン(3つ)

  • ズームが原点(左上)中心になるscale のみを変更し offset を更新していないため、ズームするたびにキャンバスが左上に引っ張られる
  • ノードのドラッグがズーム後にズレる:ドラッグ計算でスケールを考慮していないため、ズームしている状態でノードを動かすとカーソル位置とノードがズレる
  • 100件以上のノードで激重になる:全ノードをDOMに描画しているため、ノード数が増えるとフレームレートが下がりスクロールが引っかかる

7.1 Bad(典型3つ)

  • setScale(newScale) のみ更新し offset を変更しないため、ズームするたびにビューが左上にジャンプする
  • ドラッグ中のノード位置を deltaX で更新する際にスケール除算を忘れ、ズーム時にドラッグ量がズレる
  • 1000件のノードを Array.map() でフルレンダリングし、パンのたびに全ノードが再レンダリングされる

7.2 Good(対になる3つ)

  • ズーム時に newOffset.x = mouseX - (mouseX - offset.x) * ratio を計算してオフセットも同時更新する
  • ノードドラッグのデルタを deltaX / scaledeltaY / scale でスケール補正してからキャンバス座標に適用する
  • React.memo + ビューポートカリング(ノードのキャンバス座標がビューポート範囲外なら null を返す)でレンダリングをする

7.3 How to fix(手順)

  1. handleWheel でズーム時の offset 補正計算を追加する
  2. ノードドラッグのデルタを /scale で補正する
  3. ノードコンポーネントを React.memo でメモ化する
  4. キャンバス座標がビューポート外のノードをスキップするフィルタリングを追加する

8. ルール(Must / Better)

Must(守らないと壊れる)

Better(品質が跳ねる)


9. アクセシビリティ要件(必須)

Screen Reader / Keyboard

Spatial Canvas は本質的にビジュアルインタラクションに依存するUIのため、スクリーンリーダーとキーボードユーザー向けに代替アクセス手段を検討する:

<div
  role="application"
  aria-label="フローチャートキャンバス"
  tabindex="0"
>
  <!-- ノード -->
  <div
    role="button"
    aria-label="ノード:デザイン(x:220, y:40)"
    aria-selected="true"
    tabindex="0"
  >デザイン</div>
</div>

<!-- 代替:スクリーンリーダー向けのリスト表現 -->
<nav aria-label="ノード一覧(スクリーンリーダー向け)" class="sr-only">
  <ul>
    <li><a href="#node-start">開始ノード</a></li>
    <li><a href="#node-design">デザイン</a></li>
  </ul>
</nav>

キーボード

  • Tab:ノード間のフォーカス移動
  • 矢印キー:選択ノードの微移動(±1px または ±10px)
  • + / -:ズームイン/アウト
  • 0:ビューリセット
  • Escape:選択解除

10. 実装メモ(Implementation Notes)

  • React Flow:ノード・エッジ管理・ズーム・パン・ミニマップがすべて組み込みのライブラリ。プロダクションレベルのフロービルダーには React Flow をベースにすることを強く推奨
  • Excalidraw(ライブラリ):ホワイトボード型のキャンバスを自前のUIに組み込める React コンポーネントとして提供されている
  • パフォーマンスtransform: translate(Xpx, Ypx) scale(N) の変更は GPU合成レイヤーに委ねられるため、left/top を直接変更するよりパフォーマンスが高い。will-change: transform を追加すると最初のフレームが速くなる
  • タッチ対応onTouchStart / onTouchMove でピンチズームとパンを実装する場合、2点タッチのdistanceでスケールを、midpointでオフセットを更新するロジックが必要

11. 関連リンク


12. まとめ

Spatial Canvasの設計で最重要なのは「座標変換の正確な実装」です。パン(translate)とズーム(scale)の2変数を一元管理し、すべてのインタラクションでスクリーン座標⇔キャンバス座標の変換を正しく適用してください。ズーム時のマウス位置中心補正とノードドラッグのスケール補正は特に見落としやすいポイントです。プロダクションレベルで実装する場合は React Flow などの専用ライブラリをベースにすることで、座標変換・パフォーマンス・アクセシビリティの複雑な実装を回避できます。

更新のお知らせ

サイトに載せていない実例や、新しい記事のお知らせはこちらで出しています。

読んだ内容を、自分の画面に当てるとき

UIXHEROは、記事を書くほかに、画面の検品・判定、デザインシステムの構築、実装と改善の伴走を受けています。何を頼めばいいか決まっていない段階の相談も、同じ窓口で受けます。

UIXHEROに頼めることを見る

※ 記事の内容についての質問や、書いてほしいテーマの要望も同じ窓口で受けています

記事をシェア

メールでお知らせを受け取る

最終更新: 2026年9月3日

この記事を書いた人

Dengen Yosho(DGYS)

Dengen Yosho(DGYS)

UI/UXデザイナー兼デザインエンジニア デザイン歴25年以上 情報設計〜UIデザイン〜React/TypeScriptによる実装までを一気通貫で担当 大手企業のDXプロジェクトや決済アプリ領域で、デザインリードとして改善と構築を経験 現在はフリーランスとして、プロダクトのUI/UX改善とデザインシステム構築を支援 長年の実務の中で感じてきたのは、 「良いUI」はセンスではなく、再現可能な判断の積み重ねであるということ UIXHEROは、 心理学や行動科学の知見を、現場で使える設計言語に翻訳するための場所 関心領域は「ユーザーの行動が変わるUI」 人の認知・注意・意思決定の構造を理解し、 “なぜそのUIが機能するのか”を言語化することを目指している

あわせて読みたい

この記事に関連する記事をご紹介します

Bar Chart(棒グラフ)

カテゴリごとの量を棒の長さで比べるチャート。ゼロ基線の扱い、並び順、縦横の選び方、しきい値の見せ方という設計判断と、色だけに頼らないアクセシビリティ要件を解説する。

2026年8月27日
18

Donut Chart(ドーナツチャート)

中央をくり抜いた円で構成比を示すチャート。中央に置く値の選び方、円グラフとの使い分け、リングの太さ、凡例の作りという設計判断と、色だけに頼らないアクセシビリティ要件を解説する。

2026年8月27日
17

Gauge Chart(ゲージチャート)

1つの値を範囲の中に置いて示す半円のチャート。範囲の両端に意味があるかという条件、しきい値の帯の設計、色だけで良否を伝えない書き方という設計判断とアクセシビリティ要件を解説する。

2026年8月27日
16

もっと深く知りたいですか?

ここに掲載されていないトピックについても、リクエストがあれば解説記事を追加します。 わかりにくい点や、具体的な事例について知りたいことがあれば教えてください。

リクエストを送る