Animate to Different End States Using One Set of CSS Keyframes

Avatar of Ana Tudor
Ana Tudor am

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

Ich habe kürzlich eine reine CSS-Live-Coding-Animation einer zufälligen Regenbogen-Partikel-Explosion erstellt. Es gibt eine Quelle in der Mitte des Bildschirms, und Regenbogen-Partikel schießen mit unterschiedlichen Geschwindigkeiten zu verschiedenen Zeitpunkten heraus und verblassen dann. Es mag so aussehen, als ob dies viel Arbeit und Code erfordert, aber es ist etwas, das ich ziemlich schnell und mit nur 30 Zeilen SCSS gemacht habe.

GIF der Partikel-Explosionsanimation.

Diese Abhandlung soll einen besonders coolen Trick zeigen: Es gibt nur einen Satz von Keyframes, der verwendet wird, um all diese Partikel auf dem Bildschirm zu bewegen! Es gibt einen zweiten, der für das Ausblenden verantwortlich ist. Aber obwohl sie an völlig unterschiedlichen Positionen auf dem Bildschirm enden, ist nur ein Satz von Keyframes dafür zuständig.

Schauen wir mal, wie das alles funktioniert!

Struktur

Hier passiert nicht viel. Wir fügen einfach 400 Partikel in das body-Element ein. Ich habe Haml verwendet, weil ich finde, dass es die einfachste Möglichkeit bietet, zu schleifen, ohne überhaupt eine Schleifenvariable zu benötigen, die ich sowieso nicht brauche. Beachten Sie, dass es reine persönliche Präferenz ist. Ich neige dazu, den Präprozessor zu wählen, der mir mit dem geringsten Code das gewünschte Ergebnis liefert, denn je weniger ich schreiben muss, desto besser. In diesem speziellen Fall ist es Haml. Aber letztendlich funktioniert jeder Präprozessor, der es Ihnen ermöglicht, alle .particle-Elemente in einer Schleife zu generieren, einwandfrei.

- 400.times do
  .particle

Grundlegende Stile

Das erste, was wir tun, ist, unsere Partikel zu dimensionieren und absolut zu positionieren. Ich habe mich entschieden, sie als 4x4 Quadrate zu gestalten, da ich einen pixeligen Look anstrebte.

$d: 4px;

.particle {
  position: absolute;
  width: $d; height: $d;
}

Zufällige Positionierung auf dem Bildschirm

Wir durchlaufen diese 400 Partikel (beachten Sie, dass die Zahl in der @for-Schleife im SCSS mit der Zahl übereinstimmen muss, die wir in der Haml-Schleife verwendet haben) und verschieben sie an zufälligen x,y-Punkten auf dem Bildschirm, wobei x zwischen 1vw und 100vw und y zwischen 1vh und 100vh liegt. random(100) liefert uns zufällige ganze Zahlen zwischen 1 und 100, beide einschließlich.

Gleichzeitig geben wir diesen Partikeln auch unterschiedliche zufällige Hintergründe, damit wir sie sehen können. Wir verwenden das hsl()-Format, da es hier am praktischsten ist. random(360) deckt das gesamte Farbrad ab und liefert uns zufällige Werte zwischen 1 und 360.

Farbtonskala von 0 bis 360.

Dann maximieren wir die Sättigung (100%) und stellen eine Helligkeit über 50% (in diesem Fall 65%) ein.

.particle {
  /* same styles as before */

  @for $i from 0 to 400 {
    &:nth-child(#{$i + 1}) {
      transform: translate(random(100)*1vw, random(100)*1vh);
      background: hsl(random(360), 100%, 65%);
    }
  }
}

Wir können jetzt unsere Partikel über den gesamten Bildschirm verteilt sehen

Siehe den Pen von thebabydino (@thebabydino) auf CodePen.

Sie rufen Scrollbalken hervor, also setzen wir overflow: hidden auf dem Root-Element. Wir geben ihm auch einen dunklen background, damit wir unsere hellen Regenbogenpartikel besser sehen können

html {
  overflow: hidden;
  background: #222;
}

Auf diese Weise erhalten wir einen hübschen Nachthimmel

Siehe den Pen von thebabydino (@thebabydino) auf CodePen.

Animation

Der nächste Schritt ist, diese Partikel zu animieren und sie aus der Mitte des Bildschirms schießen zu lassen. Das bedeutet, dass unsere Animation am Punkt 50vw,50vh beginnt

@keyframes shoot {
  0% { transform: translate(50vw, 50vh); }
}

Wir geben keinen finalen (100%) Keyframe an. Wenn dieser nicht angegeben ist, wird er automatisch aus den Stilen generiert, die wir auf die animierten Elemente gesetzt haben – in unserem Fall sind das die zufälligen Translationen, die für jedes einzelne Partikel unterschiedlich sind.

Wir möchten, dass die Bewegung der Partikel anfangs schnell und dann langsam ist, was bedeutet, dass wir eine ease out-Art von Timing-Funktion verwenden müssen. Wir können einfach die schlichte ease-out-Funktion verwenden oder eine fortgeschrittenere (ich gehe zu easings.net dafür). Dann geben wir unserer animation eine Dummy-Dauer von 3s und lassen sie sich unendlich wiederholen.

.particle {
  /* same styles as before */
  animation: shoot 3s ease-out infinite;
}

Wir erhalten das folgende Ergebnis

Siehe den Pen von thebabydino (@thebabydino) auf CodePen.

Die Partikel schießen in verschiedene Positionen in der Ebene, genau wie wir es wollten. Aber sie animieren sich alle gleichzeitig, was nicht das ist, was wir wollen. Die erste Korrektur ist also, jedem von ihnen eine andere, zufällige Animationsdauer zwischen 1s und 3s innerhalb der Schleife zu geben

.particle {
  /* same styles as before */

    @for $i from 0 to 400 {
        $t: (1 + .01*random(200))*1s;

        &:nth-child(#{$i + 1}) {
            /* same styles as before */
            animation-duration: $t;
        }
    }
}

Das ist schon viel besser

Siehe den Pen von thebabydino (@thebabydino) auf CodePen.

Dann geben wir jedem Partikel eine zufällige negative Verzögerung zwischen 0% und 100% seiner animation-duration ($t) im Absolutwert

.particle {
  /* same styles as before */

    @for $i from 0 to 400 {
        $t: (1 + .01*random(200))*1s;

        &:nth-child(#{$i + 1}) {
            /* same styles as before */
            animation-delay: -.01*random(100)*$t;
        }
    }
}

Siehe den Pen von thebabydino (@thebabydino) auf CodePen.

Schließlich möchten wir nicht, dass die Partikel einfach verschwinden, also fügen wir eine zweite Animation hinzu (mit der gleichen Dauer und der gleichen Verzögerung), um sie auszublenden

.particle {
  /* same styles as before */
  animation: shoot 0s ease-out infinite;
  animation-name: shoot, fade;
}

@keyframes fade { to { opacity: 0; } }

Wir haben nun das Endergebnis!

Siehe den Pen von thebabydino (@thebabydino) auf CodePen.