Eine Textwelle mit SVG und Text-Clipping animieren

Avatar of Zach Saucier
Zach Saucier am

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

Ich bin auf diese nette kleine Animation in einem Newsletter für Designer gestoßen. Leider habe ich die Quelle aus den Augen verloren, also gebt bitte Bescheid, wenn ihr sie erkennt! Sie ist von Martí Fenosa.

Darin scheint ein Textblock mit einem Farbwirbel in die Ansicht zu fließen und verschwindet dann auf die gleiche Weise, wie er gekommen ist. Es ist ein glatter Effekt, den ich mit Code nachbilden wollte.

Der Ansatz, den ich verfolgte, war, SVG-Text als Clipping-Pfad für einen SVG-Hintergrund zu verwenden. Wir müssen SVG-Text verwenden, da CSS derzeit nur dann Text-Clipping für die Animation des Hintergrunds erlaubt, wenn der Hintergrund eine GIF-Datei ist, was wir nicht tun werden.

Unsere erste Aufgabe ist es, einen Hintergrund aus verschiedenen SVG-Formen zu erstellen. Ovale Klumpen funktionieren ziemlich gut. Wichtig ist, die Größe der Zeichenfläche/Leinwand in der von Ihnen verwendeten Zeichenanwendung an die gleiche Abmessung anzupassen wie die viewBox, die das Endergebnis haben soll. (In Inkscape befindet sich diese Option im Reiter "Skalierung" der Dokumenteigenschaften.)

Das Ziel ist es, den Großteil der Zeichenfläche mit einer Vielzahl von Formen abzudecken. Ich habe festgestellt, dass es am besten aussieht, wenn sich einige der Formen überlappen.

Als Nächstes erstellen wir etwas Text in einem , gruppieren die Objekte, die den Hintergrund bilden, innerhalb eines -Elements und wenden einen CSS-clip-path auf diese Gruppe an. Zusammen sieht das ungefähr so aus:

  
  
    We are
    Creators
    +Innovators
  

  
  
    
    
  

An diesem Punkt erhalten wir nur einfachen Text, da wir uns noch nicht um die Hintergrundanimation gekümmert haben.

Was ist also mit dieser Animation? Wir können eine relativ einfache CSS-Animation wie diese verwenden:

/* Animate the background shapes */
#background path {
  animation: pulse 4s cubic-bezier(0.455, 0.030, 0.515, 0.955) infinite;

  /* Necessary to keep the SVG objects in place while scaling */
  transform-origin: 50% 50%;
  transform-box: fill-box;
}

@keyframes pulse {
  /* Rotating it along with the scale makes it a little bit more fancy */
  0%, 100% { transform: scale(0) rotate(33deg); }
  35%, 65% { transform: scale(1) rotate(0deg); }
}

Bisher gut.

transform-box: fill-box; wird derzeit nicht in Internet Explorer oder Edge unterstützt. Wenn Sie diese Browser unterstützen müssen, benötigen Sie eine JavaScript-Workaround-Lösung, wie diese hier.

Siehe den Pen
Animierter SVG-Text-Clipping-Effekt mit Textwellen – Teil 1
von Zach Saucier (@Zeaklous)
auf CodePen.

Wir könnten die Farben hartkodieren, indem wir Text oder einen Vektoreditor verwenden, aber es macht mehr Spaß, die Formen dynamisch zu färben. So etwa:

// Define an array of colors
const colors = ['#f5a147','#51cad8','#112b39'];
// Select the SVG paths
var blobs = document.querySelectorAll("path");

// Randomly apply colors to the SVG fill property
blobs.forEach(blob => {
  blob.style.fill = colors[Math.floor(Math.random() * colors.length)];
});

Um die Textwerte für jede Iteration zu ändern, müssen wir sie zuerst in den SVG-Clipping-Pfad aufnehmen.

  We are
  Creators
  +Innovators
  
  We are
  Movers
  +Shakers
  
  We are
  Stylish
  +Techy

Dann können wir entweder CSS oder JavaScript verwenden, um die Textzeilen in unserer bevorzugten Reihenfolge anzuzeigen. Leider können wir nicht jeden Abschnitt von mit einem -Element umgeben, da -Elemente nicht innerhalb eines clipPath funktionieren. Für diesen Beitrag teilen wir die Dinge in drei CSS-Animationen auf, eine für jede Gruppe von drei Pfaden:

/* Selects paths 1-3 */
#textClip text:nth-of-type(n + 1):nth-of-type(-n + 3) {
  animation: showFirst 12s infinite;
}

