Der folgende Text ist ein Gastbeitrag von Ryan Scherf. Ryan hat einen raffinierten Weg gefunden, Avataren grobe, unebene, abwechslungsreiche Kanten zu geben. So als wären sie mit einer Schere ausgeschnitten worden, und zwar von jemandem, der nicht besonders gut mit Scheren umgehen kann. Das Schöne daran ist, dass es sich von Natur aus um eine progressive Enhancement-Technik handelt und nur mit CSS realisiert werden kann.
Mit einer kreativen und unterhaltsamen Marke wie Quirky denken wir ständig darüber nach, wie wir diese Ausstrahlung ins Web bringen können. Auf der gesamten Website gibt es bei einigen Elementen einen „handgezeichneten“ Look. Ohne die Verwendung vieler Bilder ist es sehr schwierig, diese handgezeichnete Anmutung zu erzielen. Mit etwas leichter Trigonometrie und sehr grundlegenden Kenntnissen von CSS `clip-path` können wir dies mit relativer Leichtigkeit und guter Performance erreichen.

Warum keine Bildmasken verwenden?
Zum Beispiel eine Maske, die in SVG definiert ist
img {
mask: url(mask.svg) top left / cover;
}
Die mask-Eigenschaft kann auf externe SVGs oder auf im Dokument per ID definierte SVGs verweisen.
Aber was ist, wenn Sie für jeden einzelnen angezeigten Avatar eine einzigartige Form wünschen, nicht die gleiche Form? Sie könnten programmatisch viele verschiedene SVG-Formen generieren, um sie anzuwenden. Aber wir können dasselbe erreichen und diese mathematische Generierung erzielen, indem wir clip-paths mit (S)CSS generieren.
Wie ist die Browserunterstützung?
Die Browserunterstützung für clip-path, wenn es mit einem Formwert wie polygon() verwendet wird, ist Chrome 24+, Safari 7+, Opera 25+, iOS 7.1+, Android 4.4+. Firefox unterstützt clip-path nur mit dem in SVG definierten Pfad (das werden wir behandeln). Noch keine Unterstützung in IE.
Sie müssen -webkit-clip-path verwenden, da dies die einzige Möglichkeit ist, wie es derzeit unterstützt wird, aber wahrscheinlich am besten, auch clip-path dort einzubringen. Wenn IE oder Firefox dies auf diese Weise unterstützen, wird es wahrscheinlich ohne Präfix sein.
Clipping-Pfade im Überblick
Es gibt verschiedene Formwerte, die Sie für CSS-Clipping verwenden können, aber in unserem Fall ist die polygon-Form am besten geeignet, da sie uns die meisten Punkte und Flexibilität bietet, um unseren handgezeichneten Effekt zu erzeugen.
Sie übergeben polygon() eine Liste von X-, Y-Punktwerten, wie z. B.: <x0> <y0>, <x1> <y1>, ... <xn> <yn>. Dies zeichnet einen Pfad um Ihre Punkte **in der Reihenfolge** und schneidet alle Inhalte **außerhalb** der neu erstellten Form aus.
/*
This will create a Hexagon, with the first
point being the top tip of the shape
*/
.hexagon {
clip-path: polygon(50% 0, 100% 25%, 100% 75%, 50% 100%, 0 75%, 0 25%);
}
Hier ist dieses einfache Beispiel in Aktion
Siehe den Pen Hexagon with clip-path von Chris Coyier (@chriscoyier) auf CodePen.
Keine beängstigende Mathematik
Unser Sechseck ist ziemlich cool, aber es erzeugt noch keinen wirklich skizzenhaften Effekt. Es ist ziemlich starr – zu wenige Linien. Der beste Weg, eine handgezeichnete Form zu betrachten, ist eine Reihe von kleinen Linien, die zwei Punkte verbinden. Je mehr Punkte wir haben, desto mehr kurze Linien erstellen wir. Tatsächlich könnten wir mit genügend Punkten eine polygon-Form erstellen, die so glatt ist, dass sie eine circle nachahmt.
Hier ist ein Beispiel für die Verwendung von 200 Punkten
Siehe den Pen 200 Points von Chris Coyier (@chriscoyier) auf CodePen.
Woher kommen die Punkte?
Hier kommt ein wenig Mathematik ins Spiel. Haben Sie vielleicht Trigonometrie in der High School belegt? Eine der grundlegenden Ideen, die Sie in diesem Kurs lernen, betrifft den **Einheitskreis**. Grundsätzlich gibt es eine feste Formel (unter Berücksichtigung von Pi), mit der jede Anzahl von Punkten um einen Kreis erzeugt werden kann.

Wenn wir unsere Segmente verbinden würden, erhielten wir eine Form, die aussieht wie

