From 4ab365b110f2f1f2b736326b7059244a32115089 Mon Sep 17 00:00:00 2001 From: Florian Merz Date: Thu, 11 Feb 2021 14:45:38 +0100 Subject: unslug de: move --- .../tutorial/basic_animations/index.html | 307 +++++++++++++++++++++ 1 file changed, 307 insertions(+) create mode 100644 files/de/web/api/canvas_api/tutorial/basic_animations/index.html (limited to 'files/de/web/api/canvas_api/tutorial/basic_animations') diff --git a/files/de/web/api/canvas_api/tutorial/basic_animations/index.html b/files/de/web/api/canvas_api/tutorial/basic_animations/index.html new file mode 100644 index 0000000000..78ca0ac2fc --- /dev/null +++ b/files/de/web/api/canvas_api/tutorial/basic_animations/index.html @@ -0,0 +1,307 @@ +--- +title: Einfache Animationen +slug: Web/Guide/HTML/Canvas_Tutorial/Basic_animations +translation_of: Web/API/Canvas_API/Tutorial/Basic_animations +--- +
{{CanvasSidebar}} {{PreviousNext("Web/API/Canvas_API/Tutorial/Compositing", "Web/API/Canvas_API/Tutorial/Advanced_animations")}}
+ +
+

Seitdem wir JavaScript benutzen, um {{HTMLElement("canvas")}}-Elemente zu steuern, ist es auch sehr einfach, interaktive Animationen zu erzeugen. In diesem Kapitel werden wir uns ein paar einfachen Animationen widmen.

+
+ +

Die wahrscheinlich größte Einschränkung ist, dass jede Form, die einmal gezeichnet wird, genauso bleibt wie anfänglich. Wenn wir sie bewegen wollen, müssen wir sie neuzeichnen. Aber: Auch alle anderen Formen, die wir davor schon gezeichnet haben, müssen auch neu gezeichnet werden! Es beansprucht leider einiges an Zeit, komplexe Figuren neu zu zeichnen.

+ +

Grundlagen der Animation

+ +

Diese Schritte müssen Sie befolgen, um ein neues Frame zu zeichnen:

+ +
    +
  1. Bereinigen Sie die Zeichenfläche (canvas)
    + Sofern die Form, die Sie zeichnen wollen, nicht den gesamten Platz der Zeichenfläche einnimmt, müssen Sie alle vorherigen Formen entfernen. Am einfachsten erreichen Sie dies über die {{domxref("CanvasRenderingContext2D.clearRect", "clearRect()")}}-Methode.
  2. +
  3. Sichern Sie den Canvas-Zustand
    + Wenn Sie irgendeine Einstellung verändern (wie das Layout, Transformtationen, etc.), die den Status der Zeichenfläche beeinflussen, sollten Sie den Ursprungszustand sichern. Nur so gewährleisten Sie, dass der Ursprungszustand für jedes neue Frame verwendet wird. Verwenden Sie hierfür die save()-Methode.
  4. +
  5. Zeichnen Sie die animierte Form
    + Hier erzeugen Sie nun endlich die eigentliche Animation.
  6. +
  7. Setzen Sie den Canvas-Zustand zurück.
    + Mit der restore()-Methode können Sie auf den Ursprungszustand zurückwechseln, um ein neues Frame zu erzeugen.
  8. +
+ +

Steuerung einer Animation

+ +

Formen werden auf eine Zeichenfläche appliziert, indem die entsprechende Canvas-Methode verwendet wird oder eine vorher erzeugte Funktion aufgerufen wird. Im Normalfall erscheint die Canvas-Zeichnung erst, nachdem das Skript vollständig ausgeführt wurde. So ist es nicht möglich, eine Animation durch eine for-Schleife zu erzeugen.

+ +

Das bedeutet nun, dass wir einen Weg finden müssen, die Zeichenfunktion für eine bestimmte Zeitdauer ausführen zu können. Dafür gibt es nun zwei Wege, um eine Animation so zu steuern:

+ +

Updates nach Zeitplan

+ +

Einerseits gibt es die {{domxref("window.setInterval()")}}-, {{domxref("window.setTimeout()")}}- und {{domxref("window.requestAnimationFrame()")}}-Funktionen, die benutzt werden, um eine bestimmte Funktion nach einer Zeitspanne aufzurufen.

+ +
+
{{domxref("WindowTimers.setInterval", "setInterval(function, delay)")}}
+
Ruft die unter function spezifierte Funktion wiederholend nach der in delay (Milisekunden) definierten Zeitspanne auf.
+
{{domxref("WindowTimers.setTimeout", "setTimeout(function, delay)")}}
+
Ruft die spezifizierte Funktion nach der unter delay festgelegten Zeitspanne einmalig auf.
+
{{domxref("Window.requestAnimationFrame()", "requestAnimationFrame(callback)")}}
+
Tells the browser that you wish to perform an animation and requests that the browser call a specified function to update an animation before the next repaint.
+
+ +

