HTML5-Canvas Lauftexte (Teil 1)

In den letzten beiden Beiträgen unseres Workshops über Digital Signage Newsletter zeigten wir Ihnen die Erstellung eines Lauftextes mit CSS3-Animationen, welche Schlagzeilen aus einem RSS-Feed abspielt. In diesem Artikel stellen wir eine interessante Alternative mit dem HTML5-Element Canvas vor. Canvas Lauftexte einzusetzen bringt Vorteile und Nachteile. Diese wollen wir in den folgenden beiden Beiträgen genauer erörtern.

Canvas Lauftexte
Canvas Lauftexte
Bildquelle: Herbert Weber, Hildesheim, Kreuzgang san paolo fuori le mura 3, cropped, CC BY-SA 3.0

Was ist ein HTML5-Canvas?

Ein Canvas (Leinwand) ist in HTML5 ein definierter Bereich in welchem mit Javascript-Befehlen gezeichnet werden kann. Ursprünglich entwickelte Apple Canvas für ihren Browser Safari. Später wurde er als Bestandteil von HTML5 standardisiert. Canvas ermöglicht das Zeichnen von Kreisen, Linien, Polygonen und anderen geometrische Figuren. Eine Referenzkarte befindet sich bei Wikipedia. Das Element ist sehr vielseitig und kann durch seine Bildfunktionen auch Videos abspielen. Diese können z.B. auch zusätzliche Effekte in Echtzeit enthalten. Alle aktuellen Browser (April 2018) sind in der Lage mit dem Canvas-Element umzugehen.
In HTML wird er so eingesetzt:

<canvas id="myTicker" width="500" height="80">No Canvas</canvas>

Der Text „No Canvas“ ist ein sogenannter „Fallback“. Er wird nur von Browsern angezeigt, die kein Canvas darstellen können z.B. dem IE 8. Die Höhe setzen wir laufleistentypisch auf 80 Pixel und die Breite auf 500 Pixel.
Mit id geben wir dem Element eine eindeutigen Identifikation, um es über Javascript korrekt ansprechen zu können.

Wie zeichnen wir einen Text in Canvas?

Dazu fügen wir folgende Zeilen zwischen den body-Tags im HTML-Quelltext:

<canvas id="myTicker" width="500" height="80" style="border:1px solid #ddd;">
	No Canvas
</canvas>
<script>
	var MyCanvas = document.getElementById("myTicker");
	var ctx      = MyCanvas.getContext("2d");
	ctx.font     = "30px Arial";
	ctx.fillText("Lorem ipsum dolor sit amet, consetetur", 10, 50);
</script>

Da der Browser seine Inhalte von oben nach unten abarbeitet, ist es für dieses Beispiel wichtig die Javascript-Befehle nach dem Canvas-Element einzugeben. Alternativ können wir natürlich den Canvas auch mittels onload im body Tag laden. Wir fügen zusätzlich mit style=“border:1px solid #ddd;“ der Übersicht halber einen grauen Rand hinzu. Der Befehl document.getElementById(„myTicker“); lädt das existierende Element in die Variable MyCanvas. Nun benötigt Javascript einen Kontext zum Canvas.

Der Canvas-Kontext

Unter einem Kontext versteht der Programmierer eine Schnittstelle zu einem Objekt. Der Kontext stellt Funktionen und Datenstrukturen zur Verfügung, mit denen auf der Leinwand (Canvas) gezeichnet wird. Durch MyCanvas.getContext(„2d“) wird klargestellt, dass hier nur Funktionalität für zweidimensionale Vektorgrafik benötigt wird. Alternative Kontexte wären z.B. webgl/webgl2 für dreidimensionale Vektorgrafik oder bitmaprenderer, um pixeloriente Grafikfunktionen nutzen zu können. Da wir diese nicht benötigen initialisieren wir die Kontextvariable ctx mit 2d.
Als nächstes wird mittels ctx.font = „30px Arial“ dem Canvas-Kontext ein 30 Pixel großer Arial Font zugewiesen. Mit dem Befehl fillText wird schließlich der Text „Lorem ipsum dolor sit amet, consetetur“ ausgegeben.
Die beiden nachfolgenden Parameter setzen den Tickertext 10 Pixel rechts vom Rand und 50 Pixel von oben. Dabei wird vom Textanfang unten links ausgegangen. Da die Schrift 30 Pixel hoch ist bedeutet ein Wert von 50, dass der Text 20 Pixel unterhalb des Randes oben steht.
Klicken Sie auf canvas_animations_1.html, um zu das Ergebnis zu sehen.

Animation in Javascript

Wir müssen jetzt den Text dazu bringen sich zu „bewegen“. Die grundlegende Herangehensweise für Canvas Lauftexte besteht darin, innerhalb von kurzen Zeitintervallen die Position der Inhalte zu verändern. Um für das menschliche Gehirn den Eindruck einer flüssigen Bewegung zu erzeugen, dürfen diese Intervalle auf einem digitalen Bildschirm höchstens eine 30stel Sekunde dauern. Wir sprechen dann von der sogenannten Framerate, die in diesem Fall 30fps (Frames pro Sekunde) beträgt. Um Ruckeleffekte bei schnellen Bewegungen wie z.B. in Videos oder Spielen zu vermeiden werden sogar 60fps notwendig. Wir brauchen deshalb eine Javascript-Funktionalität, die zeitgesteuert bestimmte Aktionen startet. Früher wurden dafür die Funktionen setTimeout oder setInterval eingesetzt. Diese Methode Animationen zu erstellen ist inzwischen veraltet und suboptimal.

