graphic-gif
Erzeugt ein animiertes Looping-GIF aus CSS-Animationen oder einer KI-Bild-zu-Video-API. Ausgabe: animation.gif.
Im Gegensatz zu allen anderen graphic- Skills, die ein statisches PNG oder PDF ausgeben, gibt dieser Skill ein animiertes .gif aus. Verwendet CSS @keyframes-Animationen, die Frame für Frame über Playwright und die Web Animations API erfasst werden (Option A, Standard), oder eine KI-Bild-zu-Video-Pipeline über Kling (Option B).
Wichtige Regeln (vor jeder Generierung lesen)
- Standard ist css-animiert. Verwende niemals
ai-generated, es sei denn, es wird explizit angefordert. - Canvas ist 800×800px quadratisch. Alle
clamp()-Werte werden bei 800px berechnet (1vw = 8px). - Einzelne eigenständige HTML-Datei. Sämtliches CSS inline in
<style>. Nur externer Font-CD-<link>als Abhängigkeit erlaubt. - HTML niemals in den Chat dumpen. In Datei speichern, nur Zusammenfassung anzeigen.
- Frame-Erfassung verwendet Web Animations API-Seeking. KEINE
setTimeout-Schleifen, KEINEanimation-delay-Tricks. - Exakte Frame-Anzahl:
Math.floor(dauer_sekunden * fps)Frames. Der Frame beit=dauer_msDARF NICHT erfasst werden – er dupliziertt=0und verursacht ein sichtbares Ruckeln am Loop-Punkt. - Keine Platzhalter-Boxen. Nur CSS-generierte visuelle Elemente. Keine „Bild kommt hier hin“-Elemente.
- Einfachere Paletten = kleinere Dateien. Verwende:
clean-slate,terminal,electric-burst,brutalist. - Kein animation-delay für Staffelung. Staffelung in
@keyframes-Prozentsätze einbauen – Frame-Seeking übernimmt das Timing. - Vor dem Schreiben des CSS auf eine Designrichtung festlegen. Ton, charakteristisches Element, Bewegungsstil, unvergessliches Detail – alles vor der ersten Codezeile entschieden.
Schritt 1: Aufnahme
Erforderlich: prompt (Inhaltsbeschreibung UND Bewegungskonzept)
Optional mit Standardwerten:
| Parameter | Standard | Optionen |
|---|---|---|
| animation_type | css-animated | css-animated / ai-generated |
| duration | 3.0 | Sekunden |
| fps | 12 | Bilder pro Sekunde |
| loop | true | true / false |
| style | clean-slate | clean-slate / terminal / electric-burst / brutalist |
| dimensions | 800x800 | BxH in Pixeln |
| optimization | balanced | quality / balanced / filesize |
Wenn prompt fehlt oder keine Bewegungsbeschreibung enthält, genau so fragen:
„Was soll das GIF zeigen? Beschreibe den Inhalt UND die Bewegung (z. B.: 'Statistiken zählen hoch: 73% der Käufer lesen 3+ Inhalte vor dem Kauf. Schreibmaschineneffekt, Zeichen für Zeichen. Stil: Terminal. 3 Sekunden, 12fps.')
Wichtige Einstellungen (alle optional, Standardwerte angezeigt):
- animation_type: css-animated (Standard) oder ai-generated
- duration: 3.0 Sekunden
- fps: 12
- loop: true
- style: clean-slate (Optionen: clean-slate / terminal / electric-burst / brutalist)
- dimensions: 800x800
- optimization: balanced (Optionen: quality / balanced / filesize)"
Wenn alle erforderlichen Informationen vorhanden sind → direkt zu Schritt 2 springen.
Schritt 2: Interne Architektur (dem Benutzer niemals zeigen)
Für css-animiert:
- Animationstyp auswählen aus:
fade-in,slide-in,typewriter,counter,pulse,loop-scroll references/animation-library.mdlesen – die komplette HTML/CSS-Spezifikation des gewählten Typs findenreferences/style-presets.mdlesen – den CSS-Token-Block des gewählten Stils laden- Frame-Anzahl berechnen:
Math.floor(dauer_sekunden * fps)– diese Zahl notieren - Auf Designrichtung festlegen:
| Entscheidung | Ableitung von |
|---|---|
| Ton | Emotionale Tonlage für die Zielgruppe (mechanisch / warm / elektrisch / professionell) |
| Charakteristisches Element | EIN visuelles Gestaltungsmittel, das konsistent verwendet wird (Cursor-Blinken, Geisterzahl, Zeilenüberlagerung, Akzentrahmen) |
| Bewegungsstil | Easing-Kurven-Philosophie für diesen Typ (Feder / linear / schrittweise / ease-in-out) |
| Unvergessliches Detail | Das EINE, woran sich ein Betrachter von diesem GIF erinnern wird |
Für ki-generiert:
- Basis-Standbild-HTML generieren (Plakat-Stil-Layout für die Leinwand)
- Als PNG per Screenshot exportieren
- Kling-API aufrufen:
POST https://api.klingai.com/v1/videos/image2videomitimage_urlundprompt, der die Bewegung beschreibt - Auf Abschluss des Auftrags warten
- Video herunterladen → mit ffmpeg in GIF konvertieren:
# Zwei-Durchgang-Palette für beste Farbqualität ffmpeg -i input.mp4 -vf "fps=12,scale=800:800:flags=lanczos,palettegen=stats_mode=diff" palette.png ffmpeg -i input.mp4 -i palette.png -vf "fps=12,scale=800:800:flags=lanczos,paletteuse=dither=bayer:bayer_scale=5" output.gif
Schritt 3: HTML-Generierung (css-animierter Pfad)
Vor der Generierung references/animation-library.md und references/style-presets.md lesen.
Canvas-Basis – für jedes GIF erforderlich:
*, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; }
body {
width: 800px;
height: 800px;
overflow: hidden;
background: var(--bg);
font-family: var(--font-body);
}
.canvas {
width: 800px;
height: 800px;
position: relative;
overflow: hidden;
display: flex;
align-items: center;
justify-content: center;
}
Animationsregeln:
animation-fill-mode: forwards(oderboth) bei ALLEN animierten Elementen- Timing-Funktionen pro Typ:
typewriter→steps(N, end)wobei N = exakte Zeichenanzahlcounter→linearfade-in→cubic-bezier(0.22, 1, 0.36, 1)(ease-out)slide-in→cubic-bezier(0.34, 1.56, 0.64, 1)(Feder-Überschwinger)pulse→ease-in-outmitanimation-iteration-count: infiniteloop-scroll→linearmitanimation-iteration-count: infinite
- Für Einmal-Animationen (fade-in, slide-in, typewriter, counter):
animation-iteration-count: 1– Looping erfolgt auf GIF-Ebene - Kein
animation-delay– Staffelung wird in@keyframes-Prozentsätze eingebaut
Berechnung der Typwriter-Zeichenanzahl N: Jedes Zeichen zählen, einschließlich Leerzeichen, Satzzeichen, Zahlen:
- „73% of buyers“ = 14 Zeichen →
steps(14, end) - „Hello, World!“ = 13 Zeichen →
steps(13, end)
Counter CSS @property (für Counter-Typ erforderlich):
@property --num {
syntax: '<integer>';
inherits: false;
initial-value: 0;
}
.counter {
animation: countUp var(--duration) linear forwards;
counter-reset: num var(--num);
}
.counter::after { content: counter(num); }
@keyframes countUp {
from { --num: 0; }
to { --num: var(--target); }
}
Loop-Scroll: Inhalt MUSS dupliziert werden:
<!-- 4 Original-Elemente + 4 Duplikat-Elemente -->
<div class="ticker-track" style="--item-count: 4;">
[Element1][Element2][Element3][Element4][Element1][Element2][Element3][Element4]
</div>
translateX(0 → -50%) mit linear infinite.
Designqualitätsregeln (aus Festlegung in Schritt 2):
- Das benannte charakteristische Element MUSS im CSS/HTML vorhanden sein (nicht nur beschrieben)
- Typografie: Gewichtskontrast mindestens 2:1 (z. B. 700 zu 400) zwischen Überschrift und Fließtext
- Hintergrund: kein reines Weiß
#ffffür dunkle Stile – den genauen--bg-Wert der Vorlage verwenden - Für Terminal-Stil: Zeilenüberlagerungs-
::aftermitrepeating-linear-gradientbeiopacity: 0.03hinzufügen - Für Brutalist: dicken Rand
4px solid #000oder4px solid var(--accent)an einem Schlüsselelement - Unvergessliches Detail: Wenn ein zusätzliches Element erforderlich ist – jetzt hinzufügen
Schritt 4: Selbst-QA (jeden Fehler vor Schritt 5 beheben)
Canvas:
-
bodyund.canvasexakt 800×800px (oder angegebene Abmessungen) -
overflow: hiddensowohl beibodyals auch bei.canvas - Keine Elemente ragen über die Canvas-Grenze hinaus
Animationen:
- KEIN
animation-delayirgendwo – Staffelung in@keyframes-Prozentsätzen - Alle Animationen beginnen bei
t=0(Web Animations API wird von dort aus suchen) -
animation-fill-mode: forwardsoderbothbei allen animierten Elementen - Einmal-Animationen:
animation-iteration-count: 1 - Unendliche Animationen (pulse, loop-scroll):
animation-iteration-count: infinite
Typspezifische Prüfungen:
- Typewriter: N in
steps(N, end)= exakte Zeichenanzahl der Textzeichenfolge - Counter:
@property --numdeklariert mitsyntax: '<integer>'undinitial-value: 0 - Counter:
counter-reset: num var(--num)und::after { content: counter(num) } - Loop-Scroll: Inhalt genau einmal im HTML dupliziert
Design:
- Keine Platzhalter-Boxen
- Stil-Vorlagen-Tokens aus
references/style-presets.mdangewendet – keine frei schwebenden Hex-Farben - Das in Schritt 2 benannte charakteristische Element ist tatsächlich im HTML/CSS vorhanden
- Das unvergessliche Detail aus Schritt 2 ist tatsächlich implementiert
- Font-CD-
<link>für die Schriftart des gewählten Stils vorhanden
Schritt 5: Export
Slug aus prompt ermitteln (Kebab-Case, ≤30 Zeichen). Ausgabeverzeichnis erstellen:
mkdir -p [slug]
HTML speichern:
[slug]/animation.html
Im Browser zur schnellen visuellen Prüfung öffnen:
open [slug]/animation.html
Export-Skript ausführen (ersetze [skill-root] mit dem tatsächlichen Pfad zu diesem Skill):
bash [skill-root]/scripts/export-gif.sh \
[slug]/animation.html \
[slug]/animation.gif \
--duration [duration] \
--fps [fps] \
[--no-loop if loop=false] \
--optimization [optimization] \
--width [W] \
--height [H]
Das Skript:
- Installiert
gifenc,sharp(oderjimp) undplaywrightin einem temporären Verzeichnis - Lädt Chromium herunter, falls nicht im Cache
- Führt
capture-and-encode.mjsaus – pausiert Animationen, sucht jeden Frame, erstellt Screenshots, setzt GIF zusammen - Führt gifsicle-Optimierungsdurchlauf aus, falls verfügbar
- Gibt Dateigröße aus und öffnet das Ergebnis
Wenn Export-Skript nicht gefunden unter [skill-root]/scripts/export-gif.sh, überprüfen, ob der Skill mit seinem vollständigen scripts/-Ordner installiert wurde.
Schritt 6: Ausgabe-Zusammenfassung
Nach erfolgreichem Export anzeigen:
## GIF: [1-zeilige Beschreibung]
Datum: [YYYY-MM-DD] | Stil: [style] | Animation: [type] | [duration]s @ [fps]fps
Abmessungen: [WxH] | Frames: [N] | Loop: [true/false]
Dateien
Quelle: [slug]/animation.html
Ausgabe: [slug]/animation.gif
Größe: [X] KB
Checkliste
- [ ] Vorschau läuft am Start-/Endpunkt sauber durch (kein Ruckler)
- [ ] Text bei vorgesehener Anzeigegröße lesbar
- [ ] Dateigröße angemessen: E-Mail <500KB / Social Media <3MB
KI-Generierter Pfad (Option B)
Nur verwenden, wenn animation_type: ai-generated explizit angegeben ist.
Voraussetzungen:
- Kling-API-Schlüssel in der Umgebung:
KLING_API_KEY(66 kostenlose Credits/Tag, keine Kreditkarte für den kostenlosen Tarif erforderlich) ffmpeglokal installiert für Video→GIF-Konvertierung
Arbeitsablauf:
- Ein Basis-Standbild-HTML generieren, das dem prompt entspricht (Plakat-/Grafik-Stil in den angegebenen Abmessungen)
- Standbild als PNG exportieren:
# Schneller Screenshot per Playwright node -e " const { chromium } = require('playwright'); (async () => { const browser = await chromium.launch(); const page = await browser.newPage({ viewport: { width: W, height: H } }); await page.goto('file://[slug]/animation.html'); await page.screenshot({ path: '[slug]/base-frame.png' }); await browser.close(); })(); " - An den Kling-Bild-zu-Video-Endpunkt hochladen
- Ergebnis mit ffmpeg-Zwei-Durchgang-Palette in GIF konvertieren
- gifsicle-Optimierung anwenden
Wenn Kling nicht verfügbar ist: Auf css-animiert zurückgreifen mit einem Hinweis an den Benutzer: „KI-Generierung erfordert einen Kling-API-Schlüssel (KLING_API_KEY). Fallback auf css-animiert. Setze den Schlüssel, um KI-Generierung zu aktivieren.“
Tipps für Eingabeaufforderungen (zeigen, wenn der Benutzer um Anleitung bittet)
„Beschreibe Bewegung, nicht nur Inhalt. ‚Statistiken zählen einen nach dem anderen hoch‘ ist besser als ‚zeige Statistiken‘.“
„Halte es einfach für die Dateigröße. 1–3 animierte Elemente und ein solider Hintergrund.“
„Denke in Schleifen. Die Animation sollte unsichtbar vom Ende zum Anfang zurückfließen.“
„Gib den Animationstyp explizit an.
typewriterundcountersind am effektivsten für soziale Medien.“✅ Gut: „Erstelle ein animiertes GIF, css-animiert, Typewriter-Effekt. Text: ‚73% der B2B-Käufer lesen 3+ Inhalte, bevor sie den Vertrieb kontaktieren.‘ Jedes Zeichen wird nacheinander getippt. Stil: Terminal. 3 Sekunden, 12fps, loop=true."
❌ Schlecht: „Erstelle ein animiertes GIF mit Marketing-Tipps“