SVG-Animation für Fortgeschrittene

In diesem Thema werden SVG-Animationsverfahren für fortgeschrittene Benutzer beschrieben. Das Thema schließt an SVG-Animation für Anfänger an. Rechnen Sie ungefähr mit einem Zeitaufwand von einer Stunde, um die in diesem Thema vorgestellten Konzepte vollständig zu verstehen.

Hinweis  Zum Anzeigen der in diesem Thema enthaltenen Beispiele benötigen Sie einen Browser, z. B. Windows Internet Explorer 9 oder höher, der das SVG-Element unterstützt.

In SVG-Animation – Grundstufe haben wir uns hauptsächlich auf die Drehung von Objekten konzentriert. In diesem Thema richten wir unser Augenmerk auf die Translation von Objekten (d. h. die räumliche Bewegung) und das häufigste Ergebnis derartiger Translationen – Kollisionen.

Beginnen wir die Untersuchung von Objekttranslation und -kollision mit dem wahrscheinlich einfachsten möglichen Objekt – dem Kreis. Im folgenden Beispiel wird ein Kreis über den Bildschirm bewegt:

Beispiel 1 – Einfache Translation

Beispiel 1


<!DOCTYPE html>
<html>

<head>
  <title>SVG Animation - Circle Translation</title>
  <meta http-equiv="X-UA-Compatible" content="IE=Edge"/> <!-- Remove this comment only if you have issues rendering this page on an intranet site. -->
  <style>
    svg {
      display: block; /* SVG is inherently an inline element. */
      margin: 0 auto; /* Center the SVG viewport. */
    }
  </style>
</head>

<body>
  <svg id="svgElement" width="800px" height="600px" viewBox="0 0 800 600">
    <rect x="0" y="0" width="100%" height="100%" rx="10" ry="10" style="fill: white; stroke: black;" />
    <circle id="circle0" cx="40" cy="40" r="40" style="fill: orange; stroke: black; stroke-width: 1;" />
  </svg>
  <script>
    "use strict";

    var delay = 16; // Used to compute the required displacement value.
    var svgElement = document.getElementById("svgElement"); 
    var circle0 = document.getElementById("circle0"); 

    /* Create custom properties to store the circle's velocity: */
    circle0.vx = 50; // Move the circle at a velocity of 50 pixels per second in the x-direction.
    circle0.vy = 20; // Move the circle at a velocity of 20 pixels per second in the y-direction.

    var r = circle0.r.baseVal.value; // The radius of circle0.
    var boxWidth = svgElement.width.baseVal.value; // The width of the SVG viewport.
    var boxHeight = svgElement.height.baseVal.value; // The height of the SVG viewport.

    var requestAnimationFrameID = window.requestAnimationFrame(doAnim); // Call the doAnim() function to start the demo.

    /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */

    function s2d(s)
      /*
        The function name "s2d" means "speed to displacement". This function returns the required
        displacement value for an object traveling at "s" pixels per second. This function assumes the following:

           * The parameter s is in pixels per second.
           * "constants.delay" is a valid global constant.
           * The SVG viewport is set up such that 1 user unit equals 1 pixel.
      */ {
      return (s / 1000) * delay; // Given "constants.delay", return the object's displacement such that it will travel at s pixels per second across the screen.
    }

    /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */

    function doAnim() {
      requestAnimationFrameID = window.requestAnimationFrame(doAnim); // Continue calling the doAnim() function until the circle has hit the bottom or right wall of SVG viewport.

      circle0.cx.baseVal.value += s2d(circle0.vx); // Move the circle in the x-direction by a small amount.
      circle0.cy.baseVal.value += s2d(circle0.vy); // Move the circle in the y-direction by a small amount.

      if ((circle0.cx.baseVal.value >= (boxWidth - r)) || (circle0.cy.baseVal.value >= (boxHeight - r))) // Detect if the circle attempts to exit the SVG viewport assuming the ball is moving to the right and down.
        window.cancelAnimationFrame(requestAnimationFrameID); // The circle has hit the bottom or right wall so instruct the browser to stop calling doAnim().
    }
  </script>
</body>
</html>

