HTML5-Canvas und Javascript: Einstieg und Malprogramm

Dieser Artikel behandelt das mit HTML5 eingeführte Canvas-Element und die Manipulationsmöglichkeiten mit Javascript. Nachdem die Grundlagen erklärt worden sind wird ein „Maleditor“ als Beispielprojekt programmiert.

Was ist Canvas?

Canvas ist ein Element, das mit dem HTML5-Standard eingeführt wurde. Übersetzt aus dem Englischen bedeutet es „Leinwand“ oder „Gemälde“, und genau das ist es auch: Ein Element, das durch HTML als leere Leinwand deklariert wird, und auf das durch Javascript ein Gemälde, statisch oder animiert, gezeichnet werden kann. Die jeweils aktuellen Versionen der „großen Browser“ Firefox, Chrome, Safari, Opera und der Internet Explorer (ab Version 9.0) unterstützen das Canvas-Element. 1)

Wie binde ich Canvas ein?

Canvas ist ein eigenständiges HTML5-Element. Zwischen dem öffnenden und dem schließenden Tag kann eine Fallback-Nachricht eingefügt werden, die Nutzer, deren Browser nicht HTML5 bzw. das Canvas-Element unterstützen, darüber informiert. Der folgende Code zeigt sie Einbindung des Elements in ein HTML5-Dokument:

<!DOCTYPE html>
<head>
	<title>Canvas Example</title>
</head>
<body>
 
	<canvas>
		<p>Ihr Browser unterstützt das Canvas-Element nicht. Bitte installieren sie eine neuere Version.</p>
	</canvas>
</body>
</html>

Wenn du dieses HTML5 Dokument in deinem Browser öffnest, solltest du im besten Falle nichts sehen. Wenn der Fallback-Text erscheint, unterstützt dein Browser das Canvas-Element nicht und du solltest eine neuere Versionen installieren oder einen anderen Browser nutzen. Denn Canvas-Element ist unmanipuliert weiß und hat zum Beispiel im Firefox eine Standardgröße von 300x150px. Wenn du auf die oberen, linken Ecke des Dokuments rechtsklickst, dann solltest du die Option „Grafik anzeigen“ und „Grafik speichern unter“ haben. Lässt du dir die Grafik anzeigen siehst du in der Adresszeile des Browsers den Inhalt des (leeren) Canvas im png-Format, als base64 verschlüsselt.

data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAASwAAACWCAYAAABkW7XSAAAAxUlEQVR4nO3BMQEAAADCoPVPbQhfoAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOA1v9QAATX68/0AAAAASUVORK5CYII=

Noch ist die Zeichenkette nicht sehr lang, aber wenn wir etwas die Größe des Canvas verändern oder später etwas zeichnen, so verändert sich auch dieses „Rohformat“ des Canvas.

Bei dem folgenden Canvas wurde durch das height- und width-Attribut zunächst die Größe auf 200×200 Pixel festgesetzt. Außerdem wurde per CSS ein schwarzer, ein Pixel breiter Rand um das Element herumgelegt

Wichtig: Die Größe des Canvas wird nur durch das height- und width-Attribut beeinflusst, per CSS kann nur der angezeigte Ausschnitt des Cavas-Elements verändert werden.

Das id-Attribut sorgt dafür, dass wir gleich das Canvas-Element mit Javascript als „my_first_canvas“ identifizieren können.

[...]
<canvas height="200" width="200" style="border:1px solid #000;" id="my_first_canvas">
	<p>Ihr Browser unterstützt das Canvas-Element nicht. Bitte installieren sie eine neuere Version.</p>
</canvas>
[...]

Der schwarze Rand ist jedoch noch nicht auf das Canvas, also die „Leinwand“ gemalt, sondern nur um das HTML-Element herum: Wenn du dir das Canvas als Grafik anzeigen lässt, ist er verschwunden.

Initialisierung durch Javascript

Alleine mit HTML wird das Canvas-Element weiß bleiben. Um zu es zu füllen benötigt man Javascript, dass du der Übersicht halber am besten aus einer externen .js-Datei lädst:

<!DOCTYPE html>
<head>
	<title>Canvas Example</title>
	<script type="text/javascript" src="canvas.js"></script>
</head>
<body>
[...]

Javascript musst du zunächst vermitteln, um welches Element es geht, damit du es ansprechen kannst:

var ctx= null;
window.onload = function() {
	var canvas = document.getElementById("my_first_canvas");
	if(canvas && canvas.getContext)
	{ 
		ctx = canvas.getContext('2d');
	}
}

Die Variablectx, was für Canvas-Context steht, werden wir bei jeder Manipulation des Elements benötigen, weshalb sie außerhalb der Funktion deklariert wurde und deswegen global, also aus allen Funktionen heraus, nutzbar ist. Die getElementById-Funktion sucht zunächst im Standardobjekt „document“, womit das gesamte HTML-Dokument gemeint ist, nach einem Element mit der Id „my_first_canvas“ und übergibt es an die lokale Variable canvas.

Um zu verhindern, dass dieser Code bereits ausgeführt wird, bevor das eigentliche HTML-Dokument vollständig geladen wurde und Javascript deswegen das Element nicht finden kann, werden die beiden Zeilen nur ausgeführt, wenn der Eventhandler window.onload() „getriggert“, also ausgelöst wurde.

Wenn das Element gefunden wurde, was durch die if-Verzweigung geprüft wird, wird der globalen Variable cctx der „2d-Context“ des Canvas Element zugewiesen, der es erlaubt auf das HTML-Element mit den nun folgenden Funktionen zu malen.

Manipulation des Canvas

Javascript bietet mehrere Funktionen, die es erlauben auf dem Canvas-Element zu zeichen.

Linien zeichnen

var ctx= null;
window.onload = function() {
	var canvas = document.getElementById("my_first_canvas");
	if(canvas && canvas.getContext)
	{ 
		ctx = canvas.getContext('2d');
		cxt.moveTo(0,0);
		cxt.lineTo(100,100);
		cxt.stroke();
	}
}

Mit der Funktion moveTo(x,y) geben wir den Startpunkt der Linie an. Du kannst dir das so vorstellen als würdest du einen Stift über ein Blatt Papier bewegen - ohne ihn aufzusetzen. Die Koordinaten 0,0 geben befinden sich in der oberen, linken Ecke des Canvas, die Koordianten 200,200 (zur Erinnerung, unser Canvas ist 200×200 Pixel groß) befindet sich dementsprechend rechts unten.

Die erste Koordinate (x) gibt die Entfernung von der oberen Kante des Canvas nach unten, die zweite Koordinate y die von der linken Seite nach rechts an.

Die Funktion lineTo(x,y) zieht eine Verbindung von der aktuellen Position, die dank moveTo in diesem Fall bei 0,0, also in der oberen, linken Ecke befindet, zu den angegebenen Koordinaten, also 100,100. Bei unserem 200×200 Canvas also genau in die Mitte.

Noch ist diese Verbindung allerdings nicht sichbar. Die Funktion stroke() sorgt dafür, dass alle unsichtbaren Verbindungen sichtbar werden, so dass das Endergebnis so aussieht:

BILD!!!

Es können beliebig viele Linien gezeichnet werden, bevor der stroke-Befehl alles auf die Leinwand bringt:

[...]
ctx = canvas.getContext('2d');
cxt.moveTo(125,75);
cxt.lineTo(75,75);
cxt.lineTo(50,125);
cxt.stroke();
[...]