Penpotベクター演算の極意:SVGパスとノンデストラクティブ・ブーリアンで構築するスケーラブルなアイコンシステム
テックリードの君なら、SVGの`
無数の不要なアンカーポイント、バラバラのグループ階層、そして仕様変更のたびに最初から作り直さなければならない絶望的な「破壊的編集」。
オープンソースのプロトタイピングツール「Penpot」の真価は、CSSの概念(FlexboxやGrid)をデザインに持ち込んだことだけではない。SVGの仕様に極めて忠実でありながら、開発者のメンタルモデルに完璧に合致した「ノンデストラクティブ(非破壊)・ブーリアン演算」のエンジンにある。
この記事では、Penpotのベクター演算の挙動を根本から理解し、変更に強く、コードに直結するクリーンなアイコンアセットを量産するための極限の知見を授ける。
—
1. ブーリアン演算の物理:4つの挙動と内部DOM構造の理解
まずは基本の復習ではなく、「裏でSVGがどう解釈されているか」というエンジニア視点でのブーリアン演算の再定義から始める。
Penpotのブーリアン演算(Union, Subtract, Intersect, Exclude)は、単なる見た目の合成ではない。これらは「グループ化されたパスコンテナに対するリアルタイムな演算レイヤー」であり、非破壊(ノンデストラクティブ)で維持される。
[ 親コンテナ (Boolean Group: Union) ]
├── [ パス A (Base) ]
└── [ パス B (Modifier) ]
4つの演算モードとSVG生成の挙動
1. Union(和集合 / `fill-rule=”nonzero”` 基盤)
- 挙動: 複数のパスを結合し、外郭を一つの外形線にする。
- ユースケース: 複雑なシルエット、モノクロームアイコンの外枠結合。
- エンジニアリング上の注意: 重なり合う部分の内側パスが消えるため、パステロ(Path Intersection)による予期せぬ穴あきを防げる。
2. Subtract(差集合 / 背面から前面を引く)
- 挙動: 一番下のレイヤー(底面)から、上に重なるレイヤーの領域を切り抜く。
- ユースケース: 「C」の文字のような切り欠きのあるアイコン、ネガティブスペースを利用したデザイン。
- エンジニアリング上の注意: レイヤーの上下関係(Z-index)がそのまま演算結果に直結する。最背面にあるべきベースシェイプが意図せず前面にあると、全く逆の切り抜き結果になるため注意せよ。
3. Intersect(積集合 / 重なり部分の抽出)
- 挙動: すべてのシェイプが重なり合っている領域のみを残す。
- ユースケース: ベン図的な幾何学模様、高度なマスク表現。
4. Exclude(排他的論理和 / XOR)
- 挙動: 重なり合う部分を「くり抜き」、重なっていない部分を残す。
- ユースケース: 交差するライン、複雑なギアやアブストラクトなアイコン。
—
2. ノンデストラクティブ・パス編集の極意
多くのデザイナーやエンジニアが陥る罠が、「ブーリアン演算を確定(Flatten / Destructive Merge)させてしまうこと」だ。一度フラット化してしまうと、元のパーツの微調整(例えば、円のサイズ変更や角の丸みの調整)は不可能になり、アンカーポイントを一つずつ手で動かす苦行が待っている。
非破壊ワークフローの鉄則
- 絶対に「Flatten」を押すな: Penpotでブーリアン演算を行った後、右クリックから「Flatten Selection」を実行するとSVGパスが単一の `
` に破壊的変換される。これは最終的なプロダクションビルドの直前まで封印せよ。 - ダブルクリックによる「内部パス」へのアクセス: ブーリアン・グループをダブルクリックすれば、グループを維持したまま個別のシェイプ(矩形、円、自由曲線のパス)を選択・変形できる。
- プロパティの生かし方: シェイプ自体の「角丸(Border Radius)」や「ストローク幅」は、ブーリアン演算の配下であってもライブで変更可能である。つまり、「角丸の長さを後から変更できるインタラクティブなアイコンコンポーネント」が作れる。
—
3. 開発スピードを劇的に高める隠れたキーボードショートカット
マウス操作でメニューを行き来しているようでは、プロのスピードには到達できない。Penpotのベクター編集を極限まで加速させるショートカットを体に叩き込め。
| アクション | Windows / Linux | macOS |
| :— | :— | :— |
| パス編集モード切替 | `Enter` | `Enter` |
| 頂点の削除(Delete / Backspace) | `Backspace` / `Delete` | `Delete` / `⌫` |
| ハンドル(ベジェ曲線)の対称化 | `Shift` + ドラッグ | `Shift` + ドラッグ |
| ハンドルの片側フリー化(折れ線化) | `Alt` + ハンドルドラッグ | `⌥` + ハンドルドラッグ |
| スナップを一時無効化 | `Ctrl` + ドラッグ | `⌘` + ドラッグ |
| ブーリアン: Union | `Ctrl` + `Alt` + `U` | `⌘` + `⌥` + `U` |
| ブーリアン: Subtract | `Ctrl` + `Alt` + `S` | `⌘` + `⌥` + `S` |
| ブーリアン: Intersect | `Ctrl` + `Alt` + `I` | `⌘` + `⌥` + `I` |
| ブーリアン: Exclude | `Ctrl` + `Alt` + `X` | `⌘` + `⌥` + `X` |
—
4. チーム開発で役立つデザインシステムの共有化ルール
アイコンやUIアセットの管理が破綻する原因は、命名規則の欠如と、コンポーネントの構造(Atom)の不統一にある。マルチチームでPenpotを運用する際、以下のルールをチームのコントリビューションガイドラインとして強制せよ。
アイコン設計の4大原則
1. 24x24pxグリッドの厳守: すべてのマスターアイコンは `24x24px` のフレーム内に収めること。パディング(余白)は基本 `2px`(実効描画領域 20x20px)とし、例外的に突き抜けるデザイン(斜め方向の矢印など)以外はフレームをはみ出さない。
2. ストロークは必ず「アウトライン化」する: アイコンの線をストローク(線の太さ)のままにしておくと、縮小・拡大時に線幅が崩壊する。必ず `Ctrl/⌘ + Shift + O`(またはメニューからのOutline Stroke)で、ストロークを「塗り(Fill)」のパスに変換してからコンポーネント化すること。
3. 命名規則(Nomenclature):
- フォーマット: `{category}/{name}_{size}_{state}`
- 例: `actions/ic_trash_24_default`
- これにより、コード側のアイコンコンポーネント名(例: `
`)へのマッピングが機械的に行えるようになる。
4. カラーの継承(currentColor):
- エクスポートされるSVGは、すべてのパスの `fill` 属性が親要素のCSSカラー(`currentColor`)を継承するように、Penpot上で単一のプライマリカラー(または変数)にバインドされていること。
—
5. 実用的な設定ファイル・インポート仕様のベストプラクティス
Penpot自体はブラウザベースで完結するため、伝統的なファイルベースの設定ファイルは直接持たないが、PenpotからエクスポートしたSVGアセットをフロントエンド(React / Vue / Svelte)に自動同期するためのビルドパイプライン(CI/CD)設定のベストプラクティスを提示する。
以下は、デザインシステムのリポジトリで使用する、SVG最適化ツール(SVGO)の設定ファイル `svgo.config.js` の実例だ。Penpotから出力されたSVGの不要なメタデータを削ぎ落とし、プロダクションクオリティのコンポーネントに変換する。
`svgo.config.js`(プロダクション最適化の極意)
/
- @type {import(‘svgo’).Config}
- PenpotからエクスポートされたSVGをReact/Vueコンポーネントに自動変換するためのSVGO設定
/
module.exports = {
multipass: true, // 完全に最適化されるまで複数回パスを回す
plugins: [
{
name: ‘preset-default’,
params: {
overrides: {
// viewBoxはレスポンシブ対応に必須なので絶対に取り除かない
removeViewBox: false,
// Penpot特有の不要なメタデータやIDを削除
removeUnknownsAndDefaults: true,
removeUselessStrokeAndFill: true,
},
},
},
// 既存の色情報を排除し、CSSの `currentColor` でスタイリングできるようにする
{
name: ‘removeAttrs’,
params: {
attrs: ‘(fill|stroke):((?!none$).)’, // none 以外の fill/stroke を削除
},
},
// パスの小数点以下の桁数を精衛し、ファイルサイズを極限まで軽量化(2桁〜3桁が妥当)
{
name: ‘roundCoords’,
params: {
floatPrecision: 2,
},
},
// 不要なグループ(
‘collapseGroups’,
// 孤立したパス要素の削除
‘removeEmptyContainers’,
],
};
—
結び:ツールを使いこなすのではなく、ツールの「思想」をハックせよ
優れたエンジニアは、ツールの表面的な使い方に惑わされない。Penpotが提供するノンデストラクティブなブーリアン演算の本質は、「デザインとコードの間の認知のギャップをゼロにする」ことにある。
形状の変更を恐れず、いつでも数学的な正確さと美しさを保ったままSVGパスを操作できるこの環境は、モダニアなフロントエンド開発において強力な武器となる。
明日から、チームのPenpotワークスペースを開き、破壊された(Flattenされた)アイコンたちを非破壊のブーリアン・グループへとリファクタリングしてみせろ。コードレビューと同じ厳ースさで、デザインの構造を美しく整えること。それこそが、真のプロダクト・エンジニアリングだ。