Reversing an Easing Curve

Avatar of Michelle Barker
Michelle Barker am

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

Let’s take a look at a carousel I worked on where items slide in and out of view with CSS animations. To get each item to slide in and out of view nicely I used a cubic-bezier for the animation-timing-function property, instead of using a standard easing keyword.

See the Pen Carousel with reversed easing curve by Michelle Barker (@michellebarker) on CodePen.

A cubic-bezier can appear confusing at first glance, but when used correctly, it can add a nice touch to the user experience.

While building this carousel, I realized I not only needed a custom animation curve, but had to use it in reverse as well to get the effect right. I figured it was worth sharing what I learned because creating a custom curve and reversing it may seem tricky, but it’s actually pretty straightforward.

Erstens, eine Einführung in Easing

Easing ist das Wort, das verwendet wird, um die Beschleunigung und Verlangsamung des Animationsfortschritts entlang einer Zeitachse zu beschreiben. Wir können dies als Graph darstellen, wobei x die Zeit und y der Fortschritt der Animation ist. Der Graph für eine lineare Animation, die keine Beschleunigung oder Verlangsamung aufweist (sie bewegt sich die ganze Zeit mit gleicher Geschwindigkeit), ist eine gerade Linie.

Linear easing graph

Nicht-lineares Easing verleiht Animationen ein natürlicheres, lebensechteres Gefühl. Wir können Easing auf Übergänge und Animationen in CSS anwenden. Die Eigenschaft animation-timing-function ermöglicht es uns, das Easing einer Animation zu definieren. (Die gleichen Optionen sind für transition-timing-function verfügbar.) Wir haben vier Schlüsselwörter zur Auswahl:

  • linear – wie oben beschrieben
  • ease-in – die Animation beginnt langsam und beschleunigt sich im Laufe ihres Fortschritts
  • ease-out – die Animation beginnt schnell und verlangsamt sich gegen Ende
  • ease-in-out – die Animation beginnt langsam, beschleunigt sich in der Mitte und verlangsamt sich gegen Ende
  • ease – der Standardwert, eine Variante von ease-in-out
  • cubic-bezier kennenlernen

    Wenn keine dieser Optionen für unsere Animation geeignet ist, können wir eine benutzerdefinierte Easing-Kurve mit der Funktion cubic-bezier erstellen. Hier ist ein Beispiel:

    .my-element {
      animation-name: slide;
      animation-duration: 3s;
      animation-timing-function: cubic-bezier(0.45, 0.25, 0.60, 0.95);
    }

    Wenn wir möchten, können wir diese Eigenschaften als Kurzschrift schreiben, so:

    .my-element {
      animation: slide 3s cubic-bezier(0.45, 0.25, 0.60, 0.95);
    }

    Sie werden feststellen, dass die Funktion cubic-bezier vier Werte annimmt. Dies sind die beiden Koordinatenpaare, die benötigt werden, um unsere Kurve auf dem Graphen zu plotten. Was repräsentieren diese Koordinaten? Nun, wenn Sie Vektorillustrationsprogramme wie Illustrator verwendet haben, ist Ihnen vielleicht die Idee von Vektorpunkten und „Handles“, die die Größe und Richtung der Kurve steuern, vertraut. Dies ist im Wesentlichen das, was wir mit einer Cubic-Bezier-Kurve plotten.

    Wir müssen nicht alle mathematischen Hintergründe von Cubic-Bezier-Kurven kennen, um eine schöne Animation zu erstellen. Glücklicherweise gibt es viele Online-Tools, wie cubic-bezier.com von Lea Verou, die es uns ermöglichen, eine Easing-Kurve zu visualisieren und die Werte zu kopieren. Dies habe ich für die obige Easing-Kurve getan, die so aussieht:

    Cubic-bezier easing graph

    Hier sehen wir die beiden Punkte, die wir plotten müssen, wobei die Cubic-Bezier-Funktion cubic-bezier(x1, y1, x2, y2) lautet.

    Cubic-bezier easing graph showing co-ordinates

    Easing in zwei Richtungen anwenden

    Mein Karussell dreht sich in beide Richtungen — wenn Sie auf den linken Pfeil klicken, gleitet das aktuelle Element nach rechts aus dem Bild, und das nächste Element gleitet von links herein; und wenn Sie auf den rechten Pfeil klicken, passiert das Gegenteil. Damit die Elemente schön in oder aus dem Bild gleiten, wird jeder Elementklasse eine Klasse hinzugefügt, je nachdem, ob der Benutzer auf die Schaltfläche „Nächstes“ oder „Vorheriges“ geklickt hat. Meine anfängliche Annahme war, dass ich einfach die animation-direction für Elemente, die in die entgegengesetzte Richtung gleiten, umkehren könnte, so:

    .my-element--reversed {
      animation: slide 3s cubic-bezier(0.45, 0.25, 0.60, 0.95) reverse;
    }

    Es gibt nur ein Problem: Das Umkehren der Animation kehrte auch die Easing-Kurve um! Jetzt sieht meine Animation in einer Richtung großartig aus, aber in der anderen Richtung ist sie völlig daneben. Oh nein!

    In dieser Demo zeigt die erste Box die anfängliche Animation (ein Element, das von links nach rechts gleitet) und die zweite Box zeigt, was passiert, wenn die animation-direction umgekehrt wird.

    See the Pen Reverse animation by Michelle Barker (@michellebarker) on CodePen.

    Sie können sehen, dass die beiden Animationen überhaupt nicht dasselbe Gefühl haben. Die erste Box beschleunigt früh und verlangsamt sich sanft im Verlauf, während die zweite Box recht träge beginnt, dann Fahrt aufnimmt, bevor sie abrupt abbremst. Das wäre für ein Karussell überhaupt nicht richtig.

    Wir haben die Wahl zwischen zwei Optionen, um dies zu erreichen:

    1. Wir könnten eine neue Keyframe-Animation erstellen, um die Elemente auszublenden, und dann das gleiche Easing wie zuvor anwenden. Das ist in diesem Beispiel nicht zu schwer, aber was, wenn wir eine komplexere Animation haben? Es würde viel mehr Arbeit erfordern, die gleiche Animation umgekehrt zu erstellen, und wir könnten leicht einen Fehler machen.
    2. Wir könnten die gleiche Keyframe-Animation (mit animation-direction: reverse) verwenden und die Easing-Kurve invertieren, damit wir in beiden Richtungen das gleiche Easing erhalten. Das ist auch nicht zu schwer.

    Um die Easing-Kurve für unsere umgekehrte Animation umzukehren, müssen wir die Kurve um 180 Grad um ihre Achse drehen und die neuen Koordinaten ermitteln.

    Comparing original easing graph with reversed graph

    Das können wir mit einfacher Mathematik tun — indem wir die Koordinatenpaare vertauschen und jeden Wert von 1 subtrahieren.

    Um dies zu visualisieren, stellen Sie sich vor, unsere ursprünglichen Werte sind:

    x1, y1, x2, y2

    Unsere umgekehrten Werte werden sein:

    (1 - x2), (1 - y2), (1 - x1), (1 - y1)

    In dieser Demo zeigt die dritte Box, was wir wollen: Das Element gleitet in die entgegengesetzte Richtung, aber mit umgekehrtem Easing, um ihm das gleiche Gefühl zu geben.

    See the Pen CSS Variables to reverse easing by Michelle Barker (@michellebarker) on CodePen.

    Lassen Sie uns Schritt für Schritt durchgehen, wie wir die umgekehrte Easing-Kurve berechnen können.

    Die neue Kurve mit CSS-Variablen berechnen

    Wir können CSS-Variablen verwenden, um die neue Kurve für uns zu berechnen! Weisen wir jedem Wert eine Variable zu:

    :root {
      --x1: 0.45;
      --y1: 0.25;
      --x2: 0.6;
      --y2: 0.95;
      
      --originalCurve: cubic-bezier(var(--x1), var(--y1), var(--x2), var(--y2));
    }

    Dann können wir diese Variablen verwenden, um die neuen Werte zu berechnen:

    :root {
      --reversedCurve: cubic-bezier(calc(1 - var(--x2)), calc(1 - var(--y2)), calc(1 - var(--x1)), calc(1 - var(--y1)));
    }

    Nun, wenn wir Änderungen an der ersten Variablensammlung vornehmen, wird die umgekehrte Kurve automatisch berechnet. Um dies beim Überprüfen und Debuggen unseres Codes etwas einfacher zu machen, teile ich diese neuen Werte gerne in eigene Variablen auf:

    :root {
      /* Original values */
      --x1: 0.45;
      --y1: 0.25;
      --x2: 0.6;
      --y2: 0.95;
      
      --originalCurve: cubic-bezier(var(--x1), var(--y1), var(--x2), var(--y2));
      
      /* Reversed values */
      --x1-r: calc(1 - var(--x2));
      --y1-r: calc(1 - var(--y2));
      --x2-r: calc(1 - var(--x1));
      --y2-r: calc(1 - var(--y1));
      
      --reversedCurve: cubic-bezier(var(--x1-r), var(--y1-r), var(--x2-r), var(--y2-r));
    }

    Nun bleibt nur noch, die neue Kurve auf unsere umgekehrte Animation anzuwenden:

    .my-element--reversed {
      animation: slide 3s var(--reversedCurve) reverse;
    }

    Um dies zu visualisieren, habe ich ein kleines Werkzeug erstellt, um die umgekehrten Werte einer Cubic-Bezier zu berechnen. Geben Sie die ursprünglichen Koordinatenwerte ein, um die umgekehrte Kurve zu erhalten:

    See the Pen Reverse cubic-bezier by Michelle Barker (@michellebarker) on CodePen.