Exportieren (0) Drucken
Alle erweitern

Zeitliche Steuerung für skriptbasierte Animationen ("requestAnimationFrame")

In Internet Explorer 10 und Windows Store-Apps mit JavaScript wird nun die requestAnimationFrame-Methode unterstützt. Diese Methode ruft den Animationsframe auf, wenn das System zum Zeichnen bereit ist, und bietet damit eine nahtlosere und effizientere Methode zum Erstellen animierter Webseiten. Vor dieser API stand Webentwicklern bei Animationen, die mit setTimeout und setInterval gezeichnet wurden, keine effiziente Möglichkeit zur Verfügung, um Grafiktimer für Animationen zu planen. Dies führte zu überzeichneten Animationen, Verschwendung von CPU-Zyklen und höherem Stromverbrauch. Zudem werden Animationen häufig auch dann ausgeführt, wenn eine Website nicht sichtbar ist, insbesondere wenn die Website Seiten in Hintergrundregisterkarten verwendet oder der Browser minimiert ist.

Wenn für eine Animation eine JavaScript-Timerauflösung von 10 ms zum Zeichnen von Animationen verwendet wird, fehlt die Übereinstimmung bei der zeitlichen Steuerung, wie hier dargestellt.

Ein Diagramm, das den Frequenzunterschied zwischen einer Anzeigefrequenz und einer JavaScript-Timerauflösung veranschaulicht

Die obere Zeile stellt eine Anzeigefrequenz von 16,7 ms dar, die auf den meisten Monitoren verwendet wird, und die untere Zeile eine typische setTimeout-Frequenz von 10 ms. Jeder dritte Frame kann nicht gezeichnet werden (dargestellt durch den roten Pfeil), weil vor dem Anzeigeaktualisierungsintervall eine weitere Zeichnungsanforderung erfolgt. Da jeder dritte Frame verloren geht, führt diese Überzeichnung zu ruckeligen Animationen. Die Reduzierung der Timerauflösung kann zudem die Akkulebensdauer und die Leistung anderer Apps beeinträchtigen.

Die requestAnimationFrame-Methode – definiert in der World Wide Web Consortium (W3C)-Spezifikation zur zeitlichen Steuerung für skriptbasierte Animationen – kann das Problem mit den verlorenen Frames lösen, da Apps benachrichtigt werden können, wenn (und nur wenn) der Browser die Seitenanzeige aktualisieren muss. Dadurch sind Apps perfekt auf das Zeichnungsintervall des Browsers abgestimmt und verbrauchen nur die entsprechende Menge an Ressourcen. Die Umstellung von "setTimeout" auf requestAnimationFrame ist einfach, da beide Methoden nur einen Rückruf planen. Für eine kontinuierliche Animation rufen Sie requestAnimationFrame nach dem Aufruf der Animationsfunktion erneut auf.

Verwenden von "requestAnimationFrame"

Rufen Sie zum Verwenden dieser neuen API einfach requestAnimationFrame mithilfe einer Rückruffunktion auf. Die zeitliche Steuerung wird vom System behandelt. Wenn Sie gegenwärtig wie im folgenden Beispiel dargestellt setTimeout zur zeitlichen Steuerung Ihrer Animation verwenden:


var handle = setTimeout(renderLoop, PERIOD);

Können Sie setTimeout wie hier gezeigt durch requestAnimationFrame ersetzen:


var handle = requestAnimationFrame(renderLoop);

Dieser Code erledigt die erste Aktualisierung. Um die Animation weiter auszuführen, rufen Sie requestAnimationFrame erneut innerhalb der Rückruffunktion auf (hier als "renderLoop" dargestellt).


<!DOCTYPE html>
<html>
  <head>
    <title>Script-based animation using requestAnimationFrame</title>
    <style type="text/css">
     #animated { 
       position: absolute; top:100px; 
       padding: 50px; background: crimson; color: white; 
       }
    </style>

 
  </head>
  <body>
    <div>Click the box to stop and start it</div>
    <div id="animated">Hello there.</div>
   
    <script type="text/javascript">
      // global variables 
      var elm = document.getElementById("animated");
      var handle = 0;
      var lPos = 0;

      renderLoop();  // call animation frame to start

      function renderLoop() {
          elm.style.left = ((lPos += 3) % 600) + "px";
          handle = window.requestAnimationFrame(renderLoop);
      }

      // click the box to stop the animation 
      document.getElementById("animated").addEventListener("click", function () {
        if (handle) {
          window.cancelAnimationFrame(handle);
          handle = null;
        } else {
          renderLoop();
        }
      }, false);

      </script>

  </body>
</html>


In diesem Beispiel wird zunächst das <div>-Element mit getElementById in einer globalen Variable gespeichert. Die renderLoop()-Funktion wird aufgerufen, um die Animation zu starten. Nachdem die Position des <div>-Elements geändert wurde, wird requestAnimationFrame erneut aufgerufen, um die nächste Bewegung vorzubereiten. Diese Schleife wird fortgeführt, bis Sie den Browser schließen oder auf das <div>-Element klicken.

Die addEventListener-Methode behandelt das Click-Ereignis für das <div>-Element. Wenn Sie auf das Element klicken, wird cancelAnimationFrame mit dem aktuellen Handle aufgerufen.

