So wird's gemacht: Zeichnen auf einer HTML5-Canvas

Eine Canvas ist eine Zeichenoberfläche zum Rendern und Animieren von grafischen Elementen wie etwa von rechteckigen Bereichen oder Bitmap-Bildern. Diese Elemente werden mithilfe einer Skriptsprache, meist JavaScript, bearbeitet.

Anweisungen

Schritt 1: Einrichten einer Canvas im HTML-Code, Erstellen eines Verweises und Abrufen des Kontextobjekts

Eine Canvas wird in HTML durch das <canvas>-Tag definiert. Wie bei anderen Tags werden Eigenschaften für <canvas> wie Breite und Höhe als Attribute eingegeben. Angenommen, Sie möchten eine Canvas mit einer Breite von 500 Pixel und einer Höhe von 500 Pixel erstellen und ihr den Namen "can1" geben, den Sie später in JavaScript verwenden, um auf die Canvas zu verweisen.

  1. Geben Sie das <canvas>-Tag in Ihr HTML-Dokument ein.

    <canvas id="can1" width="500" height="500"></canvas>

  2. In Ihrem JavaScript-Dokument erstellen Sie eine Variable, die beim Schreiben des Skripts für "can1" steht. In diesem Beispiel geben wir dieser Variablen den Namen "myCanvas" und verknüpfen sie mithilfe von getElementById mit "can1".

    var myCanvas = document.getElementById("can1");

  3. Das CanvasRenderingContext2D-Objekt für eine Canvas verfügt über alle Befehle zum Bearbeiten der Canvas. In diesem Beispiel rufen wir das Kontextobjekt für "can1" ab. Wir geben der Variablen den Namen "myContext".

    var myContext = myCanvas.getContext("2d");

Schritt 2: Zeichnen von Rechtecken, geraden Linien, Bézierkurven, Kreisen und Formen

