Dieser Inhalt wurde automatisch aus dem Englischen übersetzt, und kann Fehler enthalten. Erfahre mehr über dieses Experiment.

View in English Always switch to English

Window: requestAnimationFrame() Methode

Baseline Widely available

This feature is well established and works across many devices and browser versions. It’s been available across browsers since ⁨Juli 2015⁩.

Die window.requestAnimationFrame() Methode informiert den Browser, dass Sie eine Animation ausführen möchten. Sie fordert den Browser auf, eine vom Nutzer bereitgestellte Callback-Funktion vor dem nächsten Neuzeichnen aufzurufen.

Die Häufigkeit der Aufrufe der Callback-Funktion stimmt im Allgemeinen mit der Aktualisierungsrate des Displays überein. Die häufigste Aktualisierungsrate beträgt 60 Hz (60 Zyklen/Bilder pro Sekunde), obwohl auch 75 Hz, 120 Hz und 144 Hz weit verbreitet sind. requestAnimationFrame() Aufrufe werden in den meisten Browsern pausiert, wenn sie in Hintergrund-Tabs oder versteckten <iframe>s ausgeführt werden, um die Leistung und die Akkulaufzeit zu verbessern.

Hinweis: Ihre Callback-Funktion muss requestAnimationFrame() erneut aufrufen, wenn Sie ein weiteres Bild animieren möchten. requestAnimationFrame() ist einmalig.

Warnung: Stellen Sie sicher, dass Sie immer das erste Argument (oder eine andere Methode, um die aktuelle Zeit zu erhalten) verwenden, um zu berechnen, wie weit die Animation in einem Bild voranschreiten wird — ansonsten wird die Animation auf Bildschirmen mit hoher Bildwiederholfrequenz schneller laufen. Für Möglichkeiten, dies zu tun, siehe die Beispiele unten.

Syntax

js
requestAnimationFrame(callback)

Parameter

callback

Die Funktion, die aufgerufen wird, wenn es Zeit ist, Ihre Animation für das nächste Neuzeichnen zu aktualisieren. Diese Callback-Funktion wird mit einem einzigen Argument übergeben:

timestamp

Ein DOMHighResTimeStamp, der die Endzeit des Renderings des vorherigen Bildes angibt (basierend auf der Anzahl der Millisekunden seit dem time origin). Der Zeitstempel ist eine Dezimalzahl, in Millisekunden, jedoch mit einer minimalen Genauigkeit von 1 Millisekunde. Für Window Objekte (nicht Workers) entspricht er document.timeline.currentTime. Dieser Zeitstempel wird zwischen allen Fenstern geteilt, die auf demselben Agenten laufen (alle gleich-origin Fenster und, wichtiger, gleich-origin iframes) — was es ermöglicht, Animationen über mehrere requestAnimationFrame Rückrufe hinweg zu synchronisieren. Der Zeitstempelwert ist auch ähnlich wie der Aufruf von performance.now() zu Beginn der Callback-Funktion, aber es ist nie derselbe Wert.

Wenn mehrere Rückrufe, die durch requestAnimationFrame() in einer einzelnen Bildfrequenz eingereiht wurden, beginnen auszuführen, erhält jeder denselben Zeitstempel, obwohl während der Berechnung der Arbeitslast jedes vorherigen Rückrufs Zeit vergangen ist.

Rückgabewert

Ein unsigned long Integerwert, die Anforderungs-ID, die den Eintrag in der Callback-Liste eindeutig identifiziert. Sie sollten keine Annahmen über seinen Wert machen. Sie können diesen Wert an window.cancelAnimationFrame() übergeben, um die Aktualisierungs-Callback-Anforderung zu stornieren.

Warnung: Die Anforderungs-ID wird typischerweise als ein pro-Fenster inkrementierender Zähler implementiert. Auch wenn er bei 1 zu zählen beginnt, kann er daher überlaufen und 0 erreichen. Während dies für kurzlebige Anwendungen wahrscheinlich kein Problem darstellt, sollten Sie vermeiden, 0 als Sentinel-Wert für ungültige Anforderungs-IDs zu verwenden und stattdessen unerreichbare Werte wie null bevorzugen. Die Spezifikation legt das Überlaufverhalten nicht fest, daher haben Browser unterschiedliche Verhaltensweisen. Bei einem Überlauf würde der Wert entweder auf 0 zurückspringen, einen negativen Wert annehmen oder mit einem Fehler fehlschlagen. Außer wenn Überlauf einen Fehler verursacht, sind Anforderungs-IDs nicht wirklich eindeutig, da es nur endlich viele 32-Bit-Integer für möglicherweise unendlich viele Rückrufe gibt. Beachten Sie jedoch, dass es ~500 Tage dauern würde, bis das Problem auftritt, wenn mit 60Hz bei 100 Aufrufen von requestAnimationFrame() pro Bild gerendert wird.

