Eine Geschichte der Animationsleistung

Avatar of Chris Coyier
Chris Coyier am

DigitalOcean bietet Cloud-Produkte für jede Phase Ihrer Reise. Starten Sie mit 200 $ kostenlosem Guthaben!

Alles begann mit einem Tweet

Kontext

Damit wir alle auf dem gleichen Stand sind: Was Hugo meint, ist, dass es zwei verschiedene Möglichkeiten gibt, Elemente zu „bewegen“.

  • Geben Sie dem Element eine `relative`, `absolute` oder `fixed` Positionierung. Dann können Sie `top`, `right`, `left`, `bottom` (oder eine beliebige Kombination davon) verwenden, um die Objekte zu verschieben.
  • Stellen Sie sicher, dass das Element einen `display`-Wert von `block` oder `inline-block` hat und verwenden Sie dann den Transformationswert `translate()`, `translateX()` oder `translateY()`, um das Element zu bewegen.

„Besser“, v1

Mein erster Gedanke, was „besser“ in diesem Zusammenhang bedeutet, ist, welche Methode unter verschiedenen Umständen besser geeignet ist. Was mich zu der Aussage bringt: **„verwechseln Sie Positionierung nicht mit Design-Bewegung.“**

Ein Beispiel. Sie haben einen Button. Sie möchten einen Effekt auf diesen Button anwenden, sodass er in seinem `:active`-Zustand um 2 Pixel nach unten ruckelt, um einen „gedrückten“ Effekt zu simulieren. Das ist eine Design-Bewegung, die mit `translate()` erfolgen sollte. Sie könnten es mit `top` oder `bottom` und relativer Positionierung tun, aber dann vermischen Sie die Konzepte von Positionierung und Design-Bewegung.

Nehmen wir an, Sie positionieren einen Button irgendwo anders in der App absolut (völlig legitim). Wenn dann `:active` auf den Button angewendet wird, wird dieser Button wahrscheinlich irgendwohin fliegen, wo Sie ihn nicht erwartet haben, und ihn möglicherweise unklickbar machen.

Die Verwendung von `translate()` „ruckelt“ das Element immer von seiner aktuellen Position aus, was perfekt für einen solchen Effekt oder jede design-spezifische Bewegung ist.

„Besser“, v2

Was Hugo wahrscheinlich meinte, war die **Performance**. Es ist zu einer gängigen allgemeinen Empfehlung geworden, dass die Verwendung von `translate()` zum Bewegen von Elementen eine bessere Performance hat als `top/right/bottom/left`. Aber hält die Daten stand? Schauen wir uns das an.

Zuerst habe ich eine sehr einfache Animation eines roten Balls erstellt, der hin und her animiert.

Für mein bloßes Auge, im neuesten stabilen Chrome (23) und auf einem Retina MacBook Pro mit viel RAM, ist die `translate()`-Version tatsächlich etwas performanter. Ich kann bei der `top/left`-Version sehr leichte Ruckler erkennen. Wahrnehmung ist wichtig, aber schauen wir uns die echten Daten an.

In den Chrome-Entwicklertools können Sie zum Tab „Timeline“ wechseln, dann zu „Frames“ und dann auf den Kreis „Aufnehmen“-Button unten drücken. Wenn die Animation läuft, starten Sie die Aufnahme für eine Weile und stoppen Sie sie dann. Die Daten sind am besten, wenn keine anderen Webseiten sichtbar sind, insbesondere wenn diese Animationen durchführen.

Bei der `top/left`-Version sehen Sie gelegentliche Spitzen über der Linie „60 FPS“ oder sechzig Bildern pro Sekunde. Das ist die Linie, unter der wir versuchen zu bleiben, da sie einer perfekt flüssigen wahrgenommenen Bewegung entspricht.

Spitzen über der Linie == Ruckler.
Flüssig

Aber warten Sie

Das wird komplizierter. Ich begann, mit Paul Irish zu sprechen, der am Google Chrome-Team arbeitet. Paul dachte, dass dies „Paints“ so einfach sind, dass es wahrscheinlich kein bester echter Leistungsindikator ist. Paul nahm meine Demos und erhöhte die Komplexität. Anstelle eines roten Balls, Josh Hibberts MacBook Pro. Anstelle eines weißen Hintergrunds, Nate Eagles Polsterung.

Die Dinge wurden seltsam, als **Pauls Beispiele das Gegenteil von dem zeigten, was wir erwartet hatten.** Die `top/left`-Version sieht flüssiger aus als die `translate()`-Version. Und überraschenderweise zeigten die Frames-Timeline keine großen Unterschiede.

Hier begann Paul, tiefer in diese seltsame Welt einzutauchen. Er fand viele interessante Dinge heraus! Paul sprach mit einem anderen Paul im Chrome-Team, Paul Lewis, der zustimmte, dass es „intelligenter ist, `translate()` für Design-Bewegungen zu verwenden.“ Aber er fügte hinzu, dass es mehr gibt als nur die Bildrate. Mit `translate()` erhalten Sie Sub-Pixel-Animationen, eine Art Verwischen zwischen Pixeln, das normalerweise zu flüssigeren Animationen führt.

Mit Subpixel-[Animationen] verlieren Sie Klarheit, was richtig ist. Der Schlüssel ist, länger bei gerundeten Werten an den Extremen zu verweilen, damit Ihre Augen die Befriedigung der Klarheit, aber die Flüssigkeit der Bewegung erhalten.

Paul Irish gräbt viel tiefer

Ich gebe das einfach an Paul weiter. Er hat ein 13-minütiges Video erstellt, das Sie ansehen sollten. Es erklärt all diese ausgefallenen GPU-Sachen und Subpixel-Rendering und all das.