Eine einfache Linie in einer Canvas zu zeichnen, ist einfach. Legen Sie mithilfe der moveTo-Methode von JavaScript die Koordinaten für den Linienanfang fest. Danach verwenden Sie nur noch eine weitere Methode, um den Endpunkt festzulegen. Für den zweiten Schritt haben Sie verschiedene Methoden zur Auswahl, wobei sie von jeder beim Rendern einer anderen Linienart unterstützt werden, je nachdem, ob es sich um eine gerade Linie, eine Bézierkurve oder einen Bogen handelt. Wenn Sie Linien zu einer Form kombinieren möchten, schließen Sie die Linien in Aufrufe der Methoden beginPath und closePath ein. Nachdem Sie festgelegt haben, was Sie sehen möchten, wenden Sie mit der fill-Methode Farben an und rendern die Linien und Formen mit der stroke-Methode.

  1. Wenden Sie nun einige einfache Stile an. In diesem Beispiel gestalten Sie den Hintergrund der Canvas schwarz (#000). Hierzu verwenden Sie die fillStyle-Eigenschaft, um ein schwarzes Rechteck zu zeichnen. Anschließend legen Sie die Linienfarbe mithilfe der strokeStyle-Eigenschaft auf weiß (#fff) fest, wenden die schwarze Hintergrundfarbe mit der fillRect-Methode an und legen die Linienstärke mit der lineWidth-Eigenschaft auf 3 Pixel fest.

    // Specify a black background, and white lines that are 3 pixels thick.
    myContext.fillStyle   = '#000';
    myContext.strokeStyle = '#fff';
    myContext.fillRect(0,0,500,500);
    myContext.lineWidth  = 3;
    myContext.fill();
    

    Mit den folgenden Schritten fahren Sie mit dem Erstellen dieser schwarzen 500 × 500-Canvas fort.

  2. Nun können Sie eine weiße Linie auf die schwarze Oberfläche der Canvas zeichnen. Beginnen Sie mit einer geraden Linie. Legen Sie den Anfang der Linie mithilfe der moveTo-Methode und den Endpunkt mithilfe der lineTo-Methode fest. Diese Methoden nehmen zwei Zahlen als Parameter an. Die erste Zahl stellt die X-Koordinate bzw. die durch diese Koordinate definierte Anzahl Pixel von der linken Seite der Canvas dar. Die zweite Zahl entspricht der Y-Koordinate, die von oben gemessen wird.

    // Draw a line that starts at the upper left corner of the canvas and ends at the lower right. 
    myContext.moveTo(0,0);
    myContext.lineTo(500,500);
    myContext.stroke();
    
  3. Wenn Sie eine quadratische Bézierkurve zeichnen möchten, verwenden Sie die quadraticCurveTo-Methode, die zwei Koordinaten annimmt — einen Kontrollpunkt und einen Endpunkt für die Kurve.

    // Draw a swooping curve that spans the width of the canvas.
    myContext.moveTo(0,0);
    myContext.quadraticCurveTo(0,500,500,250);
    myContext.stroke();
    
  4. Wenn Sie eine kubische Bézierkurve zeichnen möchten, verwenden Sie die bezierCurveTo-Methode, die drei Koordinaten annimmt — einen Kontrollpunkt und einen Endpunkt für die Kurve.

    // Draw a V-shaped Bezier curve that spans the entire canvas.
    myContext.moveTo(0,0);
    myContext.bezierCurveTo(500, 820, 0, 500, 500, 0);
    myContext.stroke();
    
  5. Wenn Sie einen Kreis erstellen möchten, verwenden Sie die arc-Methode. Legen Sie beim Festlegen des Anfangspunkts zum Zeichnen der Kreiskontur die moveTo-Methode auf eine Position fest, die sich auf dem Pfad der Linie befindet. Andernfalls führt ein "Schwanz" am Kreis zu Ihrer moveTo-Koordinate.

    // Draw a circle that spans the width of the canvas.
    myContext.moveTo(500,250);
    myContext.arc(250,250,250,0,Math.PI*2,true);
    myContext.stroke();
    
  6. Sie können aus einer beliebigen Kombination aus den oben beschriebenen Linien eine 2D-Form erstellen, indem Sie mehrere Linien in Aufrufe von beginPath und closePath einschließen. Anschließend können Sie dieser gesamten Form mithilfe von fill eine Farbe zuweisen. Mit dem weiter oben festgelegten Strichstil werden weiße Linien erstellt. Und wenn diese mit der roten Farbe (#f00) kombiniert werden, die auf den Körper angewendet wird, erbt die Form eine Zweitondarstellung.

    //  Draw a red diamond that spans the entire canvas.
    myContext.fillStyle = '#f00';
    myContext.beginPath();
    myContext.moveTo(250,0);
    myContext.lineTo(0,250);
    myContext.lineTo(250,500);
    myContext.lineTo(500,250);
    myContext.closePath();
    myContext.fill();
    

Schritt 3: Anzeigen von Bitmap-Bildern

Bitmap-Bilder wie JPG-, PNG- und GIF-Dateien können in eine Canvas eingefügt und im Code sogar skaliert und zugeschnitten werden, ohne die Originaldatei anrühren zu müssen. Wenn Sie ein Bitmap-Bild hinzufügen möchten, geben Sie die URI für das Bild an, und legen Sie anschließend mithilfe der drawImage-Methode die Position in der Canvas fest. Mithilfe von optionalen Parametern können Sie das Bild auf die gewünschte Größe skalieren oder auch nur ein Segment des Bilds anzeigen. Das ist besonders hilfreich, wenn Sie Hintergründe mit Bildlauf implementieren oder Sprites mit einer Sprite-Vorlage animieren möchten.

  1. Wenn Sie ein Bitmap-Bild ohne Änderungen auf dem Bildschirm zeichnen möchten, geben Sie die X-Koordinate und die Y-Koordinate an, die Sie für die obere linke Ecke verwenden möchten.

    // Draw an image at the upper left corner of the canvas (0, 0).
    var myImg = new Image();
    myImg.src = 'myImageFile.png';
    myContext.drawImage(myImg, 0, 0)
    
  2. Fügen Sie am Ende zwei Zahlen hinzu, die die Höhe bzw. Breite angeben, um das Bild zu skalieren. Falls es Ihnen hilft, können Sie sich die zweiten zwei Zahlen statt als "Breite" und "Höhe" als "rechts" und "unten" vorstellen.

    // Scale the image to span the entire 500 x 500 canvas.
    var myImg = new Image();
    myImg.src = 'myImageFile.png';
    myContext.drawImage(myImg, 0, 0, 500, 500)
    
  3. Wenn Sie nur ein Segment des Bilds verwenden möchten, müssen Sie zwei rechteckige Bereiche definieren, sodass Ihr Aufruf von drawImage bis zu 9 Parameter enthalten kann (wobei der erste Parameter das JavaScript-Bildobjekt darstellt). Die ersten vier Zahlen, die Sie übergeben, stellen das Bildsegment dar. Die nächsten vier Zahlen stellen den Bereich der Canvas dar, in dem dieses Segment angezeigt wird.

    // Take a 20 x 20 slice from the upper left of the image and scale it to span the entire 500 x 500 canvas.
    var myImg = new Image();
    myImg.src = 'myImageFile.png';
    myContext.drawImage(myImg, 0, 0, 20, 20, 0, 0, 500, 500);
    

Schritt 4: Farbverläufe

Diejenigen, die wissen, wie Farbverläufe in Grafikdesignprogrammen normalerweise definiert werden, werden begeistert sein, wie einfach die Definition mit JavaScript-Code ist. Bei Designprogrammen wird die Farbe ausgewählt und mithilfe eines horizontalen Schiebereglers wird die Position der Farbe im Farbverlauf festgelegt. Die Definition in JavaScript unterscheidet sich insofern, als dass anstelle des Schiebereglers ein Dezimalwert zwischen 0 und 1 verwendet wird.

  1. Bei Designprogrammen wird ein linearer Farbverlauf mithilfe einer Linie in ein Bild eingefügt, deren Anfangs- und Endpunkt die Richtung und das Maß der Neigung angeben. Bei JavaScript wird diese Linie mithilfe von zwei Paaren von X-Y-Koordinaten gezeichnet. Diese 4 Zahlen werden an die createLinearGradient-Methode übergeben, um ein CanvasGradient-Objekt zu erstellen. Nachdem die Eigenschaften des Farbverlaufobjekts für den gewünschten Farbverlauf definiert wurden, wird das CanvasGradient-Objekt als fillStyle an die fillRect-Methode zum Rendern übergeben.

    // Render a white, red and black gradient diagonally across the canvas.
    var myGradient = myContext.createLinearGradient(0,0, 500,500); // gradient starts at upper left and ends at lower right
    myGradient.addColorStop(0,"#fff");                             // white at the beginning of the gradient
    myGradient.addColorStop(0.5,"#f00");                           // red in the middle of the gradient
    myGradient.addColorStop(1,"#000");                             // black at the end of the gradient
    myContext.fillStyle = myGradient;                              // ensure the next call to fillRect will use the specified gradient
    myContext.fillRect(0,0,500,500);                               // rectangle that contains the gradient spans the entire canvas
    
  2. Radiale Farbverläufe werden auf etwas andere Weise definiert. Für den Anfang und das Ende des Farbverlaufs werden zwei Paare von X-Y-Koordinaten gezeichnet — so, wie bei einem linearen Farbverlauf — wobei beim radialen Farbverlauf jedem Koordinatenpaar eine dritte Koordinate, nämlich die Z-Koordinate, zugeordnet ist, die den Radius definiert. Stellen Sie sich vor, dass ein Kreis um eine Koordinate gezeichnet wird, die sich im Mittelpunkt (250, 250) befindet, und die Größe des Kreises in Pixel angegeben ist. Nach der Definition von zwei Kreisen (einem kleineren und einem mit der Größe der Canvas) auf diese Weise werden 6 Zahlen an createRadialGradient übergeben. Beim Rendern wird der radiale Farbverlauf in den Bereich zwischen den beiden Kreisen gezeichnet und die Farben verlaufen proportional zur Größe der Kreisradien.

    // Render a white, red and black radial gradient spanning the canvas.
    var myGradient = myContext.createRadialGradient(250,250,0, 250,250,500); // gradient is centered and spans the entire canvas 
    myGradient.addColorStop(0,"#fff");                                       // white at the beginning of the gradient
    myGradient.addColorStop(0.5,"#f00");                                     // red in the middle of the gradient
    myGradient.addColorStop(1,"#000");                                       // black at the end of the gradient
    myContext.fillStyle = myGradient;                                        // ensure the next call to fillRect will use the specified gradient
    myContext.fillRect(0,0,500,500);                                         // rectangle that contains the gradient spans the entire canvas
    

Schritt 5: Animation

Bei der Animation gibt es einige Aspekte zu beachten.

  1. Für Elemente innerhalb der Canvas stellt JavaScript die setInterval-Methode bereit, mit deren Hilfe festgelegt werden kann, dass eine Funktion immer dann aufgerufen werden soll, wenn das definierte Zeitintervall abgelaufen ist. Mit dieser Funktion wird die Canvas unter Berücksichtigung der Änderungen an den Objekten neu gezeichnet. Im Folgenden sehen Sie ein Beispiel, bei dem die Animation von einer Funktion initialisiert wird, mit der für das Rendering eine Rate von etwa 60 Frames pro Sekunde (alle 13,33 Millisekunden) festgelegt wird, und bei dem die Canvas von der aufgerufenen Funktion wiederholt neu gezeichnet wird. In diesem Beispiel wird ein radialer Farbverlauf immer größer. Er beginnt als kleiner Punkt und füllt zum Schluss die gesamte Canvas.

    // Generate an animation of a growing gradient.
    
    // These variables must exist globally so both functions can access them.
    var myCanvas; 
    var myContext;
    var outerBoundary = 0, innerBoundary = 0;
    
    // Start the animation.
    window.onload = initialize;
    function initialize() {
        myCanvas = document.getElementById("can1");
        myContext = myCanvas.getContext("2d");
        setInterval("redrawCanvas()",13);    // redraw @ approximately 60 frames per second
    }                                        
    
    // Run the animation.                   
    function redrawCanvas() {              
        if (outerBoundary < 500) {            
            outerBoundary++;             // grow the size of the gradient
        } else {                             
            innerBoundary++;             // grow the size of the inner white circle if red is maxed
        }                                    
        var myGradient = myContext.createRadialGradient(250,250,innerBoundary, 250,250,outerBoundary);
        myGradient.addColorStop(0,"#fff");   // white at the beginning of the gradient
        myGradient.addColorStop(0.5,"#f00"); // red in the middle of the gradient
        myGradient.addColorStop(1,"#000");   // black at the end of the gradient
        myContext.fillStyle = myGradient;    // ensure the next call to fillRect will use the specified gradient
        myContext.fillRect(0,0,500,500);     // rectangle that contains the gradient spans the entire canvas
    }
    
  2. CSS3-Übergänge und -Animationen können verwendet werden, um die Canvas selbst oder Objekte außerhalb der Canvas zu transformieren.

  3. Zudem enthält die neue WinJS-Bibliothek jede Menge optimierte Animationen, die erstellt wurden, um das Verhalten von bereits vorhandenen Windows-Animationen zu emulieren. Durch die WinJS-Animationen erhält die Benutzeroberfläche Ihrer App ein ganzheitliches Erscheinungsbild. Weitere Informationen finden Sie im Thema zum "WinJS.UI.Animation"-Namespace.

Schritt 6: Weitere Hinweise zur HTML5-Canvas

  1. Mithilfe der folgenden Eigenschaften können Sie Schlagschatten hinzufügen: shadowColor, shadowBlur, shadowOffsetX und shadowOffsetY.

  2. Elemente innerhalb einer Canvas können mithilfe der createPattern-Methode in Form eines Musters wiederholt werden.

  3. Mit der save-Methode können Sie den Zustand der Canvas speichern, dann Änderungen vornehmen und anschließend mit der restore-Methode den vorherigen Zustand wiederherstellen. Das funktioniert ganz einfach, und für die Funktionen sind noch nicht einmal Argumente erforderlich.

  4. Was geschehen soll, wenn sich zwei Canvas-Elemente überschneiden, kann mithilfe der globalCompositeOperation-Eigenschaft definiert werden. Bei dieser Eigenschaft definieren Sie immer, was geschieht, an der Quelle oder auf der Ebene des neuen Elements. Dies ermöglicht es Ihnen unter anderem, Farben zu vermischen, zu maskieren und die Priorität für Überlappungen zu ändern.

    Hinweis  Im Thema zu globalCompositeOperation wird Quelle im Sinne von "neues Element" und Ziel im Sinne von "bereits vorhandenes Element" verwendet.

  5. Text können Sie einer Canvas mithilfe der strokeText-Methode hinzufügen.