Wichtig  Anstatt <meta http-equiv-"X-UA-Compatible" content="IE-Edge" /> in den <head>-Block einzubeziehen, können Sie Ihren Webentwicklungsserver so konfigurieren, dass der X-UA-kompatible HTTP-Header mit IE=Edge gesendet wird. Damit stellen Sie sicher, dass die Ausführung im aktuellen Standards-Modus erfolgt, wenn Sie in einem Intranet entwickeln.

Wie Sie im vorherigen Codebeispiel sehen können, wird die SVG-DOM-Skripterstellung verwendet (eine entsprechende Erläuterung finden Sie unter SVG-Animation – Grundstufe).

Das Grundkonzept ist einfach: Alle 16 Millisekunden (der Wert von delay) wird ‎‎‎‏‏ die Position des Kreismittelpunkts um einen kleinen Betrag geändert. In Pseudocode ‎‎‎‏‏ ausgedrückt, sieht dies wie folgt aus:


<x-coordinate of circle> = <x-coordinate of circle> + 0.5
<y-coordinate of circle> = <y-coordinate of circle> + 0.2

Anstatt die Werte für Δx (d. h. 0,5) und Δy (d. h. 0,2) hart zu codieren, wurde ein ‎‎‎‏‏ Geschwindigkeitsvektor für den Kreis angegeben, indem zwei neue benutzerdefinierte ‎‎‎‏‏ Eigenschaften an das Kreiselement angehängt wurden:


circle0.vx = 50; // Move the circle at a velocity of 50 pixels per second in the x-direction.
circle0.vy = 20; // Move the circle at a velocity of 20 pixels per second in the y-direction.

Dieser Geschwindigkeitsvektor v kann wie folgt grafisch dargestellt werden:

2D-Geschwindigkeitsvektor

Figure 1

Daher ist circle0.vx die x-Komponente des Geschwindigkeitsvektors des Kreises (in Pixel pro Sekunde) und circle0.vy ist die y-Komponente des Vektors (in Pixel pro Sekunde). Beachten Sie, dass das obige xy-Koordinatensystem den SVG-Viewport darstellt, dessen Ursprung in der oberen linken Ecke des Bildschirms liegt.

Jetzt ist zu Animationszwecken eine Funktion zum Umsetzen der Geschwindigkeitsvektoren einer dieser Komponenten in eine entsprechende Verschiebung erforderlich. Dies wird mithilfe der s2d(v)-Funktion erreicht. Wenn der Parameter v z. B. 50 Pixel pro Sekunde entspricht und delay en Wert "16 Millisekunden" aufweist, dann ergibt sich über die Dimensionsanalyse eine Verschiebung von (50 Pixel/s)•(1 s/1000 ms)•(16 ms) = 0,8 Pixel.

Zuletzt wird die Animation beendet, wenn der Kreis entweder die rechte oder untere "Feldwand" des SVG-Viewports berührt. Das bedeutet, es ist eine einfache Form der Kollisionserkennung erforderlich:


if ( (circle0.cx.baseVal.value > (boxWidth - r)) || (circle0.cy.baseVal.value > (boxHeight - r)) )
  clearInterval(timer);

Da ermittelt werden soll, wann der Kreisrand eine Wand berührt (im Gegensatz zur Kreismitte), muss der Kreisradius subtrahiert werden, wie im obigen Codeausschnitt gezeigt (d. h. boxWidth – r und boxHeight – r).

Mithilfe des obigen Verfahrens zur Kollisionserkennung wird im folgenden Beispiel gezeigt, wie ein Ball (ein Kreis) von einer Wand rückprallt:

Beispiel 2 – Rückprall von einer Wand

Beispiel 2


<!DOCTYPE html>
<html>

<head>
  <title>SVG Animation - Circle Translation</title>
  <meta http-equiv="X-UA-Compatible" content="IE=Edge" /> <!-- Remove this comment only if you have issues rendering this page on an intranet site. -->
  <style>
    svg {
      display: block; /* SVG is inherently an inline element. */
      margin: 0 auto; /* Center the SVG viewport. */
    }
  </style>
</head>

