grafisches-diagramm
Erstellt Datenvisualisierungsdiagramme als PNG. Rendert HTML mit Apache ECharts v6 in einem kopflosen Chromium über Playwright → Screenshots mit 2× Retina-Qualität.
CDN: https://cdn.jsdelivr.net/npm/[email protected]/dist/echarts.min.js
Kritische Regeln (vor jeder Generierung lesen)
areaTyp →type: 'line'+areaStyle: {}— ECharts hat keinentype: 'area'.doughnut→type: 'pie'+radius: ['40%', '70%']— ECharts hat keinentype: 'doughnut'.- Bereitschaftssignal:
chart.on('finished', fn)VORchart.setOption()registrieren — ECharts Fehler #14101/#17500: Wenn der Listener nach setOption registriert wird, wird er stillschweigend nie ausgelöst. Registrieren Sie sowohl diefinished- als auch dierendered-Ereignisse immer vor setOption. xAxis.type: 'category'muss explizit gesetzt werden — ECharts leitet dies nicht aus den Daten ab. Das Vergessen führt zu einem leeren Diagramm.- Kategoriebeschriftungen gehören in
xAxis.dataund nicht in eindata.labels-Array. Die ECharts-Struktur ist flach:{ xAxis, yAxis, series, grid, title, legend }— nicht unterdataoderoptionsverschachtelt. - Datenbeschriftungen sind voll integriert — verwenden Sie
label: { show: true }in jeder Serie. Kein Plugin nötig. - Hervorhebung eines bestimmten Balkens/Punkts über pro Element
itemStyle— setzen Sie{ value: N, itemStyle: { color: '#...' } }direkt in dasdata-Array. Verwenden Sie KEINEbackgroundColor-Arrays wie bei Chart.js. - ECharts-Initialisierung verwendet einen
<div>-Container, kein<canvas>—echarts.init(document.getElementById('chart')). Der Container-Div benötigt explizite Abmessungen. animation: falsein der Option — deaktiviert Animation für sofortiges Rendern. Registrieren Sie trotzdem die Ereignissefinished+renderedvor setOption für das Bereitschaftssignal.- HTML niemals im Chat ausgeben. In Datei speichern, nur Zusammenfassung zeigen.
- Der Titel gibt die Erkenntnis an, nicht das Thema. „Umsatz in 12 Monaten um das 3-fache gestiegen“ nicht „Monatlicher Umsatz“.
- Kreis/Ring: Body
padding: 64px 80pxund.chart-container { max-height: 860px }verwenden — verhindert randlose Füllung, wenn kein Titel vorhanden ist.
Schritt 1: Datensammlung
Erforderlich: chart_type, data
Optionale Parameter und Standardwerte:
| Parameter | Standard | Beschreibung |
|---|---|---|
| chart_type | — | bar / line / area / pie / doughnut / scatter / radar / treemap |
| data | — | JSON-Array oder CSV — erforderlich |
| title | — | Gibt die Erkenntnis an, ≤10 Wörter |
| subtitle | — | Ein-Satz-Kontextzeile |
| style | clean-slate | clean-slate / midnight-editorial / matt-gray / electric-burst / brutalist |
| dimensions | 1080x1080 | BxH Pixel (Ausgabe-PNG = 2× über deviceScaleFactor) |
| x_label | — | X-Achsenbeschriftungstext |
| y_label | — | Y-Achsenbeschriftungstext |
| source | — | Datenquelle, die in der Fußzeile angezeigt wird |
| highlight | — | Datenbeschriftung zum Hervorheben (z. B. „Q4“, „Dez“, Index 3) |
Wenn chart_type oder data fehlt, genau so fragen:
„Um das Diagramm zu erstellen, benötige ich:
- Diagrammtyp — bar / line / area / pie / doughnut / scatter / radar / treemap
- Daten — als JSON-Array oder CSV bereitstellen (z. B.
[12, 18, 22, 25, 31]mit Beschriftungen['Q1','Q2','Q3','Q4','Q5'])Optional: Titel, Stil (Standard: clean-slate), Abmessungen (Standard: 1080×1080), bestimmten Datenpunkt hervorheben"
Wenn beide vorhanden sind → zu Schritt 2 springen.
Schritt 2: Interne Architektur (dem Benutzer nie anzeigen)
1. Diagrammtyp normalisieren:
area→line+areaStyle: {}in der Seriedoughnut→pie+radius: ['40%', '70%']in der Seriehorizontal bar→bar+ xAxis/yAxis tauschen (Kategorieachse auf y)- Alle anderen: wie besehen verwenden
2. references/chart-library.md lesen — vollständige Konfigurationsspezifikation für diesen Diagrammtyp laden.
3. references/style-presets.md lesen — CSS-Tokens + Datenpalette für den gewählten Stil laden.
4. Designrichtung festlegen:
| Entscheidung | Herleiten von |
|---|---|
| Ton | Professionell / redaktionell / kühn / technisch — passend zum Publikum der Daten |
| Datengeschichte | Einzige Erkenntnis, die dieses Diagramm beweist (wird zum Titel) |
| Hervorhebungsstrategie | Welcher Datenpunkt benötigt visuelle Betonung und warum? |
| Hintergrund | Hell (clean-slate, matt-gray) oder dunkel (midnight-editorial, electric-burst, brutalist) |
5. Daten parsen:
- Einfaches Array
[12, 18, 22]→ series.data, Beschriftungen separat bereitgestellt - Objekt-Array
[{x: 'Jan', y: 12}]→ xAxis.data aus x-Schlüsseln, series.data aus y-Werten - CSV: Kopfzeile als xAxis.data parsen, Datenzeile als series.data
- Multi-Serie: mehrere
series-Einträge jeweils mittype,name,data - Streuung:
series.data: [[x1,y1], [x2,y2], ...]Format
6. Abmessungen parsen: "1080x1080" → B=1080, H=1080. Body = BxH. Ausgabe-PNG = 2B × 2H.
Schritt 3: HTML-Generierung
ALLES vor der Generierung lesen:
references/chart-library.mdfür die vollständige ECharts-Konfigurationsspezifikation dieses Diagrammtypsreferences/style-presets.mdfür die CSS-Tokens + Palette des gewählten Stils
Erforderliche HTML-Struktur:
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
[Schriftart-CDN-Link aus Stilvorlage]
<style>
:root {
[alle CSS-Tokens aus der Stilvorlage]
}
*, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; }
html, body {
width: [B]px; height: [H]px;
overflow: hidden;
background: var(--bg);
font-family: var(--font-body);
}
body {
display: flex;
flex-direction: column;
padding: 40px 48px 32px; /* Kreis/Ring: 64px 80px verwenden */
}
/* ECharts-Container muss explizite Größe haben */
.chart-container {
flex: 1;
min-height: 0;
/* nur Kreis/Ring: 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>
[wenn Titel oder Untertitel: <div class="chart-header"><div class="chart-title">...</div>...</div>]
<div id="chart" class="chart-container"></div>
[wenn Quelle: <div class="chart-footer">Quelle: [Quelle]</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' });
// KRITISCH: Ereignisse VOR setOption registrieren — ECharts Fehler #14101/#17500
// 'finished' wird möglicherweise stillschweigend nicht ausgelöst, wenn es nach setOption mit animation:false registriert wird
chart.on('finished', () => {
window.__chartReady = true;
});
// Zusätzlicher Fallback über 'rendered'
chart.on('rendered', () => {
clearTimeout(window.__renderDebounce);
window.__renderDebounce = setTimeout(() => { window.__chartReady = true; }, 100);
});
const palette = [Palette aus Stilvorlage];
const option = {
animation: false, // sofortiges Rendern für Screenshot
backgroundColor: 'transparent', // Body-CSS übernimmt Hintergrundfarbe
textStyle: {
fontFamily: '[--font-body Wert]',
color: '[--text-muted Wert]',
},
[Titelkonfiguration, wenn Titelparameter bereitgestellt],
[Legendenkonfiguration pro Diagrammtyp],
[Grid-Konfiguration pro Diagrammtyp],
[xAxis-Konfiguration pro Diagrammtyp],
[yAxis-Konfiguration pro Diagrammtyp],
series: [{
[vollständige Serienkonfiguration aus chart-library.md für diesen Typ]
[Palettenfarben pro Diagrammtyp angewendet]
[wenn Highlight: pro Element itemStyle auf dem hervorgehobenen Datenpunkt]
}]
};
chart.setOption(option); // setOption kommt IMMER nach der Ereignisregistrierung
});
</script>
</body>
</html>
Designqualitätsregeln:
- Schriftart Titel:
fontWeight: 'bold',fontSize: 20–24— keine dünnen Titel - Gitterlinien: niedrige Deckkraft (0.06–0.10) — den Daten untergeordnet
- Balken:
barMaxWidth: 60, abgerundet überitemStyle.borderRadius: [4,4,0,0] - Linien:
smooth: truefür natürliche Kurven,symbolSize: 8für Punkte - Kreis/Ring:
label.formatter: '{b}\n{d}%'für integrierte Beschriftungen auf den Segmenten - Dunkle Vorlagen: Grid
rgba(255,255,255,0.07), Achsenlinie/Strichfarbergba(255,255,255,0.15) - Tooltip:
show: false— statisches PNG, keine Hover-Interaktion - Wenn kein Titel angegeben:
.chart-headerauslassen, Titel aus ECharts-Option weglassen
Schritt 4: Selbstqualitätssicherung (jeden Fehler vor Schritt 5 beheben)
Struktur:
- Container ist ein
<div>, kein<canvas> -
window.__chartReady = falsevordocument.fonts.readydeklariert -
chart.on('finished', ...)VORchart.setOption()registriert -
chart.on('rendered', ...)Debounce-Fallback VORchart.setOption()registriert -
animation: falseim Optionsobjekt -
chart.setOption(option)ist der LETZTE Aufruf im Init-Block
Typspezifisch:
- Fläche:
type: 'line'+areaStyle: {}— keintype: 'area' - Ring:
type: 'pie'+radius: ['40%', '70%']— keintype: 'doughnut' - Balken:
xAxis.type: 'category'explizit gesetzt - Kategoriedaten in
xAxis.data(nichtdata.labels) - Kreis/Ring: Body
padding: 64px 80px+.chart-container { max-height: 860px } - Hervorhebung: pro Element
{ value: N, itemStyle: { color } }im Datenarray
Design:
- Alle Palettenfarben aus
references/style-presets.md - Titel gibt Erkenntnis an (nicht nur Thema)
-
tooltip: { show: false }oder weggelassen (kein Hover auf statischem PNG) - Dunkle Vorlage: Grid-/Achsenfarben verwenden
rgba(255,255,255,...) - Quelle in Fußzeile, wenn
source-Parameter angegeben - Datenbeschriftungen sichtbar (integriertes
label: { show: true }in Serie)
Schritt 5: Export
Slug aus Titel oder Diagrammtyp + Datenkontext ermitteln (Kebab-Schreibweise, ≤30 Zeichen):
mkdir -p chart/[slug]
HTML speichern: chart/[slug]/chart.html
Schnelle Browser-Überprüfung:
open chart/[slug]/chart.html
Export ausführen ([skill-root] durch den tatsächlichen Pfad zu diesem Fähigkeitsverzeichnis ersetzen):
bash [skill-root]/scripts/export-chart.sh \
chart/[slug]/chart.html \
chart/[slug]/chart.png \
--width [B] \
--height [H]
Das Skript installiert Playwright beim ersten Start (~200 MB Chromium-Download) und erfasst dann das Diagramm mit deviceScaleFactor: 2.
Schritt 6: Ausgabe-Zusammenfassung
## Diagramm: [Titel]
Datum: [YYYY-MM-DD] | Typ: [diagramm_typ] | Stil: [stil]
Abmessungen: [B×H]px → PNG: [2B×2H]px @2× Retina
Dateien
Quelle: chart/[slug]/chart.html
Ausgabe: chart/[slug]/chart.png
Größe: [X] KB
Checkliste
- [ ] Titel gibt die Erkenntnis klar an
- [ ] Datenbeschriftungen bei Anzeigegröße lesbar
- [ ] Hervorhebung auf richtigem Datenpunkt sichtbar
- [ ] Quellenangabe in der Fußzeile vorhanden
Eingabetipps (zeigen, wenn der Benutzer um Anleitung bittet)
"Strukturierte Daten bereitstellen — JSON oder CSV, keine Beschreibungen in Prosa."
"Geben Sie den Diagrammtyp explizit an. 'Balkendiagramm zum Vergleich Q1–Q4' nicht 'ein Diagramm, das Quartale zeigt'."
"Geben Sie die Datengeschichte an. 'hebe Q4 hervor, das alle anderen übertroffen hat' gibt den Annotationskontext."
✅ Gut: "Erstelle ein Liniendiagramm. Titel: 'Von $12k auf $95k ARR in 12 Monaten'. Daten: [12, 18, 22, 25, 31, 38, 44, 52, 61, 68, 78, 95] (Jan–Dez 2024). Hebe Dezember hervor. Quelle: Internes CRM. Stil: electric-burst."
❌ Schlecht: "erstell ein diagramm über unser firmenwachstum"