Animiertes OG-Bild
Jede Datei, die dieses Skill verwendet, wird in einem eigenen Ordner neben dieser SKILL.md ausgeliefert, und Pfade hier sind relativ zu diesem Ordner. Es braucht nichts aus anderen Skills oder anderen Ordnern, suchen Sie also nicht danach. Sofern der Benutzer keinen anderen Ort nennt, speichern Sie alles, was es erstellt, in out/og-image-animated/ unter dem aktuellen Projekt.
Die statische Share-Karte, animiert als kurze, ruhige Enthüllung:
- Leere Karte: nur Hintergrund und weicher Glanz.
- Markenzeichen und Titel fallen von oben ein (ausblenden + nach unten gleiten).
- Das App-Fenster steigt von unten auf (ausblenden + nach oben gleiten) und setzt sich genau dort ab, wo es auf der statischen Karte sitzt.
- Halten auf dem letzten Frame, der mit dem statischen OG-Bild übereinstimmen muss.
Beispiele: references/pulse.gif (das Ergebnis) und references/pulse-frames.png (vier Frames: Start, Titel erscheint, App steigt auf, Finale).
Regeln
- Von der statischen Karte ausgehen. Wenn das Projekt noch keine OG-Karten-Komponente hat, bauen Sie sie zuerst, indem Sie
references/static-card.mdfolgen (echtes Produkt, Nachrichten von der aktuellen Website, realistische Daten). Die Animation fügt nur Bewegung hinzu: gleiches Markup, gleiches endgültiges Layout, kein neuer Inhalt. - Eine Komponente, zwei Modi. Fügen Sie der vorhandenen Kartenkomponente eine
animated-Prop hinzu, anstatt sie zu kopieren, damit das statische PNG und die Animation nie auseinanderdriften. Ohne die Prop wird nichts animiert. - Bewegung, keine Effekte. Nur
opacity+transform: translateY, eine gemeinsame Ease-Out-Kurve (cubic-bezier(0.16, 1, 0.3, 1)). Kein Hüpfen, Unschärfe, Skalierungseinblendungen, Schreibmaschinentext oder rotierende Elemente. - Kurz. Gesamt-Timeline etwa 2–2,5 s, dann ein ~1,5 s Halten. Der Titel muss bei ~1,3 s vollständig lesbar sein.
- Nur CSS-Animationen (Keyframes +
animationmitboth-Fill), keine JS-gesteuerten Tweens oder Timer innerhalb der Karte. Der Aufnehmer sucht CSS-Animationen über die Web Animations API; JS-gesteuerte Bewegungen würden nicht deterministisch erfasst.
Zeitplan
| Element | Keyframes | Dauer | Verzögerung |
|---|---|---|---|
| Markenzeichen | von opacity: 0; translateY(-48px) | 900ms | 100ms |
| Titel | von opacity: 0; translateY(-48px) | 1000ms | 250ms |
| App-Fenster | von opacity: 0; translateY(320px) | 1300ms | 700ms |
Passen Sie die Abstände an die Karte an: Die App sollte größtenteils unterhalb der Unterkante beginnen (etwa halbe Kartenhöhe) und der Titel etwa in seiner eigenen Höhe über seinem Ruheplatz. Wenn es ein schwebendes Panel gibt, lassen Sie es zuletzt erscheinen (+200ms nachdem das Fenster startet).
Schritte
1. Erkunden
- Finden Sie die statische Kartenkomponente und ihre Render-Route (z. B.
og-image.tsx,/og/<seite>) sowie das aktuelle PNG inpublic/. - Notieren Sie die Wrapper für Markenzeichen, Titel und App-Fenster. Wenn das Fenster
zoomzum Anpassen verwendet, animieren Sie einen inneren Wrapper, nicht das gezoomte Element, damit die Offsets korrekt bleiben.
2. Animierten Modus hinzufügen
In der Kartenkomponente:
const KEYFRAMES = `
@keyframes og-drop { from { opacity: 0; transform: translateY(-48px); } to { opacity: 1; transform: none; } }
@keyframes og-rise { from { opacity: 0; transform: translateY(320px); } to { opacity: 1; transform: none; } }
`;
const EASE = 'cubic-bezier(0.16, 1, 0.3, 1)';
const enter = (name: string, ms: number, delay: number) => ({ animation: `${name} ${ms}ms ${EASE} ${delay}ms both` });
// <div data-og-frame …>{animated && <style>{KEYFRAMES}</style>} …
// brand: style={animated ? enter('og-drop', 900, 100) : undefined}
// title: style={animated ? enter('og-drop', 1000, 250) : undefined}
// window: <div style={{ zoom }}><div className="h-full" style={animated ? enter('og-rise', 1300, 700) : undefined}>…
Platzieren Sie die Keyframes in der Komponente (ein <style>-Tag) oder im globalen CSS des Projekts; bei Tailwind v4 werden Keyframes innerhalb von @theme nur ausgegeben, wenn ein passendes --animate-*-Token verwendet wird, bevorzugen Sie daher die Komponente oder einfaches CSS.
3. Eine Web-Route hinzufügen, die es abspielt
Ein Geschwister der statischen Route, z. B. /og/<seite>-animated (noindex, keine App-Chrome):
- Rendert
<Card animated />innerhalb des 1200×630-Rahmens. - Wiederholt für die Vorschau: Die Karte wird mit einem sich ändernden
keyalle ~4,5s neu gemountet. ?loop=0spielt einmal ab (der Aufnehmer verwendet dies). Normalisieren Sie den Suchparameter zuerst zu einem String: Router wie TanStack parsen?loop=0als Zahl0, und eine übersehene Prüfung würde die Karte während der Aufnahme weiterhin neu mounten.
Öffnen Sie es im Browser und schauen Sie es sich mehrmals an. Überprüfen Sie die Reihenfolge der Einblendungen, dass nichts vor dem Start der Animation aufblitzt und dass der Endzustand mit der statischen Karte übereinstimmt.
4. MP4 + GIF aufnehmen
Starten Sie den Dev-Server:
node <dieses Skill-Verzeichnis>/scripts/record.mjs \
--url "http://localhost:<port>/og/<seite>-animated?loop=0" \
--out out/og-image-animated/og-<seite>
Erzeugt og-<seite>.mp4 (2400×1260, H.264, 30fps), og-<seite>.gif (1200px breit, palette-optimiert, loops) und og-<seite>.png (letzter Frame). Funktionsweise: Es pausiert jede Animation auf der Seite, liest die Timeline-Länge, sucht dann alle Animationen Frame für Frame und macht einen Screenshot eines festen Ausschnitts von [data-og-frame]. Das Ergebnis ist bei jedem Durchlauf identisch, ohne ausgelassene Frames. Optionen: --fps, --hold, --lead, --scale, --formats mp4,gif,png, --selector.
Benötigt ffmpeg im PATH. Playwright installiert beim ersten Lauf in das scripts/-Verzeichnis dieses Skills, inklusive Chromium, falls keines gefunden wird.
Fallstricke:
- Die Seite darf keine reduzierte Bewegung erzwingen. Viele globale Stylesheets verkürzen Animationen unter
prefers-reduced-motion; der Aufnehmer emuliert dies nicht und schlägt laut fehl, wenn er keine Animationen findet. - Element-Screenshots warten auf „Stabilität“, die während einer Animation nie eintritt. Deshalb schneidet das Skript einen Seitenbereich aus.
- Stellen Sie sicher, dass der Port wirklich diese App bereitstellt (ein anderer lokaler Server könnte auf
localhostantworten).
5. Überprüfen
Extrahieren Sie ein Kontaktblatt und sehen Sie es sich an:
ffmpeg -y -loglevel error -i og-<seite>.mp4 \
-vf "select='eq(n\,8)+eq(n\,22)+eq(n\,40)+eq(n\,<letzter>)',scale=1000:-1,tile=2x2" -frames:v 1 sheet.png
- Frame ~0.25s: leere Karte (nur Glanz), kein Layout-Pop.
- ~0.7s: Titel drin oder fast drin, App noch nicht sichtbar.
- ~1.3s: App steigt auf, Titel vollständig lesbar.
- Letzter Frame: Inhaltlich identisch mit dem statischen PNG.
Halten Sie das GIF einigermaßen klein (unter ~3MB). Wenn es größer ist, senken Sie --fps (20–24) oder verkürzen Sie --hold.
Ausgabe
Teilen Sie dem Benutzer mit:
- die Vorschau-Routen-URL (loopt) und die geschriebenen Dateien (MP4, GIF, PNG)
- den Befehl zur erneuten Erstellung
- die Timeline (was sich bewegt, Dauern)
- dass
og:imagedas statische PNG bleiben muss: soziale Plattformen spielen keine animierten OG-Bilder ab. Verwenden Sie das MP4/GIF für Beiträge, README, Startseiten oderog:videowo unterstützt.