Easing-Animationen in Canvas

Avatar of Darshan Somashekar
Darshan Somashekar am

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

Das <canvas>-Element in HTML und die Canvas-API in JavaScript bilden zusammen eine der wichtigsten Möglichkeiten für Rastergrafiken und Animationen im Web. Ein häufiger Anwendungsfall für Canvas ist die programmatische Generierung von Bildern für Websites, insbesondere für Spiele. Genau das habe ich in einer Website, die ich zum Spielen von Solitaire erstellt habe, gemacht. Die Karten, einschließlich aller Bewegungen, werden alle in Canvas ausgeführt.

In diesem Artikel befassen wir uns speziell mit Animationen in Canvas und Techniken, um sie flüssiger aussehen zu lassen. Wir werden uns speziell mit Easing-Übergängen befassen – wie „Ease-in“ und „Ease-out“ –, die in Canvas nicht kostenlos enthalten sind, wie sie es in CSS sind.

Beginnen wir mit einem statischen Canvas. Ich habe eine einzelne Spielkarte in den Canvas gezeichnet, die ich aus dem DOM geholt habe.

Beginnen wir mit einer grundlegenden Animation: dem Bewegen dieser Spielkarte auf dem Canvas. Selbst für recht grundlegende Dinge muss man in Canvas von Grund auf neu arbeiten, daher müssen wir Funktionen aufbauen, die wir verwenden können.

Zuerst erstellen wir Funktionen, die bei der Berechnung von X- und Y-Koordinaten helfen.

function getX(params) {
  let distance = params.xTo - params.xFrom;
  let steps = params.frames;
  let progress = params.frame;
  return distance / steps * progress;
}


function getY(params) {
  let distance = params.yTo - params.yFrom;
  let steps = params.frames;
  let progress = params.frame;
  return distance / steps * progress;
}

Dies wird uns helfen, die Positionswerte zu aktualisieren, während das Bild animiert wird. Dann rendern wir den Canvas immer wieder neu, bis die Animation abgeschlossen ist. Dies tun wir, indem wir den folgenden Code zu unserer addImage()-Methode hinzufügen.

if (params.frame < params.frames) {
  params.frame = params.frame + 1;
  window.requestAnimationFrame(drawCanvas);
  window.requestAnimationFrame(addImage.bind(null, params))
}

Jetzt haben wir Animation! Wir erhöhen jedes Mal konstant um 1 Einheit, was wir eine lineare Animation nennen.

Sie können sehen, wie sich die Form linear von Punkt A nach Punkt B bewegt und dabei die gleiche konstante Geschwindigkeit zwischen den Punkten beibehält. Es ist funktional, aber es fehlt an Realismus. Der Start und Stopp ist abrupt.

Was wir wollen, ist, dass das Objekt beschleunigt (Ease-in) und abbremst (Ease-out), damit es das nachahmt, was ein reales Objekt tun würde, wenn Dinge wie Reibung und Schwerkraft ins Spiel kommen.

Eine JavaScript Easing-Funktion

Dies erreichen wir mit einem „kubischen“ Ease-in- und Ease-out-Übergang. Wir haben eine der Gleichungen aus Robert Penners Flash Easing-Funktionen modifiziert, um sie für unsere Zwecke geeignet zu machen.

function getEase(currentProgress, start, distance, steps) {
  currentProgress /= steps/2;
  if (currentProgress < 1) {
    return (distance/2)*(Math.pow(currentProgress, 3)) + start;
  }
  currentProgress -= 2;
  return distance/2*(Math.pow(currentProgress, 3)+ 2) + start;
}

Wenn wir dies in unseren Code einfügen, der eine kubische Ease ist, erhalten wir ein viel flüssigeres Ergebnis. Beachten Sie, wie die Karte zur Mitte des Raums beschleunigt und dann langsamer wird, wenn sie das Ende erreicht.

Fortgeschrittenes Easing mit JavaScript

Mit einem quadratischen oder sinusförmigen Ease können wir eine langsamere Beschleunigung erzielen.

function getQuadraticEase(currentProgress, start, distance, steps) {
  currentProgress /= steps/2;
  if (currentProgress <= 1) {
    return (distance/2)*currentProgress*currentProgress + start;
  }
  currentProgress--;
  return -1*(distance/2) * (currentProgress*(currentProgress-2) - 1) + start;
}
function sineEaseInOut(currentProgress, start, distance, steps) {
  return -distance/2 * (Math.cos(Math.PI*currentProgress/steps) - 1) + start;
};

Für eine schnellere Beschleunigung wählen Sie einen quintischen oder exponentiellen Ease.

function getQuinticEase(currentProgress, start, distance, steps) {
  currentProgress /= steps/2;
  if (currentProgress < 1) {
    return (distance/2)*(Math.pow(currentProgress, 5)) + start;
  }
  currentProgress -= 2;
  return distance/2*(Math.pow(currentProgress, 5) + 2) + start;
}

function expEaseInOut(currentProgress, start, distance, steps) {
  currentProgress /= steps/2;
  if (currentProgress < 1) return distance/2 * Math.pow( 2, 10 * (currentProgress - 1) ) + start;
 currentProgress--;
  return distance/2 * ( -Math.pow( 2, -10 * currentProgress) + 2 ) + start;
};

Anspruchsvollere Animationen mit GSAP

Eigene Easing-Funktionen zu schreiben kann Spaß machen, aber was ist, wenn Sie mehr Leistung und Flexibilität wünschen? Sie könnten benutzerdefinierten Code weiter schreiben oder eine leistungsfähigere Bibliothek in Betracht ziehen. Wenden wir uns für diesen Zweck der GreenSock Animation Platform (GSAP) zu.

Mit GSAP wird die Animation wesentlich einfacher zu implementieren. Nehmen Sie dieses Beispiel, bei dem die Karte am Ende hüpft. Beachten Sie, dass die GSAP-Bibliothek in der Demo enthalten ist.

Die Schlüsselfunktion ist moveCard.

function moveCard() {
  gsap.to(position, {
    duration: 2,
    ease: "bounce.out",
    x: position.xMax, 
    y: position.yMax, 
    onUpdate: function() {
      draw();
    },
    onComplete: function() {
      position.x = position.origX;
      position.y = position.origY;
    }
  });
}

Die Methode gsap.to ist es, wo die ganze Magie passiert. Während der zweisekündigen Dauer wird das position-Objekt aktualisiert und bei jeder Aktualisierung wird onUpdate aufgerufen, was das Neuzeichnen des Canvas auslöst.

Und wir reden nicht nur von Sprüngen. Es gibt unzählige verschiedene Easing-Optionen zur Auswahl.

Alles zusammenfügen

Sind Sie sich immer noch unsicher, welchen Animationsstil und welche Methode Sie in Canvas verwenden sollten, wenn es um Easing geht? Hier ist ein Pen, der verschiedene Easing-Animationen zeigt, einschließlich dessen, was GSAP bietet.

Sehen Sie sich mein Solitaire-Kartenspiel  an, um eine Live-Demo der Nicht-GSAP-Animationen zu sehen. In diesem Fall habe ich Animationen hinzugefügt, damit die Karten im Spiel beim Wechsel zwischen den Stapeln Ease-out und Ease-in machen.

Neben der Erzeugung von Bewegungen können Easing-Funktionen auf jedes andere Attribut angewendet werden, das einen von- und bis-Zustand hat, wie z. B. Änderungen der Opazität, Drehungen und Skalierungen. Ich hoffe, Sie finden viele Möglichkeiten, Easing-Funktionen zu verwenden, um Ihre Anwendung oder Ihr Spiel flüssiger aussehen zu lassen.