Zeit in einer Rückruffunktion

Sie können mit der Rückruffunktion fast alles animieren, z. B. SVG, Canvas oder – wie hier gezeigt – CSS-Eigenschaften. Die Rückruffunktion enthält einen eingehenden time-Parameter, der für den Zeitpunkt steht, zu dem die Rückruffunktion aufgerufen wird. Es handelt sich dabei um einen "DOMHighResTimeStamp"-Parameter, einen Zeitwert mit hoher Auflösung, der ab dem Beginn der Navigation auf der Seite gemessen wird. Der DOMHighResTimeStamp-Wert wird auf ein Tausendstel Millisekunde genau in Millisekunden gemessen. Dieser Zeitwert ist nicht direkt mit der Date.now()-Funktion vergleichbar, die die Zeit in Millisekunden ab dem 1. Januar 1970 misst. Wenn Sie den time-Parameter mit der aktuellen Zeit vergleichen möchten, verwenden Sie window.performance.now für die aktuelle Zeit. Die Änderung des Zeitwerts von "DOMTimeStamp" in "DOMHighResTimeStamp" war eine kurzfristige Änderung im aktuellsten Editor-Entwurf der W3C-Spezifikation zur zeitlichen Steuerung für skriptbasierte Animationen und wird möglicherweise von einigen Anbietern noch als "DOMTimeStamp" implementiert. In früheren Versionen der W3C-Spezifikation wurde der DOMTimeStamp-Parameter verwendet, bei dem "Date.now" für die aktuelle Zeit verwendet werden konnte.

Browserunterstützung

Einige Browseranbieter implementieren wie zuvor erwähnt möglicherweise noch den DOMTimeStamp-Parameter oder haben die window.performance.now-Zeitsteuerungsfunktion nicht implementiert. Da noch keine endgültige Version der W3C-Spezifikation vorliegt, haben andere Browserhersteller eigene, mit einem Präfix versehene Implementierungen von requestAnimationFrame und cancelAnimationFrame entwickelt. Dieses Beispiel ist eine Version unseres Animationsprogramms, das in mehreren Browsern funktioniert und das <div>-Element zeitbasiert bewegt.


<!DOCTYPE html>
<html>
<head>
<title>Script-based animation using requestAnimationFrame</title>
<style type="text/css">
div { position: absolute; left: 10px; top:100px; padding: 50px;
  background: crimson; color: white; }
</style>
<script type="text/javascript">
    var requestId = 0;
    var startime = 0;
    var lpos = 0;
    var elm;

    function init() {
        elm = document.getElementById("animated");
    }
    
    function render() {
        elm.style.left = ((lpos += 3) % 600) + "px";
        requestId = window.requestAFrame(render);
    }

    function start() {
        if (window.performance.now) {
            startime = window.performance.now();
        } else {
            startime = Date.now();
        }
        requestId = window.requestAFrame(render);
    }
    function stop() {
        if (requestId)
            window.cancelAFrame(requestId);        
    }


    // handle multiple browsers for requestAnimationFrame()
    window.requestAFrame = (function () {
        return window.requestAnimationFrame ||
                window.webkitRequestAnimationFrame ||
                window.mozRequestAnimationFrame ||
                window.oRequestAnimationFrame ||
                // if all else fails, use setTimeout
                function (callback) {
                    return window.setTimeout(callback, 1000 / 60); // shoot for 60 fps
                };
    })();

    // handle multiple browsers for cancelAnimationFrame()
    window.cancelAFrame = (function () {
        return window.cancelAnimationFrame ||
                window.webkitCancelAnimationFrame ||
                window.mozCancelAnimationFrame ||
                window.oCancelAnimationFrame ||
                function (id) {
                    window.clearTimeout(id);
                };
    })();

   
</script>
</head>
<body onload="init();">

<div id="animated">Hello there.</div>
<button onclick="start()">Start</button>
<button onclick="stop()">Stop</button>
</body>
</html>


Dies ist eine aktualisierte Version eines Beispiels aus der W3C-Spezifikation, in der Anbieterpräfixe hinzugefügt wurden. Dieses Beispiel testet zudem, ob window.performance.now unterstützt wird, und verwendet andernfalls „Date.now“ zum Abrufen der aktuellen Zeit. Wenn requestAnimationFrame und cancelAnimationFrame nicht unterstützt werden, werden setTimeout und clearTimeout verwendet. Dies gewährleistet Kompatibilität mit früheren Browserversionen.

API-Referenz

requestAnimationFrame

Beispiele und Lernprogramme

Gut funktionierende Animationen unter Verwendung des requestAnimationFrame-Beispiels

Demos für die Internet Explorer-Testversion

Bubbles
requestAnimationFrame-API

IEBlog-Beiträge

W3C-Arbeitsgruppe "Web Performance": Kontinuierliche Investition in die Leistung
Web Performance-APIs erhalten schnell den Status "W3C Candidate Recommendations"
Förderung der Webstabilität mit der IE10 Release Preview
Das Jahr im Rückblick: W3C-Arbeitsgruppe "Web Performance"
Die PC-Hardware in HTML5 noch effektiver nutzen: neue Webleistungs-APIs, Teil 1

Spezifikation

Zeitliche Steuerung für skriptbasierte Animationen

 

 

Anzeigen:
© 2015 Microsoft