<body>
  <svg id="svgElement" width="800px" height="600px" viewBox="0 0 800 600">
    <rect x="0" y="0" width="100%" height="100%" rx="10" ry="10" style="fill: white; stroke: black;" />
    <circle id="circle0" cx="40" cy="40" r="40" style="fill: orange; stroke: black; stroke-width: 1;" />
  </svg>
  <script>
    "use strict";

    var requestAnimationFrameID; // Contains the requestAnimationFrame() object, used to stop the animation.
    var delay = 16; // Used to compute the required displacement value.

    var svgElement = document.getElementById("svgElement"); // Required for Mozilla, this line is not necessary IE9 or Chrome.
    var circle0 = document.getElementById("circle0"); // Required for Mozilla, this line is not necessaryIE9 or Chrome.

    circle0.vx = 150; // Move the circle at a velocity of 150 pixels per second in the x-direction.
    circle0.vy = 60; // Move the circle at a velocity of 60 pixels per second in the y-direction.

    var r = circle0.r.baseVal.value; // The radius of circle0.
    var boxWidth = svgElement.width.baseVal.value; // The width of the SVG viewport.
    var boxHeight = svgElement.height.baseVal.value; // The height of the SVG viewport.

    requestAnimationFrameID = window.requestAnimationFrame(doAnim); // Call the doAnim() function.

    /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */

    function s2d(s)
      /*
        The function name "s2d" means "speed to displacement". This function returns the required
        displacement value for an object traveling at "s" pixels per second. This function assumes the following:

           * The parameter s is in pixels per second.
           * "constants.delay" is a valid global constant.
           * The SVG viewport is set up such that 1 user unit equals 1 pixel.
      */ {
      return (s / 1000) * delay; // Given "constants.delay", return the object's displacement such that it will travel at s pixels per second across the screen.
    }

    /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */

    function doAnim() {
      requestAnimationFrameID = window.requestAnimationFrame(doAnim); // Continue calling the doAnim() function until the circle has hit the bottom wall.

      circle0.cx.baseVal.value += s2d(circle0.vx); // Move the circle in the x-direction by a small amount.
      circle0.cy.baseVal.value += s2d(circle0.vy); // Move the circle in the y-direction by a small amount.

      /* Assumes the circle's velocity is such that it will only hit the right wall: */
      if (circle0.cx.baseVal.value >= (boxWidth - r)) // Detect if the circle attempts to exit the right side of the SVG viewport.
        circle0.vx *= -1; // Reverse the direction of the x-component of the ball's velocity vector - this is a right-wall bounce.

      if (circle0.cy.baseVal.value >= (boxHeight - r))
        window.cancelAnimationFrame(requestAnimationFrameID); // The circle has hit the bottom wall so instruct the browser to stop calling doAnim().
    }
  </script>
</body>
</html>

Das zentrale Konzept des Rückpralls eines Balls von einer Wand ist die Vektorspiegelung, wie wie in der folgenden vereinfachten Grafik dargestellt:

Vektorspiegelung an einer Wand

Figure 2

In Abbildung 2 stellt die rechte schwarz gestrichelte Linie die Wand dar, vin ist der Geschwindigkeitsvektor des Balls, bevor dieser auf die Wand trifft, und vout stellt den Geschwindigkeitsvektor des Balls dar, nachdem er auf die Wand getroffen ist. Wie Sie sehen, ändert sich (in diesem bestimmten Fall) nur das Vorzeichen der x-Komponente für die Größe des abgehenden Geschwindigkeitsvektors. Es ist also nur eine Vorzeichenänderung für die x-Komponente des Geschwindigkeitsvektors des Balls erforderlich, damit der Ball von der rechten Wand rückprallt:


if ( circle0.cx.baseVal.value > (boxWidth - r) )
  circle0.vx *= -1; 

Beachten Sie, dass die Animation gemäß Vorgabe beendet wird, sobald der Ball die untere Wand berührt:


if ( circle0.cy.baseVal.value > (boxHeight - r) )
  clearInterval(timer);

In dem vorherigen Beispiel funktioniert der Code nur dann, wenn sich der Ball anfänglich genau in die richtige Richtung bewegt. Dabei handelt es sich um eine theoretische Annahme. Im nächsten Beispiel wird diese theoretische Annahme in die Praxis umgesetzt. Bevor Sie fortfahren, betrachten Sie erneut die Abbildung 2. Stellen Sie sich vor, der blaue Vektor prallt von der linken Wand ab. Es leuchtet unmittelbar ein, dass Sie wie bei der rechten Wand nur das Vorzeichen der x-Komponente des Geschwindigkeitsvektors ändern müssen, um das richtige Verhalten zu erhalten. Das Gleiche gilt für die obere sowie für die untere Wand. Sie müssen in diesen Fällen also jeweils nur das Vorzeichen der y-Komponente ändern, um zum richtigen Ergebnis zu kommen. Dies ist die im folgenden Beispiel verwendete Logik:

