Werfen wir einen Blick darauf, wie man die CSS-Eigenschaft border-image mit animierten SVGs kombiniert, die sich um einen Rand bewegen. Dabei behandeln wir, wie man resizable, im Neuner-Schnitt animierte SVGs von Hand erstellt, die man nicht nur verwenden kann, um den Effekt nachzubilden, sondern um ihn zu seinem eigenen zu machen.
Hier ist, was wir machen

Das ist eigentlich Teil von The Skull, einem Capture-the-Flag-Rätsel, an dem ich arbeite und das darauf ausgelegt ist, die Interna von Arduino und seinem Mikrocontroller zu erforschen. Ich habe recherchiert, wie man einen Rand wie diesen animiert, konnte aber keine nützlichen Beispiele finden. Die meiste Recherche drehte sich um marching ants, aber leider funktioniert der stroke-dasharray-Trick nicht mit Totenköpfen, geschweige denn mit komplexeren Formen.
Also, im Sinne des Lernens und Teilens, blogge ich hier mit Ihnen darüber!
Sollen wir background oder border-image verwenden?
Zuerst wusste ich nicht einmal, dass border-image existiert. Ich versuchte, ein ::before Pseudoelement in meinem ersten Versuch zu verwenden und animierte seine background-position Eigenschaft. Das brachte mich bis hierher
Wie Sie sehen können, hat es funktioniert, aber um den Rand zu vervollständigen, wären mindestens acht verschiedene Elemente (oder Pseudoelemente) erforderlich. Es ist nicht ideal, das HTML so zu überladen.
Ich habe eine Frage in der israelischen Facebook-Gruppe für CSS-Entwickler gepostet, und alle wiesen mich auf die border-image-Eigenschaft hin. Sie tut genau das, was sie verspricht: Sie verwendet ein Bild (oder einen CSS-Gradienten) für den Rand eines Elements.
Um mit border-image zu arbeiten, müssen Sie ein Bild bereitstellen, das im Neuner-Schnitt verwendet wird (denken Sie an ein Tic-Tac-Toe-Feld über dem Bild). Jede dieser neun Regionen repräsentiert einen anderen Teil des Randes: oben, rechts, links und unten, jede der vier Ecken und dann die Mitte (die ignoriert wird).
Wenn wir zum Beispiel nur statische Totenköpfe wollten, könnten wir SVG-Muster nutzen, um den Totenkopf neunmal zu wiederholen. Zuerst definieren wir ein 24×24 Muster mit dem Pfad des Totenkopfs und verwenden dann dieses Muster als fill für ein 72×72 rect.
<svg version="1.1" height="72" width="72" xmlns="http://www.w3.org/2000/svg">
<defs>
<pattern id="skull-fill" width="24" height="24"
patternUnits="userSpaceOnUse">
<path d="..." fill="red"/>
</pattern>
</defs>
<rect fill="url(#skull-fill)" width="72" height="72" />
</svg>
Als nächstes definieren wir einen Rand und setzen das border-image auf das Ziel-Element.
.skulls {
border: 24px solid transparent;
border-image: url("https://skullctf.com/images/skull-9.svg") 24 round;
}
Und wir erhalten einen Rand aus Totenköpfen.
SVG-Animationen hinzufügen
Jetzt können wir diese Totenköpfe animieren! Es funktioniert, äh, größtenteils.
Die Idee ist, für jede Region im Randbild eine andere Animation zu erstellen. Zum Beispiel haben wir in der oberen linken Ecke einen Totenkopf, der von rechts nach links geht, während ein zweiter Totenkopf gleichzeitig von oben nach unten geht.
Wir animieren die transform-Eigenschaft für die Bewegung. Wir nutzen auch die <use> von SVG, um die Wiederholung der langwierigen <path>-Definition für jeden Totenkopf zu vermeiden.
<svg version="1.1" height="96" width="96" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<style>
@keyframes left {to {transform: translate(-32px, 0)}}
@keyframes down {to {transform: translate(0, 32px)}}
</style>
<defs>
<path id="skull" d="..." fill="red"/>
</defs>
<!-- Top-left corner: one skull goes left, another goes down -->
<use href="#skull" x="0" y="0" style="animation: down .4s infinite linear"/>
<use href="#skull" x="32" y="0" style="animation: left .4s infinite linear"/>
</svg>
Die SVG-Animationssyntax mag Ihnen bekannt vorkommen, denn anstelle einer SVG-spezifischen Syntax wie SMIL verwendet sie einfach CSS-Animationen. Cool, oder?
Das ist es, was wir bekommen.

