graphic-chart
データ可視化チャートをPNGとして生成します。Apache ECharts v6 を使用してHTMLをレンダリングし、Playwright経由でヘッドレスChromiumでキャプチャ→2倍Retina品質のスクリーンショットを出力します。
CDN: https://cdn.jsdelivr.net/npm/[email protected]/dist/echarts.min.js
重要なルール(毎回の生成前に必読)
areaタイプ →type: 'line'+areaStyle: {}— EChartsにtype: 'area'はありません。doughnut→type: 'pie'+radius: ['40%', '70%']— EChartsにtype: 'doughnut'はありません。- 準備完了シグナル:
chart.on('finished', fn)をchart.setOption()の前に登録する — EChartsのバグ #14101/#17500 により、リスナーをsetOptionの後に登録すると、発火しなくなります。常にfinishedとrenderedイベントの両方をsetOptionの前に登録してください。 xAxis.type: 'category'は明示的に指定する必要があります — EChartsはデータから自動推測しません。これを忘れると空白のチャートが生成されます。- カテゴリラベルは
xAxis.dataに配置します。data.labels配列ではありません。EChartsの構造はフラットです:{ xAxis, yAxis, series, grid, title, legend }—dataやoptionsの下にネストしません。 - データラベルは完全にビルトインです — 任意の系列で
label: { show: true }を使用します。プラグインは不要です。 - 特定の棒/ポイントのハイライトは、アイテムごとの
itemStyleで行います —data配列に{ value: N, itemStyle: { color: '#...' } }を直接配置します。Chart.js スタイルのbackgroundColor配列は使用しないでください。 - EChartsの初期化には
<div>コンテナを使用し、<canvas>は使用しません —echarts.init(document.getElementById('chart'))。コンテナdivには明示的な寸法が必要です。 - オプション内で
animation: false— アニメーションを無効にして即時レンダリングを行います。それでも準備完了シグナルのために、finished+renderedイベントをsetOptionの前に登録してください。 - HTMLをチャット内にダンプしないでください。 ファイルに保存し、サマリーのみ表示します。
- タイトルは洞察を示し、主題を示しません。 「月間売上」ではなく「12ヶ月で売上が3倍に成長」。
- 円/ドーナツチャート: body の
padding: 64px 80pxと.chart-container { max-height: 860px }を使用します — タイトルがない場合の端から端までの塗りつぶしを防ぎます。
ステップ 1: 情報受け取り
必須: chart_type、data
オプションパラメータとデフォルト値:
| パラメータ | デフォルト | 説明 |
|---|---|---|
| chart_type | — | bar / line / area / pie / doughnut / scatter / radar / treemap |
| data | — | JSON配列またはCSV — 必須 |
| title | — | 洞察を示す、10語以内 |
| subtitle | — | 1文のコンテキスト行 |
| style | clean-slate | clean-slate / midnight-editorial / matt-gray / electric-burst / brutalist |
| dimensions | 1080x1080 | WxH ピクセル(出力PNGは deviceScaleFactor により2倍) |
| x_label | — | X軸ラベルテキスト |
| y_label | — | Y軸ラベルテキスト |
| source | — | フッターに表示するデータソース |
| highlight | — | ハイライトするデータラベル(例: "Q4"、"12月"、インデックス3) |
chart_type または data が欠けている場合、正確に次のように尋ねます:
"チャートを作成するには、以下が必要です:
- チャートタイプ — bar / line / area / pie / doughnut / scatter / radar / treemap
- データ — JSON配列またはCSVで提供(例: ラベル
['Q1','Q2','Q3','Q4','Q5']とともに[12, 18, 22, 25, 31])オプション: タイトル、スタイル(デフォルト: clean-slate)、寸法(デフォルト: 1080×1080)、特定のデータポイントのハイライト"
両方とも存在する場合 → ステップ2に進みます。
ステップ 2: 内部アーキテクチャ(ユーザーには非表示)
1. チャートタイプの正規化:
area→line+ 系列にareaStyle: {}doughnut→pie+ 系列にradius: ['40%', '70%']horizontal bar→bar+ xAxis/yAxis を入れ替え(カテゴリ軸をyに)- その他: そのまま使用
2. references/chart-library.md を読む — このチャートタイプの完全な設定仕様を読み込みます。
3. references/style-presets.md を読む — 選択したスタイルのCSSトークンとデータパレットを読み込みます。
4. デザインの方向性を決定:
| 決定 | 導出元 |
|---|---|
| トーン | プロフェッショナル / エディトリアル / 大胆 / 技術的 — データのオーディエンスに合わせる |
| データストーリー | このチャートが証明する単一の洞察(タイトルになる) |
| ハイライト戦略 | どのデータポイントに視覚的強調が必要で、その理由は? |
| 背景 | 明るい(clean-slate、matt-gray)または暗い(midnight-editorial、electric-burst、brutalist) |
5. データの解析:
- 単純配列
[12, 18, 22]→ series.data、ラベルは別途提供 - オブジェクト配列
[{x: '1月', y: 12}]→ xキーから xAxis.data、y値から series.data - CSV: ヘッダー行を xAxis.data、値の行を series.data として解析
- 複数系列: それぞれが
type、name、dataを持つ複数のseriesエントリ - 散布図:
series.data: [[x1,y1], [x2,y2], ...]形式
6. 寸法の解析: "1080x1080" → W=1080、H=1080。Body = WxH。出力PNG = 2W × 2H。
ステップ 3: HTML生成
生成前にすべてを読む:
- このチャートタイプの完全なECharts設定仕様については
references/chart-library.md - 選択したスタイルのCSSトークン+パレットについては
references/style-presets.md
必要なHTML構造:
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
[スタイルプリセットからのフォントCDNリンク]
<style>
:root {
[スタイルプリセットからのすべてのCSSトークン]
}
*, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; }
html, body {
width: [W]px; height: [H]px;
overflow: hidden;
background: var(--bg);
font-family: var(--font-body);
}
body {
display: flex;
flex-direction: column;
padding: 40px 48px 32px; /* 円/ドーナツ: 64px 80px を使用 */
}
/* EChartsコンテナは明示的なサイズが必要 */
.chart-container {
flex: 1;
min-height: 0;
/* 円/ドーナツのみ: max-height: 860px; */
}
.chart-header { margin-bottom: 24px; }
.chart-title {
font-family: var(--font-display);
font-size: clamp(1.1rem, 2.5vw, 1.6rem);
font-weight: 700;
color: var(--text);
line-height: 1.2;
}
.chart-subtitle {
font-family: var(--font-body);
font-size: clamp(0.75rem, 1.2vw, 0.9rem);
color: var(--text-muted);
margin-top: 6px;
line-height: 1.5;
}
.chart-footer {
margin-top: 14px;
font-family: var(--font-body);
font-size: 10px;
color: var(--text-muted);
opacity: 0.65;
}
</style>
</head>
<body>
[タイトルまたはサブタイトルがある場合: <div class="chart-header"><div class="chart-title">...</div>...</div>]
<div id="chart" class="chart-container"></div>
[ソースがある場合: <div class="chart-footer">出典: [source]</div>]
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/echarts.min.js"></script>
<script>
window.__chartReady = false;
document.fonts.ready.then(() => {
const container = document.getElementById('chart');
const chart = echarts.init(container, null, { renderer: 'canvas' });
// 重要: setOptionの前にイベントを登録 — EChartsバグ #14101/#17500
// 'finished' は animation:false で setOption の後に登録すると発火しない可能性があります
chart.on('finished', () => {
window.__chartReady = true;
});
// 'rendered' による二重の安全策フォールバック
chart.on('rendered', () => {
clearTimeout(window.__renderDebounce);
window.__renderDebounce = setTimeout(() => { window.__chartReady = true; }, 100);
});
const palette = [スタイルプリセットからのパレット];
const option = {
animation: false, // スクリーンショットのための即時レンダリング
backgroundColor: 'transparent', // body CSSが背景色を処理
textStyle: {
fontFamily: '[--font-body の値]',
color: '[--text-muted の値]',
},
[title パラメータが提供された場合の title 設定],
[チャートタイプに応じた legend 設定],
[チャートタイプに応じた grid 設定],
[チャートタイプに応じた xAxis 設定],
[チャートタイプに応じた yAxis 設定],
series: [{
[chart-library.md からのこのタイプの完全な系列設定]
[チャートタイプに応じて適用されるパレット色]
[ハイライトがある場合: ハイライトされたデータポイントのアイテムごとの itemStyle]
}]
};
chart.setOption(option); // setOption は常にイベント登録の後
});
</script>
</body>
</html>
デザイン品質ルール:
- タイトルフォント:
fontWeight: 'bold'、fontSize: 20–24— 細いタイトルは不可 - グリッド線: 低不透明度(0.06–0.10)— データに従属
- 棒:
barMaxWidth: 60、itemStyle.borderRadius: [4,4,0,0]で角丸 - 折れ線:
smooth: trueで自然な曲線、ポイントにsymbolSize: 8 - 円/ドーナツ:
label.formatter: '{b}\n{d}%'でスライス上のビルトインラベル - ダークプリセット: grid
rgba(255,255,255,0.07)、軸線/目盛り色rgba(255,255,255,0.15) - ツールチップ:
show: false— 静的PNG、ホバー操作なし - タイトルが提供されない場合:
.chart-headerをスキップし、EChartsオプションからtitleを省略
ステップ 4: 自己QA(ステップ5の前にすべての失敗を修正)
構造:
- コンテナは
<div>であり、<canvas>ではない -
window.__chartReady = falseがdocument.fonts.readyの前に宣言されている -
chart.on('finished', ...)がchart.setOption()の前に登録されている -
chart.on('rendered', ...)のデバウンスフォールバックがchart.setOption()の前に登録されている - オプションオブジェクトに
animation: falseがある -
chart.setOption(option)がinitブロックの最後の呼び出しである
タイプ固有:
- 面:
type: 'line'+areaStyle: {}—type: 'area'ではない - ドーナツ:
type: 'pie'+radius: ['40%', '70%']—type: 'doughnut'ではない - 棒:
xAxis.type: 'category'が明示的に設定されている - カテゴリデータが
xAxis.dataにある(data.labelsではない) - 円/ドーナツ: body
padding: 64px 80px+.chart-container { max-height: 860px } - ハイライト: データ配列内のアイテムごとに
{ value: N, itemStyle: { color } }
デザイン:
- すべてのパレット色が
references/style-presets.mdからのものである - タイトルが洞察を示している(単なる主題ではない)
-
tooltip: { show: false }または省略(静的PNGにホバーなし) - ダークプリセット: grid/軸の色に
rgba(255,255,255,...)を使用 -
sourceパラメータが提供された場合、フッターに出典がある - データラベルが表示されている(系列にビルトインの
label: { show: true })
ステップ 5: エクスポート
タイトルまたはチャートタイプ+データコンテキストからスラッグを決定(ケバブケース、30文字以内):
mkdir -p chart/[slug]
HTMLを保存: chart/[slug]/chart.html
クイックブラウザチェック:
open chart/[slug]/chart.html
エクスポートを実行([skill-root] をこのスキルのディレクトリへの実際のパスに置き換え):
bash [skill-root]/scripts/export-chart.sh \
chart/[slug]/chart.html \
chart/[slug]/chart.png \
--width [W] \
--height [H]
このスクリプトは初回実行時にPlaywrightをインストールし(約200MBのChromiumダウンロード)、その後 deviceScaleFactor: 2 でチャートをキャプチャします。
ステップ 6: 出力サマリー
## チャート: [title]
日付: [YYYY-MM-DD] | タイプ: [chart_type] | スタイル: [style]
寸法: [W×H]px → PNG: [2W×2H]px @2倍 Retina
ファイル
ソース: chart/[slug]/chart.html
出力: chart/[slug]/chart.png
サイズ: [X] KB
チェックリスト
- [ ] タイトルが洞察を明確に示している
- [ ] データラベルが表示サイズで読みやすい
- [ ] ハイライトが正しいデータポイントに表示されている
- [ ] フッターに出典表示がある
プロンプトのヒント(ユーザーがガイダンスを求めたときに表示)
"構造化データを提供してください — 散文による説明ではなく、JSONまたはCSVで。"
"チャートタイプを明示的に指定してください。'四半期を示すチャート'ではなく 'Q1~Q4を比較する棒グラフ'。"
"データストーリーを指定してください。'他のすべてを上回ったQ4をハイライト' と指定すると注釈のコンテキストが与えられます。"
✅ 良い例: "折れ線グラフを作成。タイトル: '12ヶ月でARRが1.2万ドルから9.5万ドルへ成長'。データ: [12, 18, 22, 25, 31, 38, 44, 52, 61, 68, 78, 95](2024年1月~12月)。12月をハイライト。出典: 内部CRM。スタイル: electric-burst。"
❌ 悪い例: "会社の成長についてのチャートを作って"