In meinem großen HTML5-Artikel kam letztens ein neues Element etwas zu kurz, das eigentlich etwas besseres verdient hatte. Denn dieses Element, <canvas>
, hat viel Potenzial. Von dezenten optischen Extras bis hin zu kompletten eigenen Programmoberflächen kann man damit einiges anstellen und alles was man dafür braucht, ist ein klein wenig Ahnung von HTML und Javascript.
Was ist <canvas>
und wozu ist es gut?
Das englische Wort Canvas bedeutet auf deutsch Leinwand
und ist ziemlich genau das: Eine Leinwand, auf die man mit Javascript dynamisch Bitmap-Grafiken malen kann. Erfunden wurde das Element vom Webkit-Team und später sind auch Mozilla und Opera auf den <canvas>
-Zug aufgesprungen. Damit ist das das Element heutzutage in alle anständigen Browser implementiert (für den IE gibt es einen Trick – dazu später mehr) und Teil des werdenden HTML5-Standards.
Die Möglichkeiten von <canvas>
sind relativ weit gefasst. Wann immer man man dynamisch Grafiken erzeugen möchte, kann man das mit <canvas>
machen. Beispiele sind z.B. die bekannte Image-Replace-Technik Typeface.js, die experimentelle Online-IDE Bespin (quasi ein komplettes mit Canvas geschriebenes Programm) und das Javascript-Toolkit MochaUI. Das sind alles relativ mächtige Beispiele, aber man kann auch getrost kleinere Brötchen backen – sofern man nur ein wenig Ahnung von HTML und Javascript hat, kann man mit Canvas schon etwas anstellen. Und genau darum geht es im folgenden.
Wie bindet man das <canvas>
-Element ein?
Sowohl ein öffnender als auch ein schließender Tag werden für <canvas>
gebraucht – zwischen den Tags kann man Fallback-Content notieren, also Inhalt, der ausgegeben wird wenn das <canvas>
-Element selbst nicht angezeigt werden kann. Breite und Höhe sollten als Attribute angegeben werden – wenn man die Maße per CSS festlegt, wird der <canvas>
-Inhalt ausgehend von der Ausgangsgröße entsprechend verzerrt.
<canvas width="100" height="100">
Fallback-Inhalt
</canvas>
Eine ID zu vergeben ist meist auch sinnvoll – man will ja das Element irgendwann mit Javascript beackern können.
Wie arbeitet man mit <canvas>
?
Ein <canvas>
-Element stellt einen oder mehrere sogenannte rendering contexts zur Verfügung, quasi Ebenen auf denen man zeichnen kann. Der im Moment einzige Context ist der 2D-Context – an einem 3D-Context wird aber gearbeitet. Für den Moment vergessen wir also einfach all das und beschränken uns auf den 2D-Context. Um mit <canvas>
erste Schritte zu machen, brauchen wir nur zwei Dinge: ein <canvas>
-Element in einem HTML-Dokument und eine Javascript-Funktion, die auf dem <canvas>
-Element herummalt. Das Canvas-Element könnte so aussehen:
<canvas id="testcanvas1" width="300" height="200">
Dein Browser kann diese Grafik nicht darstellen.
</canvas>
Es enthält Maße, Fallback-Content und eine ID zur Steuerung. Wenn wir jetzt dieses Rechteck mit einer Farbe füllen wollten, bräuchten wir nur 8 Zeilen Javascript:
function drawCanvas(){
var canvas = document.getElementById('testcanvas1');
if(canvas.getContext){
var context = canvas.getContext('2d');
context.fillStyle = "rgb(255, 0, 255)";
context.fillRect(0, 0, canvas.width, canvas.height);
}
}
Zur Erläuterung:
var canvas = document...
holt das<canvas>
-Element anhand seiner IDvar context = canvas.getContext('2d')
holt den 2D-Context in die handlichecontext
-Variable. Das brauchen wir, weil wir letzlich nicht auf dem<canvas>
-Element selbst, sondern auf einem Context des Elements zeichnen.context.fillStyle = "rgb(255, 0, 255)"
setzt die Füllfarbe für alles, was wir im Context hiernach zeichnen werden auf ein schönes, kräftiges Pinkcontext.fillRect(0, 0, canvas.width, canvas.height)
zeichnet ein gefülltes Rechteck, beginnend bei den Koordinaten 0,0 und endend bei der unteren rechten Ecke des<canvas>
-Elements, definiert durch die gesamte Höhe und Breite
Jetzt braucht man nur noch die Funktion drawCanvas()
irgendwie auszuführen (z.B. mittels <body onload="drawCanvas()">
) und schon hat man ein fertiges, funktionierendes Canvas-Beispiel.
Was kann man genau alles mit <canvas>
anstellen?
Natürlich kann man mit <canvas>
einiges mehr anstellen als nur pinke Flächen malen. Die komplette API ist in den offiziellen HTML5-Spezifikationen sehr erschöpfend behandelt. Für eine etwas bekömmlichere Darstellung, die auf zwei A4-Seiten passt und obendrein noch bebildert ist, sei dieser Cheat Sheet aufs allerwärmste empfohlen.
Kurz gesagt kann man Pfade zeichnen, vorhandene Bilder manipulieren, Text scheiben und mehr. Die eingangs erwähnten Beispiele wie Bespin und MochaUI machen deutlich, dass man mit Canvas sehr viel anstellen kann. Man muss es eben nur wollen. Drei weitere (einfache) Beispiele gefällig?
Canvas-Beispiel 1: Ein Bild drehen
Man kann in ein <canvas>
-Element Bilder oder auch den Inhalt anderer <canvas>
-Elemente zeichnen. Das könnte zum Beispiel so aussehen. Im Prinzip ist das das gleiche Spiel wie beim Einführungs-Beispiel:
function drawCanvas(){
var canvas = document.getElementById('testcanvas1');
var img = new Image();
img.onload = function(){
if(canvas.getContext){
var context = canvas.getContext('2d');
context.translate(200, 0);
context.rotate(90 * Math.PI/180);
context.drawImage(img, 0, 0, 200, 200);
}
}
img.src = 'test.png';
}
var img = new Image()
erstellt ein neuesimg
-Element, das als Referenz für unsercanvas
-Element dient.context.translate(200, 0)
positioniert den Punkt, um den der Context rotieren wirdcontext.rotate(90 * Math.PI/180)
macht eine 90°-Drehungcontext.drawImage(img, 0, 0)
zeichnet das Bildimg
ausgehend von den Koordinaten 0,0.
Weil in diesem Beispiel der gesamte Context und nicht das Bild rotiert wird, kann man die Funktion drawCanvas()
immer wieder aufrufen um das Ganze in 90°-Schritten immer weiter zu drehen.
Beispiel 2: Eine kleine Animation
Animieren ist einfach: man zeichnet einfach Frame für Frame das <canvas>
-Element neu. So kann man zum Beispiel ein paar halbtransparente Quadrate durch die Gegend segeln lassen. Man nehme einfach wieder eine drawCanvas()
-Funktion …
function drawCanvas(){
var canvas = document.getElementById('testcanvas1');
if(canvas.getContext){
var context = canvas.getContext('2d');
animate(context, 31, 69, 1, -1, 8, 25, 1, 1);
}
}
… und eine mit einem Timer versehene animate()
-Funktion, die nichts weiter macht, als anhand eines Haufens von Koordinaten Frame für Frame alle neu zu zeichnen.
function animate(context, ax, ay, adx, ady, bx, by, bdx, bdy){
setTimeout(function(){
//Bewegen und Abprallen für Quadrat A
if(ax == 150){
adx = -1;
}
else{
if(ax == 0){
adx = 1;
}
}
if(ay == 150){
ady = -1;
}
else{
if(ay == 0){
ady = 1;
}
}
ax = ax+adx;
ay = ay+ady;
//Bewegen und Abprallen für Quadrat B
if(bx == 150){
bdx = -1;
}
else{
if(bx == 0){
bdx = 1;
}
}
if(by == 150){
bdy = -1;
}
else{
if(by == 0){
bdy = 1;
}
}
bx = bx+bdx;
by = by+bdy;
// Alles neu zeichnen
context.clearRect(0, 0, 200, 200);
context.fillStyle = "rgba(0, 0, 255, 0.5)";
context.fillRect(ax, ay, 50, 50);
context.fillStyle = "rgba(0, 255, 0, 0.5)";
context.fillRect(bx, by, 50, 50);
self.animate(context, ax, ay, adx, ady, bx, by, bdx, bdy);
}, 0);
}
Einfach bei jedem Frame mit context.clearRect(0, 0, 200, 200)
die Canvas putzen und die Quadrate an ihren neuen Koordinaten zeichnen.
Beispiel 3: Paint
Richtig Interessant wird <canvas>
erst, wenn man den Benutzer richtig mitmachen lässt. So ist zum Beispiel ein (sehr sehr rudimentäres) Malprogramm recht einfach machbar. Man nehme bei Mausbewegung die Koordinaten …
var x, y;
canvas.onmousemove = function(e){
x = e.clientX-canvas.offsetLeft;
y = e.clientY-canvas.offsetTop;
kx.innerHTML = x;
ky.innerHTML = y;
paint();
}
… und male, falls die Maustaste gedrückt ist, einfach an der Mausposition eine Fläche:
var active = false;
canvas.onmousedown = function(){ active = true; }
canvas.onmouseup = function(){ active = false; }
function paint(){
if(active){
context.fillRect(x, y, 10, 10);
}
}
Ist wie gesagt sehr rudimentär, aber es ein Beispiel dafür, wie man <canvas>
interaktiv ensetzen kann.
Und was machen wir mit dem Internet Explorer?
Dass keine einzige Version des Internet Explorer mit <canvas>
etwas anfangen kann, ist nicht überraschend, wenn auch ärgerlich. Glücklicherweise gibt es ExplorerCanvas. Das ist ein Script, dass versucht, <canvas>
mit diversen proprietären IE-Technologien wie z.B. VML nachzubilden.
Die Verwendung von ExplorerCanvas ist denkbar simpel: Einfach das Script einbinden und weitermachen wie bisher.
<!--[if IE]>
<script type="text/javascript" src="excanvas.js"></script>
<![endif]-->
Einige <canvas>
-Features wie radialGradient funktionieren nicht oder leicht anders als im Original, aber das ist eben der Internet Explorer. Was will man machen?
Kommentare (12)
Gerrit van Aaken ¶
16. März 2009, 12:06 Uhr
Super-Sache! Vielleicht könntest Du noch eine Liste mit Canvas-Frameworks machen, die einem beispielsweise das manuelle Tippen der Animations-Schritte abnehmen ... Gibt’s da schon was? Ich meine mich erinnern zu können!
Peter ¶
16. März 2009, 12:41 Uhr
Da gibt es sogar sehr viel. Es gibt 3D-Engines, Physikengines, Bildbearbeitungs-Frameworks … wie gesagt, es gibt viel und vor allem viel sehr spezialisiertes. Das Problem ist für mich jetzt nur, dass ich weder einen Überblick über all das habe, noch von so Sachen wie z.B. 3D-Engines besonders viel verstehe.
Am ehesten denke ich wird man mit der Canvas-Kategorie von Ajaxian glücklich, da gibt es viel Material und das ist meist auch fachmännisch kommentiert.
Nico ¶
16. März 2009, 14:00 Uhr
Super Danke! Hab mich schon lange gefragt was man damit eigentlich so machen kann, aber wenn ich das jetzt Richtig Verstanden habe ist es mehr eine Sache zum Programmieren als zum Designen oder nicht ?
Peter ¶
16. März 2009, 14:36 Uhr
Es kommt drauf an, was du damit anstellen möchtest. Du kannst mit Canvas ein interaktives Programm wie mein Paint-Beispiel bauen, aber zum Beispiel auch einfach eine Grafik animieren. Stell dir vor, du willst etwas drehen lassen, das kriegst du mit Canvas einfacher, kleiner und vermutlich auch schöner hin als mit einem GIF.
Martin Labuschin ¶
16. März 2009, 15:18 Uhr
Cool! Vielen Danke für diese Erläuterung. Hätte sonst nie gewusst, wozu dieses Element gut ist :)
Andreas ¶
16. März 2009, 18:52 Uhr
Diese These ist mit Sicherheit ein bisschen weit hergeholt, die Bespiele zeigen aber, was mit Canvas alles möglich ist...
Micha ¶
23. April 2009, 08:35 Uhr
Hallo,
etwas Schade ist, das man keinen text direkt hinzufügen kann. Ich habe bei meinem Fußballmanager damals ein in JavaScript hinterlegtes Bild genommen - siehe Fieberkurve.
Sollte es hier bereits bessere Lösungen geben, würden mich diese mal interessieren.
Peter ¶
23. April 2009, 08:43 Uhr
Zitat Micha:
Fortschrittliche Browser wie die aktuellen Betas von Safari und Firefox unterstützten Textfunktionen von Haus aus (siehe z.B. hier) und für alle anderen gibt es dieses Script.
reizi ¶
14. November 2009, 22:23 Uhr
Nicht schlecht!!! Über den Weg gelaufen ist mir Canvas auch schon, aber ich wußte bis jetzt auch nicht, was man damit alles anstellen kann. Danke dafür! Das mit dem Beispiel des einfachen Paint ist ja echt mal genial! Wäre optimal für eine Seite, wo der User irgendeine Skizze zeichnen, oder seine Unterschrift geben muß, sofern man es irgendwie speichern kann. Bin mal gespannt, was da in Zukunft noch auf uns zukommen wird.
grüße
reizi
Gromobir ¶
13. August 2012, 21:19 Uhr
Hallo Peter!
Auch Jahre später sind die Infos immer noch nützlich. Danke! :-)
Alf ¶
23. August 2012, 13:14 Uhr
Hallo Peter
Netter Beitrag - auch in Zeiten von HTML5
LG
Alf
Fredi ¶
24. September 2013, 00:18 Uhr
Bin auch ein Fan von Canvas als Alternative zu Flash. Wer ein Apple Gerät hat, weiß warum...