Beispiel 3 – Rückprall von vier Wänden

Beispiel 3


<!DOCTYPE html>
<html>

<head>
  <title>SVG Animation - Circle Translation</title>
  <meta http-equiv="X-UA-Compatible" content="IE=Edge"/> <!-- Remove this comment only if you have issues rendering this page on an intranet site. -->
  <style>
    svg {
      display: block; /* SVG is inherently an inline element. */
      margin: 0 auto; /* Center the SVG viewport. */
    }
  </style>
</head>

<body>
  <svg id="svgElement" width="800px" height="600px" viewBox="0 0 800 600">
    <rect x="0" y="0" width="100%" height="100%" rx="10" ry="10" style="fill: white; stroke: black;" />
    <circle id="circle0" cx="40" cy="40" r="40" style="fill: orange; stroke: black; stroke-width: 1;" />
  </svg>
  <script>
    "use strict";

    var requestAnimationFrameID; // Contains the requestAnimationFrame() object.
    var delay = 20; // Used to compute the required displacement value.

    var svgElement = document.getElementById("svgElement"); // Required for Mozilla, this line is not necessary for IE9 or Chrome.
    var circle0 = document.getElementById("circle0"); // Required for Mozilla, this line is not necessary for IE9 or Chrome.
    var r = circle0.r.baseVal.value; // The radius of circle0.
    var boxWidth = svgElement.width.baseVal.value; // The width of the SVG viewport.
    var boxHeight = svgElement.height.baseVal.value; // The height of the SVG viewport.

    /* Create custom properties to store the circle's velocity: */
    circle0.vx = 200; // Move the circle at a velocity of 200 pixels per second in the x-direction.
    circle0.vy = 80; // Move the circle at a velocity of 80 pixels per second in the y-direction.

    requestAnimationFrameID = window.requestAnimationFrame(doAnim); // Call the doAnim() function.

    /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */

    function s2d(s)
      /*
        The function name "s2d" means "speed to displacement". This function returns the required
        displacement value for an object traveling at "s" pixels per second. This function assumes the following:

           * The parameter s is in pixels per second.
           * "constants.delay" is a valid global constant.
           * The SVG viewport is set up such that 1 user unit equals 1 pixel.
      */ {
      return (s / 1000) * delay; // Given "constants.delay", return the object's displacement such that it will travel at s pixels per second across the screen.
    }

    /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */

    function verticalWallCollision(r, width)
      /*
        Returns true if circl0 has hit (or gone past) the left or the right wall; false otherwise.
      */ {
      return ((circle0.cx.baseVal.value <= r) || (circle0.cx.baseVal.value >= (width - r)));
    }

    /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */

    function horizontalWallCollision(r, height)
      /*
        Returns true if circl0 has hit (or gone past) the top or the bottom wall; false otherwise.
      */ {
      return ((circle0.cy.baseVal.value <= r) || (circle0.cy.baseVal.value >= (height - r)));
    }

    /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */

    function doAnim() {
      circle0.cx.baseVal.value += s2d(circle0.vx); // Move the circle in the x-direction by a small amount.
      circle0.cy.baseVal.value += s2d(circle0.vy); // Move the circle in the y-direction by a small amount.

      if (verticalWallCollision(r, boxWidth))
        circle0.vx *= -1; // Reverse the direction of the x-component of the ball's velocity vector.

      if (horizontalWallCollision(r, boxHeight))
        circle0.vy *= -1; // Reverse the direction of the y-component of the ball's velocity vector.

      requestAnimationFrameID = window.requestAnimationFrame(doAnim); // Continue calling the doAnim() function.
    }
  </script>
</body>
</html>