/* Selects paths 4-6 */
#textClip text:nth-of-type(n + 4):nth-of-type(-n + 6) {
  animation: showSecond 12s infinite;
}

/* Selects paths 7-9 */
#textClip text:nth-of-type(n + 7):nth-of-type(-n + 9) {
  animation: showThird 12s infinite;
}

@keyframes showFirst {
  0%, 33% {
    opacity: 1;
  }
  33.0001%, 100% { opacity: 0; }
}

@keyframes showSecond {
  33.0001%, 66% {
    opacity: 1;
  }
  0%, 33%, 66.0001%, 100% { opacity: 0; }
}

@keyframes showThird {
  66.0001%, 99.999% {
    opacity: 1;
  }
  0%, 66%, 100% { opacity: 0; }
}

Das erledigt die Aufgabe!

Siehe den Pen
Animierter SVG-Text-Clipping-Effekt mit Textwellen – Teil 2
von Zach Saucier (@Zeaklous)
auf CodePen.

Wie Claus Colloseus in den Kommentaren feststellte, funktioniert die obige und die folgende Demo nicht in Firefox aufgrund einer Mehrdeutigkeit in der CSS-Masking-Spezifikation: „Die Rohgeometrie jedes Kindelements, ausgenommen Rendering-Eigenschaften wie Füllung, Kontur, Konturbreite innerhalb eines clipPath, definiert konzeptionell eine 1-Bit-Maske… die die Silhouette der Grafik darstellt, die mit diesem Element verbunden ist.“ Firefox ignoriert alle Opazitätsänderungen innerhalb eines clipPath und zeigt somit alle drei gleichzeitig an. WebKit hingegen blendet Elemente mit einer Opazität von 0 innerhalb eines clipPath aus. Wer in diesem Fall richtig liegt, liegt nicht an mir, aber als Workaround sollten wir eine mask zusammen mit etwas fill anstelle des hier beschriebenen clipPath-Ansatzes verwenden. Wie die aktualisierte Demo zeigt, ist der grundlegende Ansatz derselbe, aber die CSS-Animation muss geringfügig angepasst werden, um die Funktionsweise von Masken zu berücksichtigen.

An diesem Punkt können wir ein wenig Spaß haben. Zum Beispiel können wir Hintergründe für einen anderen Effekt austauschen. Ich habe das Sternwerkzeug von Inkscape mit drei bis vier Spitzen verwendet, um einige zufällige Formen zu erzeugen (unter Verwendung des Zufallsparameters von Inkscape) und sie dann mit einer Palette von einem der vielen Farbpalettengeneratoren (ich habe Palx verwendet) gefärbt, um diese Version zu produzieren:

Siehe den Pen
Animierter SVG-Text-Clipping-Effekt mit Textwellen – Teil 3
von Zach Saucier (@Zeaklous)
auf CodePen.

Die Hintergründe müssen nicht den gesamten Hintergrund ausfüllen, je nach gewünschtem Effekt. Zum Beispiel könnten wir den Text mit einem Element duplizieren und den Text damit füllen, wie in dieser Demo zu sehen ist.

Oder wir könnten es mischen, indem wir die Hintergrundklumpen drehen, wie hier:

Siehe den Pen
Animierter SVG-Text-Clipping-Effekt mit Textwellen – Teil 5
von Zach Saucier (@Zeaklous)
auf CodePen.

Um die Farben für jedes neue Wortset zu ändern, könnten wir entweder CSS oder JavaScript für die Animation verwenden. Ich habe JavaScript verwendet (und die CSS-Animation, die die Textzeilen versteckte, in das JavaScript verschoben)

Siehe den Pen
Animierter SVG-Text-Clipping-Effekt mit Textwellen – Teil 6
von Zach Saucier (@Zeaklous)
auf CodePen.

Um den Text horizontal zu zentrieren, fügen Sie x="50%" text-anchor="middle" zu jedem -Element hinzu (Demo). Vertikales Zentrieren würde mehr manuelle Berechnungen erfordern, da wir mit einem mehrzeiligen Format arbeiten.

Eines der schönen Dinge an diesem Ansatz ist, dass er, da er SVG verwendet, standardmäßig responsiv ist!

PS Nachdem ich diesen Ansatz entwickelt hatte und nach dem ursprünglichen GIF-Autor suchte, stieß ich auf eine weitere Nachbildung von Martí Fenosa, der denselben Effekt mit einem anderen Ansatz erzielte. Schauen Sie sich seine Demo auch an, sie ist clever!