Immer noch etwas steif, aber auch etwas handgezeichneter.
Mehr Punkte!
Wir wissen, wie man Sechsecke und Kreise mit clip-path: polygon() erstellt, also wie bekommen wir ihn dazu, handgezeichnet auszusehen?
- Passen Sie die Anzahl der Punkte an (je mehr es gibt, desto kürzer sind die Segmentlängen)
- Fügen Sie einige X- und Y-Varianten hinzu (damit die Segmente nicht gleichmäßig sind)
Lassen Sie uns das in SCSS einbringen und eine Funktion erstellen, die die schmutzige Arbeit für uns erledigt. Wir werden verwenden
random()cos()sin()
Die relevanteste Mathematik ist
/*
To generate an arbitrary points on
the unit circle at angle t
*/
$x: cos(t);
$y: sin(t);
Und das in die richtige Syntax zu bringen, sieht so aus
$w: 160px // Avatar width
$n: 60; // Number of points on the circle
@function sketchAvatar() {
$points: ();
@for $i from 0 through $n {
$points: append($points, ($w / 2) * (1 + cos((2 * pi() * $i / $n))) ($w / 2) * (1 + sin((2 * pi() * $i / $n))), comma);
}
@return $points;
}
Das ist ein bisschen knifflig. Was passiert, ist, dass wir oben in der Mitte unserer Form beginnen und eine Liste von Punktesätzen um den Kreis für 60 gleichmäßig verteilte Punkte erzeugen.
Alles zusammen mit Variationen
Der obige Code erzeugt immer noch recht langweilige und gleichmäßige Polygone, daher müssen wir Varianz hinzufügen. Alles, was wir tun müssen, ist, die Punkte in beliebige Richtungen anzupassen, um das gewünschte Offset-Gefühl zu erzielen. Die `$lower`- und `$upper`-Variationszahlen können je nach gewünschtem Aussehen fast alles sein.
$w: 120px; // Overall width
@function sketchAvatar() {
$n: 60; // Number of points
$lower: -80; // Lower variance
$upper: 80; // Upper variance
$points: ();
@for $i from 0 through $n {
$points: append($points, ($w / 2) * (1 + cos((2 * pi() * $i / $n))) + (rand($lower, $upper) / 100) ($w / 2) * (1 + sin((2 * pi() * $i / $n))), comma);
}
@return $points;
}
Wir haben es geschafft! Skizzenhafte, einzigartige Avatare mit CSS clip-path: polygon()
Siehe den Pen Sketchy Avatars von Chris Coyier (@chriscoyier) auf CodePen.
Funktioniert es auch in Firefox?
Chris hier! Ich dachte mir, da Firefox dies auf diese Weise nicht unterstützt, aber die SVG-Syntax unterstützt, könnten wir es quasi polyfillen.
.avatar {
clip-path: polygon( ... ) /* Firefox: nope */
clip-path: url(#clip); /* Firefox: yep */
}
Also habe ich für jeden Avatar…
- Die Polygonpunkte im `content`-Attribut eines Pseudo-Elements (eines Elements mit einem gültigen Pseudo-Element wie dem übergeordneten Div) in CSS ausgeben
- Diesen Wert mit JavaScript extrahiert
- Die Punkte in das SVG-Format umformatiert (z. B. keine „px“)
- Ein neues
<svg>mit einem<clipPath>pfad eingefügt, der bereit ist
$(".user").each(function(i) {
var path = window.getComputedStyle(this, ':after').getPropertyValue('content');
// clean house
svgPolygonPoints =
path
.replace(/px/g, "")
.replace(/polygon/, "")
.replace(/\(/, "")
.replace(/\)/, "")
.replace(/\;/g, "")
.replace(/"/g, "")
.replace(/\'/g, "");
// To get this to actually work, create a <div> instead with this inside, see below.
var svg = $("<svg width='0' height='0'>")
.append("<defs><clipPath id='clip-" + (i+1) +"'><polygon points='" + svgPolygonPoints +"' /></clipPath></defs>");
$("body").append(svg);
});
Es funktioniert nicht! haha. Selbst wenn man einen Neuzeichnen erzwingt, mag es das injizierte SVG aus irgendeinem Grund einfach nicht. Schauen Sie sich Amelias Lösung an
Es ist im Grunde so etwas wie
.user:nth-child(1) {
clip-path: polygon(120.04px 60px ...);
}
wird zu
<svg width="0" height="0">
<defs>
<clippath id="clip-1">
<polygon points="120.04 60, ... "></polygon>
</clippath>
</defs>
</svg>
Interessant, aber immer noch zu kompliziert für einen Effekt, den man leicht mit transparenten Bildern erzielen kann.
Aber wenn alle Avatare einheitlich sein sollen, können Sie wirklich erwarten, dass alle Ihre Benutzer transparente Bilder hochladen, die das Bild korrekt maskieren? Möchten Sie sich damit herumschlagen, sicherzustellen, dass jedes Mal, wenn Sie Ihr eigenes Avatar hochladen, es so maskiert ist, wie es sein soll? Diese Lösung ist tatsächlich viel bequemer.
Ich stimme zu... ein interessantes Proof of Concept... aber komplex... für die aktuelle Zeit für vollständige Cross-Browser-Unterstützung wären standardmäßige transparente Bilder am besten... aber für die Zukunft ist dies etwas, das man für die Zukunft in Betracht ziehen kann...
Dies und auch CSS-Masken... sehen vielversprechend aus... aber wieder unterstützt Firefox nur Inline-SVG als Maskenquelle, während die anderen (Chrome, Opera, Safari) eine Bildmaske im PNG- oder JPG-Format verwenden können... und wieder keine Unterstützung in IE... (Quelle: http://caniuse.com/#feat=css-masks ) ...
Interessanter Beitrag... danke fürs Teilen...
Ein möglicher Anwendungsfall dafür wäre, die gleichen erstellten Polygone als CSS-Form auf dem Bild zu verwenden, um Text darum herumfließen zu lassen, was mit einem transparenten Bild nicht möglich ist.
So zum Beispiel
Siehe den Pen MYYWrg von Karsten Buckstegge (@MrBambule) auf CodePen.
Ich mag das Comeback von CSS Tricks hier. Eine Weile lang wurde es hier ziemlich ernst, nicht mehr so viele unterhaltsame, aber nur vage nützliche Artikel. Gut, dass die Tricks zurück sind! :)
Es funktioniert nicht, weil Sie JQuery verwenden. JQuery weiß nicht, wie man Elemente im SVG-Namensraum erstellt oder welche Elemente im SVG-Namensraum sein sollten. Das bedeutet, dass es viele Elemente für Sie erstellt, die in Ihrem DOM-Inspektor korrekt aussehen – sie haben die richtigen Tag-Namen –, aber sie sind eigentlich alle
HTMLUnknownElementim DOM. Und so können Sie sie tatsächlich nicht als SVG-Inhalt verwenden.Im Gegensatz dazu wird beim Kopieren und Einfügen dieses Markups in eine separate Datei die Datei vom HTML5-Parser gelesen, der alle <svg>-Elemente und ihre Kinder als eben
SVGElements erkennt.Sie haben zwei Möglichkeiten
document.createElementNS("www.w3.org/2000/svg", "svg")(und das Gleiche für ihre Kinder) zu erstellen.Ich verwende hier Option 2. Sie lässt den Clip-Pfad in Firefox funktionieren
http://codepen.io/AmeliaBR/pen/qEBxXW
Schön! Ich werde das als das Wichtigste abhaken, was ich heute gelernt habe.
... Habe auch gerade den Pen aktualisiert, so dass er nur die SVG-Elemente injiziert, wenn sie tatsächlich verwendet werden.
Fast, jedenfalls. Er erstellt kein SVG, wenn die endgültige Funktion des Clip-Path-Polygons verwendet wird (hypothetisch bisher) oder wenn die Webkit-Clip-Path-Eigenschaft erkannt wird (Chrome oder Opera). Aber er erstellt sie immer noch für Internet Explorer, der die Basis-URL-Form von clip-path als gültige Stil-Deklaration erkennt, sie aber nicht auf Nicht-SVG-Elemente anwendet.
Das ist ziemlich cool. Leider werden 99,9 % der Benutzer nicht einmal bemerken oder sich darum kümmern, dass die Ränder anders aussehen. Daher könnten Sie es genauso gut auf einfache Weise mit Bildern/SVG machen.
Schön. Sehr interessant, leider war ich noch nie gut in Mathe, aber es sieht nicht schwierig aus.
Danke fürs Teilen.
svgPolygonPoints ist zum globalen window-Objekt hinzugefügt. Nicht sehr schön.
Übrigens, falls Sie es nicht wissen, es gibt einen Cross-Browser-Clip-Path-Generator http://cssplant.com/clip-path-generator
Oder Sie könnten es mit http://bennettfeely.com/clippy versuchen *hust* *hust*
Schöner Beitrag, gute Kommentare. Ich liebe *kalkulierte Bilder*, besonders wenn Trigonometrie und Zufälligkeit ins Spiel kommen.
Ich glaube nicht, dass das unter Windows 8 in Chrome funktioniert. Ich habe einfach ein Bild über das andere auf Codepen gezogen und es wurde identisch überlagert.
Geliebt... schöne Codierung... du machst es einfach nach so einer Erklärung!