はじめに
図を描くツール、何を使っていますか。
正直なところ、Figma、draw.io、Miro...選択肢は山ほどあるんですが、どれも「ちょっとしたスケッチを描きたい」だけなのに機能が多すぎて、使うたびに疲れるんですよね。
そんな中で最近よく使っているのがExcalidrawという手書き風ホワイトボードツールです。
GitHubで112,000スター以上を獲得していて、オープンソースで完全無料。手書き風のゆるい雰囲気が特徴的で、アイデアをサッと可視化するのに最適なツールです。
これ、意外とエンジニア界隈で流行ってて、技術ブログの図解とか、設計ドキュメントのダイアグラムとかで見かけることが増えました。
読むより先に触ってみたほうが早いと思うので、<Excalidraw />コンポーネントを実際にブラウザ上で動かせるサンプルを用意しました。先に手を動かしたい方はこちらからどうぞ。
Excalidrawとは
Excalidrawは、手書き風のダイアグラムやスケッチを作成できるオープンソースの仮想ホワイトボードです。ブラウザ上で動作し、インストール不要で今すぐ使い始められます。
6年前にプロジェクトが開始され、現在は348人のコントリビューターによって活発に開発が続けられています。MITライセンスなので、商用利用も自由です。
公式サイト: https://excalidraw.com GitHub: https://github.com/excalidraw/excalidraw
特徴・メリット
1. 手書き風のスタイルがいい
これがExcalidrawの最大の特徴です。
描いた図形が全部手書き風になるので、「完璧に仕上げなきゃ」というプレッシャーがない。ラフスケッチとして自然に見えるから、アイデア段階の図でも恥ずかしくないんですよ。
設計レビューとかで「これ仮なんで」って言いやすい。個人的にはこの「ゆるさ」がめちゃくちゃ気に入ってます。
2. 無限キャンバス
キャンバスに制限がないので、どこまでも広げられます。
複数のダイアグラムを同じキャンバスに配置したり、関連する図をつなげて俯瞰したり。PowerPointみたいにスライドを意識しなくていいのは楽ですね。
3. リアルタイムコラボレーション
URLを共有するだけで、複数人で同時編集ができます。
しかもエンドツーエンド暗号化対応なので、セキュリティ面も安心。チームでブレストする時とか、リモートワークでのホワイトボード代わりに使えます。
4. ローカルファーストでPWA対応
データはローカルに保存されるので、オフラインでも使えます。
PWA(Progressive Web App)にも対応しているので、デスクトップアプリのようにインストールして使うことも可能。ネット環境がなくても作業を続けられるのは地味にありがたい。
5. 多彩なエクスポート形式
PNG、SVG、クリップボードへのコピーに対応。
ブログ記事に貼り付けたり、ドキュメントに埋め込んだり、Slackで共有したり。用途に合わせて最適な形式で出力できます。SVGなら拡大しても劣化しないので、プレゼン資料にも使いやすい。
6. Reactコンポーネントとして使える
これがエンジニアとしては嬉しいポイント。
npmパッケージとして提供されているので、自分のReactアプリに組み込めます。自社ツールにホワイトボード機能を追加したい時とか、カスタマイズしたい時に便利。
インストール方法
ブラウザで使う場合
インストール不要です。
https://excalidraw.com にアクセスするだけ。時短になりますね。
デスクトップアプリとして使う場合
Excalidraw.comにアクセスして、ブラウザのアドレスバー右側にあるインストールアイコンをクリック。PWAとしてインストールできます。
自分のプロジェクトに組み込む場合
npm install react react-dom @excalidraw/excalidraw
# または
yarn add react react-dom @excalidraw/excalidraw
Excalidrawのサンプルを動かす
Excalidrawの正体は、突き詰めると<Excalidraw />という1つのReactコンポーネントです。npmパッケージ@excalidraw/excalidrawが提供するこのコンポーネントを配置するだけで、手書き風の描画キャンバスがまるごと画面に現れます。
コアになる部分だけを抜き出すと、こんな形です。@excalidraw/excalidraw/index.cssの読み込みを忘れると、ツールバーやパネルのレイアウトが崩れて正しく表示されないので注意してください。
import { createRoot } from 'react-dom/client'
import { Excalidraw } from '@excalidraw/excalidraw'
import '@excalidraw/excalidraw/index.css'
function App() {
return (
<div style={{ width: '100%', height: '480px' }}>
<Excalidraw
onChange={(elements) => {
console.log(`要素数: ${elements.length}`)
}}
/>
</div>
)
}
createRoot(document.getElementById('root')).render(<App />)
実際に動かせるものが下です。四角形や矢印、フリーハンドの線などをキャンバス上に自由に描いてみてください。onChangeコールバックが呼ばれるたびに、その時点のelements配列の長さ(=要素数)がコンソールに出力されます。
キャンバスに図形を描いてから消しゴムツールで消してみると、コンソールの「要素数」が増減する様子が確認できるはずです。onChangeの中身を書き換えれば、描画内容を自分のサーバーに送ったり、ローカルストレージに保存したりする処理をそのまま差し込めます。initialDataで最初から図形を表示するパターンや、themeでダーク・ライトを切り替えるパターンは、この後の「実践的なユースケース」で個別に紹介します。
基本的な使い方
Webアプリとして使う
- excalidraw.com にアクセス
- 左側のツールバーから図形を選択
- キャンバス上でドラッグして描画
- 右上のメニューからエクスポート
直感的に使えるので、説明はほとんど不要だと思います。
ツールの種類
- 選択ツール: 図形の選択・移動・リサイズ
- 矩形: 四角形を描画
- 菱形: ひし形を描画
- 楕円: 円・楕円を描画
- 矢印: 接続線を描画
- 線: 直線・折れ線を描画
- フリードロー: 自由に手書き
- テキスト: 文字を入力
- 画像: 画像を挿入
Reactコンポーネントとして使う
import { Excalidraw } from '@excalidraw/excalidraw'
function App() {
return (
<div style={{ width: '100%', height: '500px' }}>
<Excalidraw />
</div>
)
}
export default App
これだけでExcalidrawがアプリに組み込まれます。シンプルですね。
コンテナのサイズがゼロだと何も表示されないので、widthとheightを明示的に指定するのがポイントです。
状態を管理する
import { useState } from 'react'
import { Excalidraw } from '@excalidraw/excalidraw'
import type { ExcalidrawElement } from '@excalidraw/excalidraw/types/element/types'
function App() {
const [elements, setElements] = useState<ExcalidrawElement[]>([])
return (
<div style={{ width: '100%', height: '500px' }}>
<Excalidraw
initialData={{ elements }}
onChange={(elements) => {
setElements(elements)
}}
/>
</div>
)
}
onChangeでキャンバスの変更を検知して、状態として保持できます。これをローカルストレージやデータベースに保存すれば、永続化も簡単。
ダークモード対応
import { Excalidraw } from '@excalidraw/excalidraw'
function App() {
return (
<div style={{ width: '100%', height: '500px' }}>
<Excalidraw
theme="dark"
/>
</div>
)
}
themeプロパティで簡単に切り替えられます。
実践的なユースケース
1. システム構成図の作成
アーキテクチャ図とか、インフラ構成図を描くのに最適です。
手書き風だから「まだ検討中です」感が出て、レビュー時の指摘も受けやすい。完璧に見えると「もう決まってるんでしょ」って思われがちなので、この曖昧さが逆にいいんですよね。
2. ワイヤーフレームの作成
UIの初期検討とか、画面遷移の整理に使えます。
Figmaほどの精度は出ないけど、アイデア段階では十分。デザイナーに渡す前の下書きとして重宝してます。
3. 技術ブログの図解
この記事の図もExcalidrawで作れます。
SVGでエクスポートすれば高画質だし、手書き風で他のブログと差別化できる。QOL上がりますね。
4. ブレインストーミング
リモートワークでのチームブレストに便利。
リアルタイムコラボ機能があるので、Zoomしながら全員で同じキャンバスにアイデアを書き出せます。Miroより軽くてサクサク動くのがいい。
5. 自社ツールへの組み込み
import { Excalidraw, exportToSvg } from '@excalidraw/excalidraw'
import { useRef } from 'react'
function DiagramEditor() {
const excalidrawRef = useRef(null)
const handleExport = async () => {
if (!excalidrawRef.current) return
const svg = await exportToSvg({
elements: excalidrawRef.current.getSceneElements(),
appState: excalidrawRef.current.getAppState(),
files: excalidrawRef.current.getFiles()
})
// SVGを処理(サーバーに保存、ダウンロードなど)
console.log(svg.outerHTML)
}
return (
<div>
<button onClick={handleExport}>SVGでエクスポート</button>
<div style={{ width: '100%', height: '500px' }}>
<Excalidraw ref={excalidrawRef} />
</div>
</div>
)
}
社内のドキュメントツールとか、プロジェクト管理ツールにダイアグラム機能を追加したい場合に使えます。
6. 初期データを渡してあらかじめ図形を配置する
テンプレート的な図をあらかじめ表示しておきたいケースでは、initialDataプロパティに要素の配列を渡します。要素を1つずつ手で組み立てるのは大変なので、convertToExcalidrawElementsというヘルパー関数を使うと、typeとx・y程度の最小限の情報から正式なExcalidrawの要素データに変換してくれます。
import { Excalidraw, convertToExcalidrawElements } from '@excalidraw/excalidraw'
const elements = convertToExcalidrawElements([
{ type: 'rectangle', x: 80, y: 80, width: 180, height: 100, backgroundColor: '#a5d8ff' },
{ type: 'text', x: 110, y: 120, text: 'Excalidraw', fontSize: 20 },
])
function App() {
return <Excalidraw initialData={{ elements }} />
}
実際に動かせるサンプルです。開いた時点で四角形・矢印・テキストがすでに配置された状態になっています。
配列の中のbackgroundColorやx・yの値を書き換えると、初期表示される図形の色や位置がそのまま変わります。ダッシュボードのテンプレートや、ワークフローの叩き台をあらかじめ用意しておきたい場合に便利なパターンです。
7. onChangeで変更をリアルタイムに検知する
「何か描くたびに自動保存する」といった機能を作りたい場合は、onChangeイベントを使います。第一引数に渡ってくるelements配列の長さを見るだけで、キャンバス上の要素数をリアルタイムに把握できます。
import { useState } from 'react'
import { Excalidraw } from '@excalidraw/excalidraw'
function App() {
const [count, setCount] = useState(0)
return <Excalidraw onChange={(elements) => setCount(elements.length)} />
}
コンソールだけでなく、画面上のカウンタにも反映したサンプルです。図形を描いたり消したりすると、上部の数字がその場で変わります。
図形を1つ描くと「要素数: 1」に変わり、消しゴムで消すと「要素数: 0」に戻ることが確認できるはずです。このcountをトリガーにsetTimeoutでデバウンスをかければ、そのまま自動保存機能に転用できます。
8. Excalidrawのthemeプロパティでダーク・ライトを切り替える
自分のアプリ全体がダークモードに対応している場合、Excalidrawだけ白いキャンバスのままだと浮いてしまいます。themeプロパティに"light"または"dark"を渡すだけで、キャンバスとUIパネルの配色をまとめて切り替えられます。
import { useState } from 'react'
import { Excalidraw } from '@excalidraw/excalidraw'
function App() {
const [theme, setTheme] = useState('light')
return <Excalidraw theme={theme} />
}
ボタンを押すたびにthemeのstateを反転させるサンプルです。ツールバーや左側のパネルの配色が切り替わる様子を確認してください。
themeはpropとして渡すだけで、自分でCSS変数を上書きする必要はありません。アプリ側のダークモード切り替えロジックにthemeのstateを接続すれば、そのままExcalidrawも追従します。
VS Code拡張機能
VS Code向けの公式拡張機能もあります。
.excalidraw、.excalidraw.svg、.excalidraw.pngファイルを直接VS Code上で編集できるので、コードとダイアグラムを同じエディタで管理したい人には便利です。
注意点
いくつか気をつけるポイントがあります。
1. フォントの自己ホスティング
npmパッケージを使う場合、デフォルトではCDNからフォントを取得します。
セキュリティ要件が厳しい環境では、フォントを自己ホストする必要があります。node_modules/@excalidraw/excalidraw/dist/prod/fontsフォルダを自分のpublicディレクトリにコピーして、window.EXCALIDRAW_ASSET_PATHを設定してください。
2. バンドルサイズ
Reactコンポーネント版はそこそこサイズがあります。
パフォーマンスが気になる場合は、動的インポートを使って遅延読み込みすることをおすすめします。
3. データの永続化
ブラウザ版はローカルストレージに保存されますが、ブラウザのデータを消すと消えます。
大事なダイアグラムは.excalidrawファイルとしてエクスポートしておきましょう。
まとめ
Excalidrawは「ちょっとした図をサッと描きたい」というニーズにぴったりのツールです。
- 手書き風のスタイルでゆるく描ける
- 無限キャンバスで自由にレイアウト
- リアルタイムコラボでチーム作業もOK
- オープンソースで完全無料
- Reactコンポーネントとして組み込み可能
個人的には、技術ドキュメントの図解ツールとしてExcalidraw一択ですね。FigmaやMiroは機能が多すぎて、図を描くだけなのに時間がかかる。Excalidrawなら数分で完成します。
30代になって思うのは、「シンプルで速いツールが正義」ということ。余計な機能がないからこそ、本来やりたいことに集中できる。
まだ使ったことがない人は、excalidraw.com にアクセスして試してみてください。インストール不要で、今すぐ使えます。
公式サイト: https://excalidraw.com GitHub: https://github.com/excalidraw/excalidraw npm: @excalidraw/excalidraw