Die Alternative heißt requestAnimationFrame

Seit ca. 2013 unterstützen alle aktuellen Browser eine effiziente Funktion namens requestAnimationFrame. Diese Funktion informiert den Browser, dass eine Animation ansteht. Worauf dieser selbstständig die Framerate auswählt und speziell für Animationen ausgelegte interne Routinen einsetzt. Dabei besteht die oberste Priorität darin, die Animation möglichst ruckelfrei ablaufen zu lassen. Es grundsätzlich besser, wenn der Browser die Framerate festlegt, da der optimale Wert abhängig von der Anzahl und der Art der Animationen auch während der Laufzeit variieren kann. Mit den alten statischen Funktionen werden schnell Grenzen erreicht. Außerdem stoppt die Animation wenn der Benutzer das Browsertab wechselt, während Animationen mittels setInterval() oder stTimeout() in dem Fall einfach weiterlaufen und sinnlos Ressourcen verbrauchen.

Der erste Lauftext

Wir erweitern Beispiel 1, um den Text zu bewegen. Dieser soll unendlich oft von rechts nach links scrollen. D.h. sobald der letzte Buchstabe am linken Rand raus läuft startet der Ticker vom rechten Rand aus neu. Der dafür notwendige Code für Canvas Lauftexte sieht so aus:

<canvas id="myTicker" width="500" height="80" style="border:1px solid #d3d3d3;">
	No Canvas	
</canvas>	
<script>
	const move_pixel   = 1;
	var MyCanvas       = document.getElementById("myTicker");
	var ctx		   = MyCanvas.getContext("2d");
        ctx.font           = "30px Arial";
	var x              = 500;
	var ticker_content = "Lorem ipsum dolor sit amet, consetetur";
	var text_width     = ctx.measureText(ticker_content).width;
	ctx.fillText(ticker_content, x, 50);
	window.requestAnimationFrame(moveTicker);

	function moveTicker()
	{
		ctx.clearRect(0,0,x,80);
		if (x > -text_width)
			x = x - move_pixel;
		else
			x = 500;
		ctx.fillText(ticker_content, x, 50);	
		window.requestAnimationFrame(moveTicker);
	}
</script>

Als erstes setzen wir eine Konstante namens pixel_move. Dort legen wir fest um wie viele Pixel der Tickertext bei jeden Frame nach links gesetzt wird. Diese Variable steuert die Geschwindigkeit der Canvas Lauftexte. Bei höhere Werten scrollt lassen der Text schneller; bei kleineren Werten z.B. 0.5 langsamer. Ein Wert von 1 sollte für unsere Zwecke reichen.

Die nächsten Zeilen sind identisch zum ersten Beispiel. Da wir den Text durch den Canvas „schieben“ wird die x-Position bei jedem Durchlauf neu kalkuliert. Also setzen wir x = 500 als Startwert, denn bei 500 Pixel befindet sich der rechte Rand des Canvas. Der Inhalt wird, weil mehrfach genutzt zur Vereinfachung ebenfalls in eine Variable gesetzt.
Als nächstes muss das Skript die Weite des Textes in 30px Arial kennen, um zu erkennen wann der Text komplett durchgelaufen ist. Danach wird er bei Position 500px wieder neu gestartet. Diese Berechnung geschieht durch den Befehl ctx.measureText(ticker_content).width und wird in die Variable text_width geschrieben. Auf einem System mit Linux und Chromium/Linux entspricht das beispielsweise ca. 519 Pixel. Mit ctx.fillText(ticker_content, x, 50); setzen wir – wie oben beschrieben – den Textbeginn auf den rechten Rand des Canvas. Die nächste Zeile window.requestAnimationFrame(moveTicker) ruft die Funktion moveTicker auf. Programmierer bezeichnen eine Funktion, die als Parameter von einer anderen Funktion aufgerufen wird übrigens als sogenannte Rückruffunktion (Callback). In unserem Callback moveTicker passiert nun die „Magie“.

Der Algorithmus für Canvas Lauftexte

ctx.clearRect(0,0,x,80) löscht zunächst alle bisherigen Inhalte des Canvas-Kontextes. Als nächstes wertet das Skript mit der if..else-Bedingung den aktuellen x-Wert aus und entscheidet über die neue Textposition. Entweder solle der Text einen Pixel nach links rücken oder wieder auf den Anfangszustand zurück. Solange x größer ist als der negative Wert der Textlänge (also -519px), schiebt sich der Textinhalt immer weiter nach links. Die Variable x wird irgendwann kleiner als -519. Das bedeutet, dass der Text nun vollständig aus dem sichtbaren Bereich gelaufen ist. Also muss seine Position wieder den Startwert annehmen (x = 500).
Um die Animation in einer Endlosschleife abspielen zu können, ruft sich die Callback-Funktion zum Schluss wieder mittels requestAnimationFrame selbst auf. Programmierer nennen so etwas eine rekursive Funktion.
Klicken Sie auf canvas_animations_2.html, um das Ergebnis zu sehen. Falls Sie gerade an einem PC sitzen, werden Sie vermutlich feststellen, dass dieser Ticker auf Anhieb ruhiger läuft als Lauftexte mit CSS3-Animationen .

Wie geht es weiter?

Im nächsten Teil unseres Workshops werden wir die RSS-Behandlung aus dem vorherigen Beitrag CSS3-Animationen mit RSS leicht abgeändert für Canvas Lauftexte kombinieren.
Wenn Sie Fragen oder Anmerkungen haben, können Sie uns gerne kontaktieren.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.