Eine kleine Canvas-Einführung

Achtung: dieser Beitrag ist alt! Es kann gut sein, dass seine Inhalte nicht mehr aktuell sind.

Zum Thema HTML5 gibt es auch ein ganzes Buch von mir, das alle Aspekte rund um HTML5 bespricht, die Browserunterstützung unter die Lupe nimmt und einen Anhang mit vielen Tabellen und Referenzen bietet. Mehr Infos gibt es auf der Webseite zum Buch.

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 ID
  • var context = canvas.getContext('2d') holt den 2D-Context in die handliche context-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 Pink
  • context.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.

Ein einfaches 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 neues img-Element, das als Referenz für unser canvas-Element dient.
  • context.translate(200, 0) positioniert den Punkt, um den der Context rotieren wird
  • context.rotate(90 * Math.PI/180) macht eine 90°-Drehung
  • context.drawImage(img, 0, 0) zeichnet das Bild img 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.

Ein Bild mit Canvas 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.

Eine einfache Animation mit Canvas

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);
    }
}
Ein einfaches Malprogramm mit Canvas

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?

Links zum Thema

Kommentare (12)

  1. 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!

  2. 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.

  3. 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 ?

  4. 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.

  5. 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 :)

  6. 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...

  7. 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.

  8. Peter

    23. April 2009, 08:43 Uhr

    Zitat Micha:

    Sollte es hier bereits bessere Lösungen geben, würden mich diese mal interessieren.

    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.

  9. 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

  10. Gromobir

    13. August 2012, 21:19 Uhr

    Hallo Peter!
    Auch Jahre später sind die Infos immer noch nützlich. Danke! :-)

  11. Alf

    23. August 2012, 13:14 Uhr

    Hallo Peter

    Netter Beitrag - auch in Zeiten von HTML5

    LG
    Alf

  12. 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...

Die Kommentarfunktion ist seit Juli 2014 deaktiviert, weil sie zu sehr von Suchmaschinenoptimierern für manuellen Spam mißbraucht wurde. Wenn du Anmerkungen oder Fragen zum Artikel hast, schreib mir eine E-Mail oder melde dich via Twitter.

Folgt mir!

Kauft mein Zeug!

Cover der HTML5-DVD
Infos auf html5-dvd.de, kaufen bei Amazon

Cover des HTML5-Buchs
Infos auf html5-buch.de, kaufen bei Amazon

Cover des CSS3-Buchs
Infos auf css3-buch.de, kaufen bei Amazon