Was macht Whiteboard-Animation?
Der VideoScribe / Doodly-Look: Eine Hand zeichnet Illustrationen und Handschrift Strich für Strich auf eine Tafel, während eine Erzählung den Inhalt erklärt. Erstelle es aus animierten SVG-Pfaden, die sich selbst zeichnen, plus einer Markerhand, die der Zeichenspitze folgt. Ordne die Elemente dann so an, dass sich die Tafel in der Reihenfolge der Erzählung füllt.
Wann verwenden
- Eine "Scribe"- / Doodle-Erklärung, bei der eine Hand Kunst und Text auf ein Whiteboard zeichnet.
- Animation einer Skizze oder eines Logos, das Strich für Strich live gezeichnet wird.
- Handschrift, die sich selbst schreibt, synchron zu einem Voiceover.
- Umwandlung einer statischen Illustration in eine geführte, Strich-für-Strich-Enthüllung.
Kernmechanismus: SVG-Strich-Zeichnung
Ein Pfad "zeichnet sich selbst", indem stroke-dashoffset von seiner vollen Länge auf 0 animiert wird – die Strichlücke schrumpft und legt den Strich von Anfang bis Ende frei.
const path = document.querySelector("#stroke");
const len = path.getTotalLength();
path.style.strokeDasharray = len; // ein Strich so lang wie der gesamte Pfad
path.style.strokeDashoffset = len; // komplett aus dem Bild geschoben = unsichtbar
path.getBoundingClientRect(); // Reflow erzwingen, bevor der Übergang beginnt
path.style.transition = "stroke-dashoffset 1.2s linear";
path.style.strokeDashoffset = "0"; // zeichnet von Anfang → Ende
Verwende pathLength="1" auf dem <path>, um zu normalisieren: dann zeichnet stroke-dasharray:1; stroke-dashoffset:1 jeden Pfad unabhängig von seiner tatsächlichen Länge, und ein einzelner abgestufter Wert (0→1) ist der Zeichenfortschritt. linear (oder eine sehr sanfte Abmilderung) wirkt wie eine gleichmäßige Hand; vermeide ease-in-out bei langen Strichen – es lässt den Marker ruckeln.
Die Markerhand folgt der Spitze
Die Illusion steht und fällt damit, dass sich die Hand genau an dem Punkt befindet, der gerade gezeichnet wird. Taste den Pfad am aktuellen Zeichenfortschritt ab und platziere das Handbild dort in jedem Frame; die Spitze des Hand-Assets muss auf den Pfadpunkt ausgerichtet sein (verschiebe das Bild so, dass seine Spitze, nicht seine Ecke, auf dem Punkt liegt).
const hand = document.querySelector("#hand"); // <img>/<g>, Spitze an der oberen linken "Nase"
const NIB = { x: 6, y: 4 }; // Nasen-Offset innerhalb der Handgrafik
function drawOn(path, hand, dur = 1200) {
const len = path.getTotalLength(), t0 = performance.now();
path.style.strokeDasharray = len;
(function frame(now) {
const k = Math.min(1, (now - t0) / dur); // 0→1 Fortschritt
path.style.strokeDashoffset = len * (1 - k); // Start→Spitze freilegen
const p = path.getPointAtLength(len * k); // aktuelle Spitze in SVG-Koordinaten
hand.setAttribute("transform", `translate(${p.x - NIB.x} ${p.y - NIB.y})`);
if (k < 1) requestAnimationFrame(frame);
})(t0);
}
getPointAtLength(len * k) ist das Arbeitstier: Es gibt die Koordinate auf dem Pfad beim gleichen Fortschritt zurück, der strokeDashoffset antreibt, sodass die Spitze am wachsenden Strich haftet. Hebe die Hand zwischen den einzelnen Strichen an (ausblenden, zur nächsten Startposition springen), damit sie nicht über die leere Tafel gleitet.
Einblendungsreihenfolge – die Tafel füllt sich
Ordne die Elemente so an, wie eine Person die Szene zeichnen würde, in der Reihenfolge der Erzählung: Jede Illustration und jeder Handschriftblock wird eingeblendet, bleibt einen Moment stehen, dann beginnt der nächste. Staffle die Striche innerhalb einer Zeichnung; halte nach jedem Element einen kurzen Moment inne, bevor du die Hand zum nächsten bewegst. Eine Zeichnung = ein Takt der Erzählung. Zeichne nicht zwei Dinge gleichzeitig – das Auge (und die einzelne Hand) kann nur einer Spitze folgen.
| Schritt | Mechanismus |
|---|---|
| Strich zeichnen | stroke-dashoffset Länge→0, Hand bei getPointAtLength(Länge*k) |
| Mehrstrichzeichnung | Striche staffeln; Hand springt zum Start jedes neuen Strichs |
| Handschrift | Striche pro Buchstabe/Wort in Lesereihenfolge zeichnen, Hand folgt |
| Innehalten | Hand nach Abschluss des Elements kurz vom Brett nehmen (0,4–1,0 s) |
| Nächstes Element | Hand zum nächsten Start bewegen/ausblenden; dessen Zeichnung beginnen |
| Löschen / Leeren | Wischen oder rückwärts zeichnen, um die Tafel für den nächsten Abschnitt zu leeren |
Konvertieren von Grafiken in zeichenbare Pfade
Das Zeichnen benötigt einzügige, offene Pfade in Zeichenreihenfolge – keine gefüllten zusammengesetzten Formen.
- Erstelle oder zeichne Strichgrafiken als offene Striche (Illustrator/Inkscape: Kontur, nicht Füllung). Eine gefüllte Fläche hat keinen "Strich", den man animieren könnte; wandle Füllungen in einen Mittellinienstrich um oder zeichne einen Konturpfad und fülle ihn nach Abschluss der Kontur.
- Die Reihenfolge ist wichtig: Die
<path>-Elemente sollten im SVG in der Reihenfolge erscheinen, in der eine Hand sie zeichnen würde – animiere sie in der Dokumentenreihenfolge. - Lange durchgehende Linien wirken am natürlichsten; unterbrich nur, wo ein echter Stift abgesetzt würde.
- Für einfarbige Bereiche: Zeichne zuerst die Kontur, dann blende die Füllung dahinter ein (
opacityoder eine Clip-Enthüllung), sodass es wie "nachträglich ausgemalt" wirkt. - Handschrift: Verwende eine Strich-/Handschrift-Schriftart, wandle Glyphen in Pfade um und zeichne dann jeden Glyphenpfad in der Strichreihenfolge. Oder simuliere es: Maskiere das Wort und streiche eine Enthüllung von links nach rechts, wobei die Hand der Maskenkante folgt.
Markerhand-Asset
Ein PNG/SVG einer Hand, die einen Marker hält, mit der Spitze an einem bekannten Punkt. Miss den Spitzen-Offset einmal (NIB oben) und verwende ihn wieder. Verwende für das gesamte Stück ein einziges Hand-Asset für Konsistenz. Spiegele es (scaleX(-1)) nur, wenn du eine linke Hand benötigst. Füge einen leichten Schatten unter der Hand für Tiefe hinzu; lass ihn während der Pausen weg, wenn die Hand "abgesetzt" ist.
Lösch- / Wisch-Übergänge
Zwischen den Abschnitten die Tafel leeren, damit sie nicht überfüllt wirkt:
- Wischen: Animieren eines
clip-path(oder eines weißen Rechtecks) über die gefüllte Gruppe, um sie wegzuwischen, die Hand optional "löschend". - Rückwärts zeichnen:
strokeDashoffset0→Länge ausführen, um rückgängig zu machen, Hand folgt rückwärts. - Ausblenden + neu zeichnen: Blende die alte Gruppe über Kreuz aus und beginne die Zeichnung der nächsten Gruppe.
Behalte eine klare Grammatik bei (z. B. immer von links nach rechts wischen), damit sich Übergänge bewusst anfühlen.
Tempo zur Erzählung
Die Zeichendauer sollte dem gesprochenen Satz folgen, keinem festen Timer. Schätze aus der Erzählung mit ~2,3 Wörtern/s; setze die gesamte Zeichnungszeit für jede Zeichnung auf ungefähr die Länge des Satzes, den sie illustriert, plus eine kurze Pause. Ein Label, das die Erzählung nennt, sollte genau dann fertig gezeichnet sein, wenn das Wort ausgesprochen wird. Verlangsame die Hand für betonte Linien; beschleunige kleinere verbindende Striche. Lass die Hand niemals auf einer fertigen Tafel ruhen, während die Erzählung weiterläuft – bewege sie weg oder beginne das nächste Element.
Ausgabe-Checkliste
- Jeder Strich ist ein einzelner offener Pfad in der Zeichenreihenfolge; nichts erscheint fertig geformt.
- Die Handspitze sitzt während jedes Strichs exakt auf der Zeichenspitze (kein Schweben, kein Nachhinken).
- Die Hand hebt sauber zwischen den einzelnen Strichen/Elementen ab; kein Gleiten über die leere Tafel.
- Elemente werden nacheinander in der Reihenfolge der Erzählung gezeichnet; jedes hält inne, bevor das nächste beginnt.
- Handschrift wird in Lesereihenfolge gezeichnet; Füllungen erscheinen nach ihrer Kontur.
- Die Lösch-/Wisch-Grammatik ist konsistent; die Tafel wird niemals überfüllt.
- Die Zeichenzeit folgt dem Erzählsatz, den sie illustriert.
prefers-reduced-motion: Zeige die fertige Tafel (alle Striche bei Offset 0, Hand ausgeblendet) ohne die Zeichenanimation.
Ausliefern und verifizieren (eigenständiges HTML)
Gepacktes Hilfsskript (
scripts/):scripts/seek-shot.sh anim.html 0 1.5 3friert die?t=N-Umgebung ein und erstellt Screenshots von jedem Moment;scripts/contact-sheet.sh sheet.png frame-*.pngerstellt eine Kontaktblatt-Montage zur schnellen Durchsicht. Siehescripts/README.md.
Für eine eigenständige Whiteboard-Szene (gezeichnete Illustration, Handschrift, ein kurzer Scribbeats) ist das Ergebnis ein HTML-file, das sich direkt im Browser öffnen lässt – kein Build-Schritt, keine Render-Pipeline. Eine einzelne Datei ist die richtige Stufe für Web-Animationen; greife nicht zu einem Bundler, wenn eine Datei ausreicht. (Für ein vollständiges vertontes Scribe-Video mit eingebackener Erzählung erstelle es als Remotion-Komposition und verifiziere mit remotion still – siehe explainer-video.)
Ausgabe-Vertrag:
- Ein
.html-File: SVG inline (Pfade in Zeichenreihenfolge,pathLength="1"oder gemessene Länge), das Hand-Asset inline oder als data-URI, und der Zeichen-Treiber in einem Inline-<script>. - Alles zeichnet auf einer Master-Timeline (GSAP
tl, oder eine rAF-Uhr), sodass die gesamte Sequenz einen einzigen Playhead hat, den du suchen kannst –strokeDashoffsetUND die Handposition werden beide vom selben Fortschrittswert gesteuert. - Füge die folgende Suchhilfe ein, damit jeder Moment für Screenshots eingefroren werden kann. Das Einfrieren bei
tzeigt genau, wie viel vom Pfad gezeichnet ist – die Verifikation stützt sich darauf.
Suchhilfe – einen genauen Moment für Screenshots einfrieren. ?t=N sucht die Master-Timeline zu N Sekunden und pausiert, sodass ein Screenshot auf einem eingefrorenen, deterministischen Frame mitten im Zeichenvorgang landet.
<script>
// ... baue deine Master-Timeline als `tl` (drawOn-Aufrufe werden darauf platziert) ...
const t = new URLSearchParams(location.search).get("t");
if (t !== null) { tl.pause(); tl.seek(parseFloat(t)); } // eingefroren bei t Sekunden
// kein ?t → normale Wiedergabe
window.__ready = true; // Bereitsignal für Headless-Wartezeit
console.log("duration", tl.duration());
</script>
Verifikationsschleife – rendern → einfrieren → Screenshot → prüfen:
- Öffne die Datei zu verschiedenen Zeitpunkten auf der Timeline – Anfang, ein Frame mitten im Zeichnen, Ende:
…/scribe.html?t=0,?t=<dur/2>,?t=<dur>. Liestl.duration()von der Konsole für die Endzeit aus. Wähle mindestens eintmitten in einem Strich – das ist der Punkt, an dem die Hand-an-der-Spitzen-Illusion bewiesen oder widerlegt wird. - Erstelle Headless-Screenshots von jedem eingefrorenen Frame:
npx playwright screenshot --wait-for-timeout=500 "file://$PWD/scribe.html?t=1.2" frame-mid.png - PRÜFE jeden Standbild – überprüfe die Wiedergabetreue: Bei einem
tmitten im Strich sitzt die Handspitze genau an der vorderen Spitze des gezeichneten Teils (nicht davor, nicht dahinter, nicht schwebend); der Pfad ist nur bis zur Spitze gezeichnet; bei?t=<dur>ist jeder Strich sauber abgeschlossen, ohne Lücken, ohne Überschwingen, ohne verbleibende Strichlängen. Überprüfe auf Artefakte: Die Hand gleitet zwischen Strichen über die leere Tafel, der Spitzen-Offset ist falsch (Spitze schwebt von der Linie), Striche werden in falscher Reihenfolge gezeichnet, Füllungen erscheinen vor ihrer Kontur, abgeschnittene/außerhalb der Zeichenfläche liegende Zeichnungen, FOUC (Flash of Unstyled Content) bevor Schriftarten geladen sind. - Iteriere: Passe
NIB, Strichreihenfolge, Dauern an und erstelle erneut Screenshots, bis jeder eingefrorene Frame wie eine Hand mitten im Zeichnen aussieht.
Bevor du fertig bist:
- Öffnet eigenständig im Browser – keine Konsolenfehler, keine fehlenden CDN/Assets.
- Eine Master-Timeline;
?t=Nfriert korrekt ein undstrokeDashoffset+ Handposition teilen sich einen Fortschrittswert. - Per Screenshot bei Anfang / Mitte eines Strichs / Ende – Handspitze liegt durchgehend auf der Spitze, Striche sind am Ende sauber abgeschlossen, Zeichenreihenfolge korrekt.
- Hand hebt zwischen Strichen ab; kein Gleiten über die leere Tafel.
prefers-reduced-motionzeigt die fertige Tafel (alle Striche gezeichnet, Hand ausgeblendet) ohne die Zeichenanimation.
Für einen vertonten, frame-deterministischen Export portiere dieselbe Zeichenfunktion (strokeDashoffset und die Handtransformationssteuerung über useCurrentFrame()/fps) in eine Remotion-Komposition und rendere sie als MP4/GIF – siehe das explainer-video-Skill für den Render-Stills → Kodierungs-Loop.
Referenzdateien
references/draw-on-recipes.md– ausführbare Zeichenmechaniken:getTotalLength/getPointAtLengthHand-folgt-Pfad, GSAPDrawSVGPluginundMotionPathPluginVarianten, Staffelung mehrerer Striche, Handschrift pro Glyphe, Füllung-nach-Kontur, Lösch-/Wisch- und Rückwärts-Zeichenübergänge, und der von Frames gesteuerte Remotion-Port.references/whiteboard-pipeline.md– Umwandlung von Kunst in zeichenbare Einzelstrich-SVGs, Erstellung der Zeichenreihenfolge, Handschrift-/Strich-Schriftarten, das Markerhand-Asset und die Spitzenkalibrierung, Abstimmen der Zeichenzeit auf die Erzählsätze, sowie die Abfolge Storyboard-zu-Tafel-Erstellung.