Und wenn wir ein Gitter hinzufügen, können wir sehen, wie diese Animation auch einige der oberen und linken Ränder abdeckt.

Es beginnt beeindruckender auszusehen, nachdem wir die restlichen drei Kanten hinzugefügt haben und somit alle acht Regionen des Randbildes vollständig abgedeckt sind.
<svg version="1.1" height="96" width="96" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<style>
@keyframes left {to {transform: translate(-32px, 0)}}
@keyframes down {to {transform: translate(0, 32px)}}
@keyframes right {to {transform: translate(32px, 0)}}
@keyframes up {to {transform: translate(0, -32px)}}
</style>
<defs>
<path id="skull" d="..." fill="red"/>
</defs>
<!-- Top-left corner: one skull goes left, another goes down -->
<use href="#skull" x="0" y="0" style="animation: down .4s infinite linear"/>
<use href="#skull" x="32" y="0" style="animation: left .4s infinite linear"/>
<!-- Top-right corner: one skull goes up, another goes left -->
<use href="#skull" x="64" y="0" style="animation: left .4s infinite linear"/>
<use href="#skull" x="64" y="32" style="animation: up .4s infinite linear"/>
<!-- Bottom-left corner: one skull goes down, another goes right -->
<use href="#skull" x="0" y="32" style="animation: down .4s infinite linear"/>
<use href="#skull" x="0" y="64" style="animation: right .4s infinite linear"/>
<!-- Bottom-right corner: one skull goes right, another goes up -->
<use href="#skull" x="32" y="64" style="animation: right .4s infinite linear"/>
<use href="#skull" x="64" y="64" style="animation: up .4s infinite linear"/>
</svg>
Und das gibt uns eine vollständige Schaltung.

Zusammenfassend verwenden wir das gerade erstellte animierte SVG als border-image und erhalten das gewünschte Ergebnis.
Ich könnte den ganzen Tag damit spielen…
Nachdem ich das zum Laufen gebracht hatte, begann ich, mit den Animationseigenschaften zu experimentieren. Das ist einer der Vorteile der Verwendung von SVGs anstelle von GIFs: Die Art der Animation zu ändern, ist so einfach wie das Ändern einer CSS-Eigenschaft in der SVG-Quelldatei, und Sie sehen das Ergebnis sofort, ganz zu schweigen von den kleineren Dateigrößen (insbesondere bei Gradienten), voller Farbunterschützung und scharfer Skalierung.
Zuerst versuchte ich zu sehen, wie es aussehen würde, wenn ich die Animations-Timing-Funktion auf ease ändere.
Wir können die Totenköpfe auch zwischen Rot und Grün überblenden lassen.
Wir können die Totenköpfe sogar ihre Ausrichtung ändern lassen, während sie um die Highscore-Liste kreisen.
Gehen Sie zum JavaScript-Tab, wo Sie mit dem SVG-Quellcode herumspielen und es selbst ausprobieren können.
Der Elefant 🐘 im Raum (hüstel, Firefox)
Ich war sehr glücklich, als ich das zum ersten Mal zum Laufen brachte. Es gibt jedoch einige Einschränkungen, die Sie beachten sollten. Erstens und vor allem rendert Firefox aus irgendeinem Grund die Animation nicht an den Rändern des Rahmens, sondern nur an den Ecken.

Lustigerweise, wenn ich den SVG in ein GIF mit der gleichen Animation umwandle, funktionierte es perfekt. Aber dann hören die Ränder auf, sich unter Chrome zu animieren! 🤦♂️
Auf jeden Fall scheint es ein Browserfehler zu sein, denn wenn wir die Eigenschaft border-image-repeat auf stretch ändern, animiert Firefox die Ränder, aber das Ergebnis ist etwas eigenartig (obwohl es wahrscheinlich zum Thema der Seite passt).