Der einzige wesentliche Unterschied zwischen Beispiel 2 – Rückprall von einer Wand und Beispiel 3 – Rückprall von vier Wänden zeigt sich in den beiden Funktionen verticalWallCollision(r, width) und horizontalWallCollision(r, height). Letztere Funktion besteht einfach aus der folgenden Zeile:


return ( (circle0.cy.baseVal.value <= r) || (circle0.cy.baseVal.value >= (height - r)) );

Diese gewissermaßen kryptische Zeile wird mithilfe der folgenden Abbildung verständlich:

Kollisionen mit horizontalen Wänden

Figure 3

Wie Sie in Abbildung 3 erkennen können, kollidiert der Ball mit der unteren Wand, wenn die y-Koordinate des Ballmittelpunkts größer als oder gleich dem Abstand "r" von der unteren Wand ist. Dieser Abstand ist einfach Höhe – r. Daher sieht der Test für die untere Wand wie folgt aus:


circle0.cy.baseVal.value >= (height - r)

Gleichermaßen kollidiert der Ball mit der oberen Wand, wenn die y-Koordinate des Ballmittelpunkts kleiner als oder gleich dem Abstand "r" ist. Dieser Abstand ist wiederum einfach "r – 0 = r", daher lautet der Test für die obere Wand:


circle0.cy.baseVal.value <= r

Die Kombination beider Tests führt zur obigen Rückgabeanweisung.

Beispiel 4 – Kollisionen zweier Bälle

Beispiel 4

Einen Ball in einem Feld herumspringen zu sehen, ist für ein paar Minuten ganz spaßig. Der nächste Schritt, bei dem ein weiterer Ball zum Feld hinzugefügt wird, macht das Ganze sehr viel interessanter. Dazu müssen Ball-Ball-Kollisionen und deren mathematische Grundlagen berücksichtigt werden. Einen Einstieg in die Thematik bietet Beispiel 4. Beachten Sie, dass dieser Beispielcode aufgrund seiner Länge nicht angezeigt wird. Verwenden Sie stattdessen das Feature View source in Windows Internet Explorer, um den zugehörigen Code anzuzeigen. Hier folgt der Einfachheit halber ein Bildschirmfoto vonBeispiel 4:

Bildschirmfoto von Beispiel 4

Zu Beginn werden ein Objekt, das einen generischen Vektor darstellt, und Funktionen für vier allgemeine Vektoroperationen erstellt:

  • Vektoraddition.
  • Vektorsubtraktion.
  • Die Multiplikation eines Skalars mit einem Vektor.
  • Das Skalarprodukt zweier Vektoren.

Die Implementierung dieser Funktionen erweist sich als unkompliziert, wenn die grundlegenden Vektoroperationen verstanden wurden. Eine gute Übersicht über Vektoren und ihre zugehörigen Operationen finden Sie bei Wikipedia oder Wolfram MathWorld.

Beachten Sie, dass die Vektorfunktionen in diesem Beispiel in einem Skriptblock mit der Kennzeichnung "VEKTORFUNKTIONEN" enthalten und umfassend kommentiert sind. Die Tatsache, dass jedes Kreiselement (d. h. jeder Ball) seinem eigenen Geschwindigkeitsvektor folgt, sollte diesbezüglich jedoch hervorgehoben werden (siehe init-Funktion):


var gv0 = new Vector(0, 0);

ball0.v = gv0;
ball0.v.xc = 200;      
ball0.v.yc = 80;

Hier wird ein neuer generischer Vektor gv0 lokal erstellt und an das globale Kreiselement ball0 angehängt. Anschließend werden für die x- und y-Komponente des Geschwindigkeitsvektors von Ball 0 die Werte 200 Pixel bzw. 80 Pixel pro Sekunde festgelegt.