If you don't want any user interaction you can use the setInterval() function which repeatedly executes the supplied code. If we wanted to make a game, we could use keyboard or mouse events to control the animation and use setTimeout(). By setting {{domxref("EventListener")}}s, we catch any user interaction and execute our animation functions.

+ +
+

In the examples below, we'll use the {{domxref("window.requestAnimationFrame()")}} method to control the animation. The requestAnimationFrame method provides a smoother and more efficient way for animating by calling the animation frame when the system is ready to paint the frame. The number of callbacks is usually 60 times per second and may be reduced to a lower rate when running in background tabs. For more information about the animation loop, especially for games, see the article Anatomy of a video game in our Game development zone.

+
+ +

An animated solar system

+ +

This example animates a small model of our solar system.

+ +
var sun = new Image();
+var moon = new Image();
+var earth = new Image();
+function init() {
+  sun.src = 'https://mdn.mozillademos.org/files/1456/Canvas_sun.png';
+  moon.src = 'https://mdn.mozillademos.org/files/1443/Canvas_moon.png';
+  earth.src = 'https://mdn.mozillademos.org/files/1429/Canvas_earth.png';
+  window.requestAnimationFrame(draw);
+}
+
+function draw() {
+  var ctx = document.getElementById('canvas').getContext('2d');
+
+  ctx.globalCompositeOperation = 'destination-over';
+  ctx.clearRect(0, 0, 300, 300); // clear canvas
+
+  ctx.fillStyle = 'rgba(0, 0, 0, 0.4)';
+  ctx.strokeStyle = 'rgba(0, 153, 255, 0.4)';
+  ctx.save();
+  ctx.translate(150, 150);
+
+  // Earth
+  var time = new Date();
+  ctx.rotate(((2 * Math.PI) / 60) * time.getSeconds() + ((2 * Math.PI) / 60000) * time.getMilliseconds());
+  ctx.translate(105, 0);
+  ctx.fillRect(0, -12, 50, 24); // Shadow
+  ctx.drawImage(earth, -12, -12);
+
+  // Moon
+  ctx.save();
+  ctx.rotate(((2 * Math.PI) / 6) * time.getSeconds() + ((2 * Math.PI) / 6000) * time.getMilliseconds());
+  ctx.translate(0, 28.5);
+  ctx.drawImage(moon, -3.5, -3.5);
+  ctx.restore();
+
+  ctx.restore();
+
+  ctx.beginPath();
+  ctx.arc(150, 150, 105, 0, Math.PI * 2, false); // Earth orbit
+  ctx.stroke();
+
+  ctx.drawImage(sun, 0, 0, 300, 300);
+
+  window.requestAnimationFrame(draw);
+}
+
+init();
+
+ + + +

{{EmbedLiveSample("An_animated_solar_system", "310", "310", "https://mdn.mozillademos.org/files/202/Canvas_animation1.png")}}

+ +

An animated clock

+ +

This example draws an animated clock, showing your current time.

+ +
function clock() {
+  var now = new Date();
+  var ctx = document.getElementById('canvas').getContext('2d');
+  ctx.save();
+  ctx.clearRect(0, 0, 150, 150);
+  ctx.translate(75, 75);
+  ctx.scale(0.4, 0.4);
+  ctx.rotate(-Math.PI / 2);
+  ctx.strokeStyle = 'black';
+  ctx.fillStyle = 'white';
+  ctx.lineWidth = 8;
+  ctx.lineCap = 'round';
+
+  // Hour marks
+  ctx.save();
+  for (var i = 0; i < 12; i++) {
+    ctx.beginPath();
+    ctx.rotate(Math.PI / 6);
+    ctx.moveTo(100, 0);
+    ctx.lineTo(120, 0);
+    ctx.stroke();
+  }
+  ctx.restore();
+
+  // Minute marks
+  ctx.save();
+  ctx.lineWidth = 5;
+  for (i = 0; i < 60; i++) {
+    if (i % 5!= 0) {
+      ctx.beginPath();
+      ctx.moveTo(117, 0);
+      ctx.lineTo(120, 0);
+      ctx.stroke();
+    }
+    ctx.rotate(Math.PI / 30);
+  }
+  ctx.restore();
+
+  var sec = now.getSeconds();
+  var min = now.getMinutes();
+  var hr  = now.getHours();
+  hr = hr >= 12 ? hr - 12 : hr;
+
+  ctx.fillStyle = 'black';
+
+  // write Hours
+  ctx.save();
+  ctx.rotate(hr * (Math.PI / 6) + (Math.PI / 360) * min + (Math.PI / 21600) *sec);
+  ctx.lineWidth = 14;
+  ctx.beginPath();
+  ctx.moveTo(-20, 0);
+  ctx.lineTo(80, 0);
+  ctx.stroke();
+  ctx.restore();
+
+  // write Minutes
+  ctx.save();
+  ctx.rotate((Math.PI / 30) * min + (Math.PI / 1800) * sec);
+  ctx.lineWidth = 10;
+  ctx.beginPath();
+  ctx.moveTo(-28, 0);
+  ctx.lineTo(112, 0);
+  ctx.stroke();
+  ctx.restore();
+
+  // Write seconds
+  ctx.save();
+  ctx.rotate(sec * Math.PI / 30);
+  ctx.strokeStyle = '#D40000';
+  ctx.fillStyle = '#D40000';
+  ctx.lineWidth = 6;
+  ctx.beginPath();
+  ctx.moveTo(-30, 0);
+  ctx.lineTo(83, 0);
+  ctx.stroke();
+  ctx.beginPath();
+  ctx.arc(0, 0, 10, 0, Math.PI * 2, true);
+  ctx.fill();
+  ctx.beginPath();
+  ctx.arc(95, 0, 10, 0, Math.PI * 2, true);
+  ctx.stroke();
+  ctx.fillStyle = 'rgba(0, 0, 0, 0)';
+  ctx.arc(0, 0, 3, 0, Math.PI * 2, true);
+  ctx.fill();
+  ctx.restore();
+
+  ctx.beginPath();
+  ctx.lineWidth = 14;
+  ctx.strokeStyle = '#325FA2';
+  ctx.arc(0, 0, 142, 0, Math.PI * 2, true);
+  ctx.stroke();
+
+  ctx.restore();
+
+  window.requestAnimationFrame(clock);
+}
+
+window.requestAnimationFrame(clock);
+ + + +