Das Ändern des Werts von border-image-repeat auf space scheint auch zu funktionieren, aber nur, wenn die Breite des Elements kein ganzzahliges Vielfaches der Totenkopfgröße ist, was bedeutet, dass wir einige Lücken in der Animation bekommen.
Ich habe auch ein paar visuelle Probleme festgestellt, wenn die Containergröße kein Vielfaches der Patchgröße (in diesem Fall 32 Pixel) ist, wie z. B. winzige schwarze Linien auf den Totenköpfen. Ich vermute, das hat mit einem Rundungsfehler bei Fließkommazahlen zu tun. Es neigt auch dazu, beim Zoomen zu versagen.
Nicht perfekt, aber definitiv fertig! Wenn Sie die endgültige Version in Aktion sehen möchten, sind Sie eingeladen, sich die High Scores von The Skull-Seite anzusehen. Hoffentlich werden bald einige Ihrer Namen darauf stehen!
Ich wünschte, meine Kunden hätten das Budget dafür :) Grüße aus PL.
Danke! Ich wünsche mir das auch :)
Wahnsinn, ich werde meinen ganzen Hintergrund animieren.
Großartig! Bitte zeigen Sie mir das Ergebnis :)
Guter Trick und gut geschrieben, danke!
Könnten Sie bitte auf den "schmutzigen Trick zum Laden des obigen (Inline-)SVG" näher eingehen? Haben Sie ihn verwendet, weil URL-Fragmente bei einigen CSS-Eigenschaften nicht funktionieren? Ich frage, weil ich heute Morgen versucht habe,
cursormit einem URL-Fragment, das auf ein animiertes SVG (inline im Dokument) verwies, zu definieren, aber es wurde nicht gerendert. Meine Hauptmotivation war, zu prüfen, ob Browser Animationen rendern, die in einem externen SVG definiert sind.Ich habe versucht, Ihre Animation mit
marker-midzu implementieren, aber nicht mit viel Erfolg, undborder-imageist ohnehin eindeutig die richtige Methode.Guillaume!
Genau, wie hier erklärt. Haben Sie es herausgefunden oder brauchen Sie noch Hilfe dabei?
Hallo Uri,
Entschuldigung, ich kann nicht erkennen, wie der verlinkte Abschnitt zu meiner Frage passt.
Ich hoffte, Sie könnten erklären, warum Sie
Blob+createObjectURLverwenden, um den Wertborder-imagein den beiden CodePens dieses Abschnitts hier zuzuweisen.Ich habe diesen "Hack" bereits verwendet und konnte mich nicht erinnern, warum ich ihn brauchte. Es scheint, dass bestimmte CSS-Bildeigenschaften nicht einer URL zugewiesen werden können, die auf ein Fragment in der Seite zeigt, z. B.
url(#fragment), undelement(#fragment)wird derzeit nur von Firefox unterstützt. Ich denke, das ist die Antwort, auf die ich gewartet habe.Entschuldigung, ich habe Ihre Frage wahrscheinlich nicht richtig verstanden! Wenn ich mich recht erinnere, habe ich irgendwann auch
url(#fragment)ausprobiert, aber es funktionierte nicht. Es schien, dass der einzig sinnvolle Weg die Verwendung einer Blob-URL wäre, da weder Fragment- noch Daten-URLs für mich funktioniert hätten.Ich kannte
element(#fragment)nicht. Schön, etwas Neues zu lernen!Gut! Ich erinnere mich, vor etwa 10 Jahren ein paar Späße mit animierten SVG-Rändern auf meiner DA-Seite gemacht zu haben.
Tatsächlich habe ich gerade überprüft und es funktioniert immer noch im aktuellen mobilen Firefox und Chrome.
https://deviantart.com/fli-c/journal/pfft-SVG-journal-skin-367755371
Guten Tag, ich verwende viel einfachere Animationen in SVG für border-image. Ich habe eine Produktkarte, die kompliziert gezeichnet ist, und an ein oder zwei Stellen sind kleine blaue blinkende Linien. Wenn ich diese animiere, habe ich viele Verzögerungen auf meinem Computer, Handy und so weiter, als ob border-image die Leistung auffressen würde. Können Sie mir dabei helfen?
Hallo,
Ich versuche, Ihren benutzerdefinierten Randtrick zu replizieren, aber ich bleibe auf der ersten Ebene der SVG-Animation hängen – ich verstehe sie nicht wirklich. Wie leiten Sie das SVG zu Ihrem eigenen SVG-Upload-Symbol? Wie geben Sie es dann als GIF aus? Jede Hilfe wäre willkommen!
Danke