bklit-studio-chart-performance について
Studioで動作が重いチャートを調べる、bklit-uiコントリビューター向けのパフォーマンス改善スキルです。レンダリングの分離、SVGパスの静的化、コンテキスト分割、検証手順を案内します。
主な機能
- 01操作による再レンダリングの追跡
- 02安定データとホバー状態の分離
- 03入場アニメーション後のパス静的化
- 04チャートコンテキストとプレビューのメモ化
- 05Studioでの性能検証チェックリスト
活用シーン
- 01スライダー操作時の遅延調査
- 02凡例ホバー時の再計算削減
- 03キャンバス移動中の描画改善
- 04リリース前のチャート操作検証
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ bklit/ bklit-ui --skill bklit-studio-chart-performanceインストール後、Claude Code で/bklit-studio-chart-performanceを入力して読み込まれたか確認します。
詳細
Studio のチャートパフォーマンス
Studio でチャートの動作が遅く感じられる一方、類似のチャート(例:pie-chart)は問題ない場合に使用します。
1 行でのルール
必要ならパスの enter アニメーションは維持し、その後は Motion のパスサブスクリプションを削除し、ホバーを分離します。これにより、Studio のスライダーや凡例の更新のたびに、すべてのシリーズで高負荷な arc/path 計算が毎フレーム再実行されるのを防ぎます。
1. インタラクションのたびに再レンダリングされるものを特定する
Studio はスライダーの各ティックや凡例/スライスのホバーのたびに displayState を更新します。次の点を確認してください。
- ホバーは、データ、スケール、アニメーション設定と同じコンテキストにありますか?
- プレビューはレンダリングのたびに子要素を再作成しますか(
data.map、パターン定義、Motion の props など)? - チャートは不要に再マウントされていますか(手動再生ではなく、モーションシグネチャに紐付いた
keyなど)?
パターン: カルテジアンチャート/円グラフのようにコンテキストを分割します。データ、ジオメトリ、アニメーション設定を含む安定スライスと、ホバー状態(hoveredIndex、ツールチップ)を含むホバースライスに分けます。ホバーを必要としないコンシューマーは、安定したフック(usePieStable、useRingStable、useChartStable など)だけを使用します。
Studio のパン: チャートのレンダリングを StudioChartRender(packages/studio/src/components/studio-chart-render.tsx)でラップし、レンダリング用 props が変更されていない場合は、カメラのパン/FPS カウンターによる親の更新がチャートツリーに伝播しないようにします。
2. SVG パスの d アニメーションは高コストとして扱う
Motion/useTransform と d3 arc(または同様のもの)を使用して d をアニメーションさせると、シリーズごとに毎フレーム、レイアウトと描画が実行されます。
| 推奨 | 避けること |
|---|---|
ホバーには transform/opacity を使う(コンポジターに適しています) | enter の完了後も d を継続的にモーフィングする |
enter の完了後は d を静的にする | チャートのライフタイム全体にわたって d の Motion サブスクリプションを維持する |
| enter アニメーションの後はパスを静的にする | 関係のない prop の変更で enter のパス計算を再実行する |
パターン: enter には useMountProgress を使用し、進捗が 1 以上になったら(useEnterComplete)、静的なパスをレンダリングします。ホバーのアニメーションには、パスごとの motion.path の scale ではなく、motion.g ラッパー上の x/y/opacity/scale だけを使用します。
共有フック:packages/ui/src/charts/use-enter-complete.ts
3. チャートシェルのコンテキストをメモ化する
プロバイダーの値をメモ化しないと、親のレンダリングのたびにすべての子要素の再調整が発生します。
- 安定したコンテキストオブジェクトを、明示的な依存値(データ、arc/半径、寸法、コールバック)でメモ化します。
- ホバーコンテキストは
hoveredIndexと安定したsetHoveredIndex(チャートシェル内のuseCallback)を依存値としてメモ化します。 isLoadedは ring/カルテジアンチャートに合わせます。遅延useState初期化子ではなく、useEffectとタイムアウトを使います。
参考:pie-context.tsx、ring-context.tsx、chart-context.tsx、プロバイダー値に useMemo を使用する PieChartCore/RingChartCore
4. Studio プレビューに特化した効果
チャートの種類に依存しません。packages/studio/src/components/charts/*-studio*.tsx に適用します。
| 効果 | 方法 |
|---|---|
| 定義を条件付きで渡す | シリーズでパターンを使用する場合にのみ patternDefs/グラデーションを渡す |
| 派生データをメモ化する | 色付け/マッピング済みのデータ配列、スライス/シリーズのリスト(useMemo を使い、依存値には dataSeed と色に影響するデザインフィールドを指定) |
| Motion の enter をメモ化する | getStudioMotionEnterProps をインラインで呼び出さず、モーションのみの依存値(state 全体ではない)を使って useMemo を使用する |
| 凡例のホバーをメモ化する | { hoveredIndex, setHoveredIndex } を useMemo に入れる — これはすでに studio-legend-hover.tsx にあります |
| チャート本体をメモ化する | memo() ラッパーを使用し、コンテキスト全体の ctx ではなく、プリミティブ値(chartKey、chartSize、data)を渡して、パン/シェルの再レンダリングによる再構築を防ぐ |
| Studio でグローを無効にする | シリーズコンポーネントで showGlow={false} を設定する |
参考:pie-studio-preview.tsx、ring-studio-preview.tsx
5. Studio で「高速」な同系統のチャートと比較する
同じエディター内でスムーズに動作するチャート(通常は pie-chart)と、動作の遅いチャートを比較します。
| 確認項目 | 動作の遅いチャートによくある特徴 | 動作の速いチャートによくある特徴 |
|---|---|---|
| シェル | インライン描画、余分な定義 | StudioChartShell + 条件付きパターン |
| 系列数 | アニメーション付きのパスが多い | パスが少ない、またはジオメトリがシンプル |
| ホバー | コンテキストとツリー全体の再描画 | 安定したサブスクライバー、motion.g 上でのホバー/変換 |
| 入場 | 系列ごとにパスの d をワイプ | 入場後は静的な d、ホバー時は変換のみ |
| パン | フレームごとにチャートツリーを再構築 | StudioChartRender のメモ化境界 |
6. 検証基準
PR を作成する前に:
pnpm lint
pnpm --filter @bklitui/ui check-types
pnpm --filter @bklitui/studio check-types
# scoped production build when touching studio/web
手動で /studio?chart=<slug> を確認:
- 入場アニメーション
- ホバー/凡例の同期
- ジオメトリのスライダーをドラッグ(不要な再マウントがないこと)
- 入場後にキャンバスをパン(スペースキー + ドラッグ) — FPS が pie-chart の基準値に近いこと
- パターン/グラデーションモード(サポートされている場合)
チャートのステータス(bklit-ui)
| チャート | スラッグ | ステータス |
|---|---|---|
| 円 | pie-chart | ✅ 参照(#120) |
| リング | ring-chart | ✅ チェックリストに準拠(コンテキスト分割、静的パス、StudioChartRender、プレビューのメモ化) |
| レーダー/ファネル/コロプレス | 各種 | 一部対応 — チェックリストを実行 |
| 直交座標/散布図/ライブライン | 各種 | ✅ #91 の間引き + ホバーのバッチ処理 |
| サンキー | sankey-chart | リンクのストロークで useTransform を使用 — useEnterComplete の候補 |
| ゲージ | gauge-chart | 優先度低(単一の弧) |
主なファイル
| 領域 | パス |
|---|---|
| 入場完了フック | packages/ui/src/charts/use-enter-complete.ts |
| 円のリファレンス | packages/ui/src/charts/pie-slice.tsx、pie-context.tsx、pie-studio-preview.tsx |
| リング | packages/ui/src/charts/ring.tsx、ring-chart.tsx、ring-studio-preview.tsx |
| パンの分離 | packages/studio/src/components/studio-chart-render.tsx |
| レジストリ | packages/studio/src/lib/registry.tsx |