{{EmbedLiveSample("An_animated_clock", "180", "180", "https://mdn.mozillademos.org/files/203/Canvas_animation2.png")}}

+ +

A looping panorama

+ +

In this example, a panorama is scrolled left-to-right. We're using an image of Yosemite National Park we took from Wikipedia, but you could use any image that's larger than the canvas.

+ +
var img = new Image();
+
+// User Variables - customize these to change the image being scrolled, its
+// direction, and the speed.
+
+img.src = 'https://mdn.mozillademos.org/files/4553/Capitan_Meadows,_Yosemite_National_Park.jpg';
+var CanvasXSize = 800;
+var CanvasYSize = 200;
+var speed = 30; // lower is faster
+var scale = 1.05;
+var y = -4.5; // vertical offset
+
+// Main program
+
+var dx = 0.75;
+var imgW;
+var imgH;
+var x = 0;
+var clearX;
+var clearY;
+var ctx;
+
+img.onload = function() {
+    imgW = img.width * scale;
+    imgH = img.height * scale;
+
+    if (imgW > CanvasXSize) { x = CanvasXSize - imgW; } // image larger than canvas
+    if (imgW > CanvasXSize) { clearX = imgW; } // image width larger than canvas
+    else { clearX = CanvasXSize; }
+    if (imgH > CanvasYSize) { clearY = imgH; } // image height larger than canvas
+    else { clearY = CanvasYSize; }
+
+    // get canvas context
+    ctx = document.getElementById('canvas').getContext('2d');
+
+    // set refresh rate
+    return setInterval(draw, speed);
+}
+
+function draw() {
+    ctx.clearRect(0, 0, clearX, clearY); // clear the canvas
+
+    // if image is <= Canvas Size
+    if (imgW <= CanvasXSize) {
+        // reset, start from beginning
+        if (x > CanvasXSize) { x = -imgW + x; }
+        // draw additional image1
+        if (x > 0) { ctx.drawImage(img, -imgW + x, y, imgW, imgH); }
+        // draw additional image2
+        if (x - imgW > 0) { ctx.drawImage(img, -imgW * 2 + x, y, imgW, imgH); }
+    }
+
+    // if image is > Canvas Size
+    else {
+        // reset, start from beginning
+        if (x > (CanvasXSize)) { x = CanvasXSize - imgW; }
+        // draw aditional image
+        if (x > (CanvasXSize-imgW)) { ctx.drawImage(img, x - imgW + 1, y, imgW, imgH); }
+    }
+    // draw image
+    ctx.drawImage(img, x, y,imgW, imgH);
+    // amount to move
+    x += dx;
+}
+
+ +

Below is the {{HTMLElement("canvas")}} in which the image is scrolled. Note that the width and height specified here must match the values of the CanvasXZSize and CanvasYSize variables in the JavaScript code.

+ +
<canvas id="canvas" width="800" height="200"></canvas>
+ +

{{EmbedLiveSample("A_looping_panorama", "830", "230")}}

+ +

Other examples

+ +
+
A basic ray-caster
+
A good example of how to do animations using keyboard controls.
+
Advanced animations
+
We will have a look at some advanced animation techniques and physics in the next chapter.
+
+ +

{{PreviousNext("Web/API/Canvas_API/Tutorial/Compositing", "Web/API/Canvas_API/Tutorial/Advanced_animations")}}

-- cgit v1.2.3-54-g00ecf