Beispiele

In diesem Beispiel wird ein Element für 2 Sekunden (2000 Millisekunden) animiert. Das Element bewegt sich mit einer Geschwindigkeit von 0,1px/ms nach rechts, sodass seine relative Position (in CSS-Pixeln) in Abhängigkeit von der seit dem Start der Animation verstrichenen Zeit (in Millisekunden) mit 0.1 * elapsed berechnet werden kann. Die endgültige Position des Elements ist 200px (0.1 * 2000) rechts von seiner Ausgangsposition.

js
const element = document.getElementById("some-element-you-want-to-animate");
let start;

function step(timestamp) {
  if (start === undefined) {
    start = timestamp;
  }
  const elapsed = timestamp - start;

  // Math.min() is used here to make sure the element stops at exactly 200px
  const shift = Math.min(0.1 * elapsed, 200);
  element.style.transform = `translateX(${shift}px)`;
  if (shift < 200) {
    requestAnimationFrame(step);
  }
}

requestAnimationFrame(step);

Die folgenden drei Beispiele veranschaulichen verschiedene Ansätze zur Festlegung des Nullpunkts in der Zeit, der Grundlage zur Berechnung des Fortschritts Ihrer Animation in jedem Bild. Wenn Sie zu einer externen Uhr synchronisieren möchten, wie zum Beispiel BaseAudioContext.currentTime, ist die höchste verfügbare Präzision die Dauer eines einzelnen Bildes, 16,67ms @60Hz. Das Zeitstempel-Argument des Rückrufs repräsentiert das Ende des vorherigen Bildes, sodass der frühestmögliche Zeitpunkt, zu dem Ihr neu berechneter Wert angezeigt wird, im nächsten Bild ist.

Dieses Beispiel wartet bis zur Ausführung des ersten Rückrufs, um zero zu setzen. Wenn Ihre Animation zu einem neuen Wert springt, wenn sie startet, müssen Sie sie auf diese Weise strukturieren. Wenn Sie nicht zu etwas Externem synchronisieren müssen, wie zum Beispiel Audio, wird dieser Ansatz empfohlen, da einige Browser eine Verzögerung von mehreren Bildern zwischen dem ersten Aufruf von requestAnimationFrame() und dem ersten Aufruf der Callback-Funktion haben.

js
let zero;
requestAnimationFrame(firstFrame);
function firstFrame(timestamp) {
  zero = timestamp;
  animate(timestamp);
}
function animate(timestamp) {
  const value = (timestamp - zero) / duration;
  if (value < 1) {
    element.style.opacity = value;
    requestAnimationFrame((t) => animate(t));
  } else element.style.opacity = 1;
}

Dieses Beispiel verwendet document.timeline.currentTime, um einen Nullwert vor dem ersten Aufruf von requestAnimationFrame festzulegen. document.timeline.currentTime stimmt mit dem timestamp Argument überein, sodass der Nullwert gleichwertig zum Zeitstempel des 0. Bildes ist.

js
const zero = document.timeline.currentTime;
requestAnimationFrame(animate);
function animate(timestamp) {
  const value = (timestamp - zero) / duration; // animation-timing-function: linear
  if (value < 1) {
    element.style.opacity = value;
    requestAnimationFrame((t) => animate(t));
  } else element.style.opacity = 1;
}

Dieses Beispiel animiert mithilfe von performance.now() anstelle des Zeitwertes des Rückrufs. Sie könnten dies verwenden, um eine etwas höhere Synchronisationspräzision zu erreichen, obwohl der zusätzliche Präzisionsgrad variabel ist und nicht viel von einer Steigerung darstellt.

Hinweis: Dieses Beispiel erlaubt es Ihnen nicht, Animationsrückrufe zuverlässig zu synchronisieren.

js
const zero = performance.now();
requestAnimationFrame(animate);
function animate() {
  const value = (performance.now() - zero) / duration;
  if (value < 1) {
    element.style.opacity = value;
    requestAnimationFrame((t) => animate(t));
  } else element.style.opacity = 1;
}

Spezifikationen

Specification
HTML
# dom-animationframeprovider-requestanimationframe

Browser-Kompatibilität

Siehe auch