Zum Inhalt springen
Michael Blaess
IT-Consulting
Michael Blaess
EN

retro-text-effects.js: Terminal-Texteffekte für den Browser

JavaScriptAnimationRetroOpen Source

Wer im Terminal lebt, kennt TerminalTextEffects (TTE) - die Python-Library, die Text im Terminal entschlüsselt, regnen oder explodieren lässt. Ich fand das großartig und wollte diese Effekte auch in meinen Web-Projekten haben - ohne Canvas-Zwang, ohne Framework, ohne Build-Step. Also habe ich TTE portiert: retro-text-effects.js ist dependency-freies Vanilla JavaScript, ausgeliefert als eine einzige Datei ohne externe Requests - auch DSGVO-technisch entspannt.

Live-Demo

Genug geredet - die Library läuft direkt hier im Artikel (die Buttons starten den jeweiligen Effekt):

 R E T R O - T E X T - E F F E C T S . J S

43 Effekte für den Browser eine Datei - null Dependencies der Text bleibt selektierbar kein Canvas nötig (außer du willst)

Text
Canvas
Stil

Jedes Emoji wird zur ASCII-Figur

Dieser eine Effekt stammt nicht aus TerminalTextEffects. Die Idee kommt von der Seite des Terminal-Emulators Ghostty: Dort schwebt ein Geist aus Textzeichen, umgeben von einem flackernden Ring. Das wollte ich nachbauen, aber nicht als fertiges Bild, sondern für jedes beliebige Zeichen.

Der Effekt heißt aura und funktioniert anders als alle anderen: Er erzeugt keinen Text, er rendert ein beliebiges Icon in animierte ASCII-Art. Das Emoji wird auf einer unsichtbaren Zeichenfläche gerendert, das Ergebnis in ein Zellraster zerlegt, und jede Zelle wird nach Deckung und Helligkeit auf ein Zeichen abgebildet.

Zeichen
Aura
Bewegung

Drei Dinge waren dabei schwierig.

Die Kontur entsteht an der Kante, nicht aus der Helligkeit. Bildet man nur Helligkeit auf Zeichen ab, franst die Figur am Rand aus, weil das Emoji dort weich ausläuft. Erst als jede Zelle mit einem leeren Nachbarn hart ein @ bekam, hatte die Figur einen sauberen Umriss.

Der Ring muss wissen, dass Textzellen hochkant sind. Der Abstand zur Figur wird über ein Distanzfeld berechnet. Zählt man einen Schritt nach links genauso schwer wie einen nach oben, wird aus dem Ring eine liegende Ellipse, denn eine Textzelle ist etwa doppelt so hoch wie breit. Der waagerechte Schritt zählt deshalb nur gut halb so viel.

Drehen darf keine CSS-Transformation sein. Der naheliegende Weg wäre, die fertige Figur per transform: rotate() zu kippen. Dann kippen aber die Buchstaben mit, und das Raster, das die Figur überhaupt erst ausmacht, zerfällt. Stattdessen wird das Emoji in sechzehn Stellungen einmal neu gerastert, und der Effekt spielt diese Stellungen als Schleife ab. Das Wippen ist ein Versatz um ganze Zeilen.

Wer die Zeichnung lieber einmalig und ohne Animation haben möchte, nimmt asciiArt('🎃'). Die Funktion gibt sie als Zeichenkette zurück, und die lässt sich dann in jeden anderen Effekt kippen, etwa in decrypt.

Eine Einschränkung gehört dazu: Emoji-Schriften unterscheiden sich je nach Betriebssystem. Derselbe Geist sieht unter Windows, macOS und Linux verschieden aus, weil jedes System seine eigene Emoji-Schrift mitbringt. Wer ein festes Ergebnis braucht, erzeugt die Zeichnung einmal und legt sie als Text ins Markup.

Vier Effekt-Gruppen

Inzwischen sind es 43 Effekte, aufgeteilt in vier Gruppen:

  • Text-Effekte (15 Stück) laufen auf einem normalen <pre>-Block und schreiben nur dessen Textinhalt um - kein Canvas, der Text bleibt selektierbar, Box-Drawing-Zeichen bleiben ausgerichtet, und die Farbe wird vom Element geerbt. Dazu gehören decrypt, print, matrix, burn, vhstape, waves, slide, pour und mehr.
  • Canvas-Effekte (24 Stück) legen temporär ein Canvas über das Element für freie 2D-Bewegung (fireworks, blackhole, rain, swarm, synthgrid, thunderstorm und weitere), blenden es danach aus und geben den unangetasteten Text darunter frei. Einige tragen eine 2 im Namen (matrix2, decrypt2, print2, overflow2): das sind die Canvas-Zwillinge der gleichnamigen Text-Effekte, aufwendiger, aber mit mehr Bewegung.
  • Style-Effekte (3 Stück) verändern das Element an Ort und Stelle, ohne den Text neu zu schreiben: crt legt eine dauerhafte Phosphor-Optik mit Scanlines darüber, colorshift einen laufenden Farbverlauf, highlight einen einzelnen Lichtstreifen.
  • Art-Effekte (bisher einer) lesen keinen Text von der Seite. aura rendert ein beliebiges Icon in die animierte ASCII-Art von oben und läuft dauerhaft, bis man ihn beendet. Das ist der einzige Effekt der Library ohne Vorbild in TerminalTextEffects, er ist von Ghostty inspiriert.

Integration in drei Zeilen

<pre id="log">=== System ready ===</pre>

<script src="retro-text-effects.min.js"></script>
<script>
  RetroTextEffects.decrypt('#log');
</script>

Das ist die komplette Integration: Ein Script-Tag exponiert window.RetroTextEffects, dann wird ein Effekt mit Element oder CSS-Selektor aufgerufen. Jeder Effekt liefert einen kleinen Controller zurück:

const fx = RetroTextEffects.print('#log', { cps: 80 });
fx.cancel();        // vorzeitig stoppen
await fx.finished;  // Promise, aufgeloest am Ende der Animation

Optionen wie speed, fps, glyphs oder color lassen sich pro Effekt anpassen. Schrift, Farbe und Zeichenraster liest die Library vom Ziel-Element ab, damit beim Übergang zum echten Text kein sichtbarer Sprung entsteht.

Warum Single File?

Die Library ist für den Fall gebaut, in dem man kein npm-Projekt hat: eine CMS-Seite, ein Widget, eine statische Demo. Datei kopieren, Script-Tag setzen, fertig - keine Dependencies, kein Build, keine externen Requests. Genau so ist übrigens auch die Demo in diesem Artikel eingebunden.

Links: GitHub-Repo · Live-Demo aller Effekte

“Es ist nicht wenig Zeit, die wir haben, sondern viel Zeit, die wir nicht nutzen.”

- Seneca