Die Ball-Wand-Kollisionen wurden in Beispiel 3 bereits beschrieben. Hier gehen wir auf die Ball-Ball-Kollisionen ein. Leider sind die zugehörigen mathematischen Grundlagen nicht trivial. Die folgenden mathematischen Berechnungen sind erforderlich, um die korrekten Geschwindigkeitsvektoren im Anschluss an die Kollision zweier Bälle zu ermitteln:

  1. Berechnen Sie die relative Geschwindigkeit Vab mithilfe der beiden Geschwindigkeitsvektoren der Bälle vor der Kollision:
    
    var Vab = vDiff(ballA.v, ballB.v);
    
    
  2. Berechnen Sie einen Einheitsvektor n, der senkrecht zum Kollisionspunkt ist:
    
    var n = collisionN(ballA, ballB);
    
    
  3. Berechnen Sie den "Impuls" f, damit das Moment erhalten bleibt:
    
    f = f_numerator / f_denominator;
    
    
  4. Berechnen Sie die relative Geschwindigkeit Vab mithilfe der beiden Geschwindigkeitsvektoren der Bälle vor der Kollision:
    
    ballA.v = vAdd( ballA.v, vMulti(f/Ma, n) ); 
    ballB.v = vDiff( ballB.v, vMulti(f/Mb, n) );
    
    

Weitere Informationen finden Sie im Abschnitt "Have Collision, Will Travel" von Collision Response.

Beispiel 5 – Kombination aller Elemente: Ballarena

Beispiel 5

Nachdem die Ball-Wand- und Ball-Ball-Kollisionen erläutert wurden, kann Beispiel 4 dahingehend erweitert werden, dass sich viele Bälle innerhalb einer kreisförmigen Arena (im Gegensatz zu einem Feld) – der "Ballarena" – befinden und miteinander kollidieren.

Auch hier wird der Code für dieses Beispiel aufgrund seiner Länge nicht angezeigt (verwenden Sie zum Anzeigen des Codes die Funktion Quellcode anzeigen). Es folgt jedoch ein Screenshot:

Bildschirmfoto der Ballarena

Wichtige Hinweise zu Codeelementen:

  • Alle Ballelemente (d. h. circle-Elemente) werden programmgesteuert erstellt, und benutzerdefinierte Eigenschaften werden an diese Elemente angehängt (z. B. ein Geschwindigkeitsvektorobjekt).
  • Farbe, Radius und Ausgangsposition (innerhalb der Arena) der einzelnen Bälle werden zufällig gewählt, daher ergeben sich bei jeder Aktualisierung der Seite unterschiedliche Ausgangsbedingungen.
  • Da die Bälle nicht länger von den Wänden eines einfachen Felds abprallen, wird die Gleichung für die allgemeine Vektorspiegelung (v – 2(v•n)n) verwendet, um den korrekten Geschwindigkeitsvektor für einen Ball nach der Kollision mit der Arenawand zu berechnen. Weitere Informationen finden Sie unter Reflection auf der Website "Wolfram MathWorld".
  • Die Masse jedes Balls (d. h. Kreises) entspricht seiner Fläche.
  • Sie können anpassen, wie viel Energie pro Aufprall verloren geht, indem Sie den Stoßkoeffizienten anpassen (d. h. constants.epsilon). Der Wert "1" gibt an, dass kein Energieverlust auftritt, wie dies bei vollkommen elastischen Kollisionen der Fall ist.

Beispiel 6 – Objektorientierte Ballarena

Beispiel 6 entspricht mit Ausnahme der wesentlich objektorientierteren Implementierung genauBeispiel 5.

Übungen

Aus den beiden letzten Beispielen ergeben sich die folgenden logischen Schritte:

  • Hinzufügen einer Schaltfläche zum Zurücksetzen.
  • Hinzufügen von Schaltflächen zum Erhöhen oder Verringern der Anzahl von in der Simulation verwendeten Bällen.
  • Hinzufügen von Schaltflächen zum Erhöhen oder Verringern der Geschwindigkeit der Simulation.
  • Hinzufügen einer Schaltfläche zum Verkleinern des Stoßkoeffizienten.
  • Hinzufügen einer Schaltfläche zum Umschalten der Balllinienverfolgung (in dem Sinne, dass jeder Ball eine "Spur" hinterlässt, die angibt, welchen Weg ihr Mittelpunkt zurückgelegt hat).
  • Und in erster Linie das Verbessern der in dieser Simulation verwendeten und so einfach wie möglich gehaltenen Kollisionserkennung.

Diese Erweiterungen werden dem Leser in Form einer Übung bereitgestellt, die wesentlich zum Verständnis der in diesem Thema beschriebenen Verfahren beitragen sollte.

Verwandte Themen

SVG-Animation für Anfänger
HTML5-Grafiken
Scalable Vector Graphics (SVG)

 

 

Anzeigen:
© 2014 Microsoft