1 HTML-Element + 5 CSS-Eigenschaften = Magie!

0
39

Sagen wir, ich sagte dir, dass wir bekommen können die nachstehenden Ergebnisse mit nur einem HTML-element und fünf CSS-Eigenschaften für jeden. Kein SVG, keine Bilder (außer für den hintergrund auf der Wurzel ist es nur, um klar zu machen, dass unsere ein HTML element hat einige transparente Teile), kein JavaScript. Was würden Sie denken, dass beinhaltet?

Die gewünschten Ergebnisse.

Nun, dieser Artikel wird erklären, wie dies zu tun, und dann auch zeigen, wie die Dinge Spaß machen, indem einige Animationen.

CSS-ing Farbverlauf Strahlen

Der HTML-Code nur ein <div>.

<div class= “Strahlen” ></div>

In die CSS legen wir die Dimensionen dieses element, und wir müssen, um ihm einen hintergrund, damit wir es sehen können. Wir machen es auch kreisförmige Verwendung von border-radius:

.Strahlen {
Breite: 80vmin; Höhe: 80vmin;
border-radius: 50%;
background: linear-gradient(#b53, #f90);
}

Und… wir haben bereits vier von fünf Eigenschaften, um das Ergebnis zu erhalten unter:

Finden Sie den Stift, indem Sie thebabydino (@thebabydino) auf CodePen.

Also, was ist die fünfte? Maske mit einer sich wiederholenden-conic-gradient () – Wert!

Lassen Sie uns sagen, wir wollen 20 Strahlen. Das heißt, wir müssen reservieren, $p: 100%/20 der Kreis für ein Strahl und die Lücke nach.

Die Aufteilung der Scheibe in Strahlen und Lücken (live).

Hier halten wir die Lücken zwischen den Strahlen gleich der Strahlen (also das ist .5*$p entweder ein sonnenstrahl oder ein Leerzeichen), aber wir machen können, entweder von Ihnen breiter oder schmaler. Wir wollen eine abrupte änderung nach Beendigung der Stopp-position der opake Teil (den Strahl), so dass die Start-stop-position für den transparenten Teil (der Lücke) sollte gleich oder kleiner als es ist. Also, wenn das Ende der Stopp-position für den Strahl ist .5*$p, dann die Start-Stopp-position für die Kluft nicht größer sein. Es kann jedoch kleiner sein und das hilft uns, die Dinge einfach halten, weil es bedeutet, dass wir einfach null.

Wie wiederholen-conic-gradient() funktioniert (live).

$nr: 20; // Anzahl der Strahlen, die
$p: 100%/$nr; // Prozent der Kreis zugewiesen ray und die Lücke nach

.Strahlen {
/* das gleiche wie vorher */
Maske: die Wiederholung-conic-gradient(#000 0% .5*$p, transparent, 0% $p);
}

Beachten Sie, dass, anders als für lineare und radiale Farbverläufe, stop-Positionen für die konischen Verläufe nicht unitless. Sie müssen entweder Prozentwerte oder Winkel-Werte. Dies bedeutet, dass mit so etwas wie transparent 0 $p funktioniert nicht, wir müssen transparent 0% $p (oder 0deg statt 0%, es ist egal, welchen wir wählen, es kann einfach nicht sein, unitless).

Farbverlauf-Strahlen (live-demo, keine Edge Unterstützung).

Es gibt ein paar Dinge hier zu beachten, wenn es darum geht, zu unterstützen:

  • Edge nicht unterstützt Maskierung auf HTML-Elemente zu diesem Punkt, aber dieser ist wie aufgelistet In der Entwicklung und eine Flagge für ihn (das tut nichts für jetzt) hat bereits gezeigt, bis in about:flags.
    Das Aktivieren der CSS-Masking – flag im Rand.
  • Kegelschnitt-gradient() ist nur unterstützt von Blink-Browser hinter dem Experimental-Web-Platform-features fahne (die aktiviert werden kann, von chrome://flags / bzw. opera://flags). Unterstützung kommt Safari auch, aber bis das passiert, Safari basiert immer noch auf der polyfill, genau wie Firefox.
    Die Experimental-Web-Platform-features flag in Chrom.
  • WebKit-Browser benötigen noch das -webkit – Präfix für die Maske Eigenschaften für HTML-Elemente. Sie würden denken, dass ist kein problem, da wir mit der polyfill die sich auf -Präfix-frei sowieso, also, wenn wir mit dem polyfill, wir müssen -Präfix-frei, bevor das sowieso nicht. Leider, es ist ein bisschen mehr kompliziert als das. Das ist, weil -prefix-free funktioniert über die Erkennung von Auffälligkeiten, die scheitert in diesem Fall, denn alle Browser unterstützen die Maske unprefixed… auf SVG-Elemente! Aber wir sind mit Maske auf ein HTML-element hier, so sind wir in der situation, in der WebKit-Browser benötigen, das -webkit – Präfix, aber -prefix-free wird nicht fügen Sie es hinzu. Also ich denke, das bedeutet, dass wir brauchen, um es manuell hinzufügen:
    $nr: 20; // Anzahl der Strahlen, die
    $p: 100%/$nr; // Prozent der Kreis zugewiesen ray und die Lücke nach
    $m: Wiederholung-conic-gradient(#000 0% .5*$p, transparent, 0% $p); // Maske

    .Strahlen {
    /* das gleiche wie vorher */
    -webkit-mask: $m;
    Maske: $m;
    }

    Ich denke, das könnte man auch verwenden, Autoprefixer, auch wenn wir hinzufügen müssen -Präfix-frei sowieso, aber mit beiden nur für diese fühlt sich ein bisschen wie mit einer Schrotflinte, um eine fliege zu töten.

In der Animation hinzufügen

Eine Coole Sache über Kegelschnitt-gradient() unterstützt nativ in Blink-Browser ist, können wir mithilfe von CSS-Variablen in Ihnen (wir können nicht tun, wenn mit der polyfill). Und die CSS-Variablen können nun auch animiert, Blinken, Browser mit ein bisschen Houdini magic ” (wir müssen die Experimental-Web-Platform-features – flag aktiviert werden, aber wir müssen auch aktiviert es für native-conic-gradient() so zu unterstützen, dass sollte nicht das problem sein).

Im Hinblick auf die Vorbereitung unserer-code für die animation, ändern wir unsere Maskierung Verlauf so, dass es verwendet die variable alpha-Werte:

$m: Wiederholung-conic-gradient(
rgba(#000, var (–) 0% .5*$p,
rgba(#000, calc(1 – var (–))) 0% $p);

Wir registrieren Sie dann die alpha –eine benutzerdefinierte Eigenschaft:

CSS.registerProperty({
name: ‘–‘,
syntax: ‘<Anzahl>’,
initialValue: 1;
})

Und schließlich fügen wir in eine animation in der CSS:

.Strahlen {
/* das gleiche wie vorher */
animation: ein 2s linear infinite alternate;
}

@keyframes ein {{ –: 0 } }

Dies gibt uns das folgende Ergebnis:

Ray-alpha-animation (live-demo, funktioniert nur in der Blink-Browser mit der Experimental-Web-Platform-features flag).

Meh. Sieht nicht so toll aus. Wir konnten uns jedoch stellen sich die Dinge noch interessanter, indem mehrere alpha-Werte:

$m: Wiederholung-conic-gradient(
rgba(#000, var(–a0)) 0%, rgba(#000, var(–a1)) .5*$p,
rgba(#000, var(–a2)) 0%, rgba(#000, var(–a3)) “$p”);

Der nächste Schritt ist registrieren jeder der diese benutzerdefinierten Eigenschaften:

for(let i = 0; i < 4; i++) {
CSS.registerProperty({
name: `–${i}`,
syntax: ‘<Anzahl>’,
initialValue: 1 – ~~(i/2)
})
}

Und schließlich, fügen Sie die Animationen in der CSS:

.Strahlen {
/* das gleiche wie vorher */
animation: ein 2s infinite alternate;
animation-name: a0, a1, a2, a3;
animation-timing-function:
/* easings aus easings.net */
cubic-bezier(.57, .05, .67, .19) /* easeInCubic */,
cubic-bezier(.21, .61, .35, 1); /* easeOutCubic */
}

@for $i von 0 bis 4 {
@keyframes a#{$i -} {{–ein#{$i}: #{floor($i/2)} } }
}

Beachten Sie, da setzen wir die Werte der benutzerdefinierten Eigenschaften, die wir brauchen, um zu interpolieren, die floor () – Funktion.

Mehrere ray alpha-Animationen (live-demo, funktioniert nur in der Blink-Browser mit der Experimental-Web-Platform-features flag).

Es sieht jetzt ein bisschen interessanter, aber sicherlich können wir besser machen?

Lassen Sie uns versuchen, mit einem CSS-Variablen für die position “stop” zwischen ray und die Lücke:

$m: Wiederholung-conic-gradient(#000 0% var(–p), transparent, 0% $p);

Wir registrieren dann diese variable:

CSS.registerProperty({
name: ‘–p’,
syntax: ‘<Prozentsatz>’,
initialValue: ‘0%’
})

Und wir animieren von CSS durch eine keyframe-animation:

.Strahlen {
/* das gleiche wie vorher */
animation: p .5s linear infinite alternate
}

@keyframes p {{ –p: #{$p} } }

Das Ergebnis ist interessant, in diesem Fall:

Abwechselnd ray-Größe-animation (live-demo, funktioniert nur in der Blink-Browser mit der Experimental-Web-Platform-features flag).

Aber wir können noch etwas aufpeppen ein bisschen mehr durch Umklappen der ganze horizontal zwischen jeder iteration, so dass es immer umgedreht, der für die reverse lieben. Dies bedeutet nicht umgedreht, wenn –p geht von 0% bis zu $p und umgedreht, wenn –p geht zurück von $p auf 0%.

Die Art, wie wir flip ein element horizontal durch die Anwendung einer transform: scalex(-1) zu. Da wir wollen, dass diese flip angewandt werden, am Ende der ersten iteration und entfernt dann am Ende die zweite (rückwärts), wenden wir es in eine keyframe-animation sowie—in einem mit einem Schritte() timing-Funktion und Doppel-animation-Dauer.

$t: .5s;

.Strahlen {
/* das gleiche wie vorher */
animation: p $t linear infinite Alternative,
s 2*$t die Schritte(1) unendlich;
}

@keyframes p {{ –p: #{$p} } }

@keyframes s { 50% { transform: scalex(-1); } }

Jetzt haben wir endlich ein Ergebnis, das sieht eigentlich ziemlich cool:

Abwechselnd ray Größe der animation mit horizontal flip zwischen Iterationen (live-demo, funktioniert nur in der Blink-Browser mit der Experimental-Web-Platform-features flag).

CSS-ing Gradient Strahlen und Wellen

Zu erhalten, die Strahlen und Wellen führen, müssen wir hinzufügen, eine zweite Steigung, die Maske, dieses mal zu wiederholen-radial-gradient().

Wie repeating-radial-gradient() funktioniert (live).

$nr: 20;
$p: 100%/$nr;
$stop-Liste: #000 0% .5*$p, transparent, 0% $p;
$m: Wiederholung-conic-gradient($stop-Liste),
repeating-radial-gradient(closest-side, $stop-Liste);

.Strahlen-Wellen {
/* das gleiche wie vorher */
Maske: $m;
}

Leider mit mehreren Haltepositionen funktioniert nur in der Blink-Browser mit dem gleichen Experimentellen Web-Plattform-Funktionen – flag aktiviert. Und während das Kegelschnitt-gradient() polyfill deckt dieses für die Wiederholung-conic-gradient () – Teil im Browser unterstützen CSS-masking auf HTML-Elemente, aber nicht tragenden konischen Verläufe nativ (Firefox, Safari, Blink-Browser, ohne das flag), nichts behebt das problem für die Wiederholung-radial-gradient () – Teil in diesen Browsern.

Dies bedeutet, dass wir gezwungen sind, haben sich einige Wiederholungen in unserem code:

$nr: 20;
$p: 100%/$nr;
$stop-Liste: #000, #000 .5*$p, transparent 0%, transparent $p;
$m: Wiederholung-conic-gradient($stop-Liste),
repeating-radial-gradient(closest-side, $stop-Liste);

.Strahlen-Wellen {
/* das gleiche wie vorher */
Maske: $m;
}

Wir sind natürlich immer näher, aber wir sind noch nicht ganz dort:

Vermittler führen mit den beiden Masken-Ebenen (live-demo, keine Edge Unterstützung).

Um das Ergebnis zu erhalten, die wir wollen, müssen wir die Maske nutzen-composite-Eigenschaft, und legen Sie es ausschließen:

$m: Wiederholung-conic-gradient($stop-Liste) auszuschließen,
repeating-radial-gradient(closest-side, $stop-Liste);

Beachten Sie, dass Maske-composite-ist nur unterstützt in Firefox 53+ für jetzt, aber Edge sollte mitmachen, wenn es endlich unterstützt CSS-masking auf HTML-Elemente.

XOR-Strahlen und Wellen (live-demo, Firefox 53+ nur).

Wenn Sie denken, es sieht aus wie die Strahlen und die Zwischenräume zwischen den Strahlen sind nicht gleich, du hast Recht. Dies ist durch einen polyfill Problem.

In der Animation hinzufügen

Da die Maske-composite funktioniert nur in Firefox für jetzt und Firefox noch nicht unterstützt, konisch-gradient() nativ, wir können nicht CSS-Variablen innerhalb der sich wiederholenden-conic-gradient() (weil Firefox noch fällt zurück auf das polyfill für es und der polyfill keine Unterstützung für CSS-Variablen-Nutzung). Aber wir können Sie in der Wiederholung-radial-gradient() und auch wenn wir nicht animieren mit CSS keyframe Animationen, können wir so tun, mit JavaScript!

Denn wir sind nun dabei die CSS-Variablen innerhalb der repeating-radial-gradient(), aber nicht in der Wiederholung-conic-gradient() (da die XOR-Effekt funktioniert nur über Maske-composite, die nur unterstützt Firefox jetzt und Firefox nicht unterstützt konischen Verläufe nativ, also es fällt wieder auf das polyfill, die keine Unterstützung für CSS-Variablen-Nutzung), können wir nicht den gleichen $stop-Liste für beide Gradienten Schichten unserer Maske nicht mehr.

Aber wenn wir umschreiben unsere Maske ohne eine gemeinsame $stop-Liste sowieso, wir können diese Gelegenheit nutzen, verschiedene Stopp-Positionen für die zwei Gradienten:

// für den konischen Verlauf
$nc: 20;
$pc: 100%/$nc;
// für einen radialen Farbverlauf
$nr: 10;
$pr: 100%/$nr;

Die CSS-variable, die wir animieren ist ein alpha-eine, wie für die erste animation in der Strahlen-Fall. Außerdem stellen wir die –c0 –c1-Variablen, weil wir hier nicht haben, die mehrere Positionen pro Stopp und wollen wir, um Wiederholungen zu vermeiden, so viel wie möglich:

$m: Wiederholung-conic-gradient(#000 .5*$pc, transparent 0% $pc) ausschließen,
repeating-radial-gradient(closest-side,
var(–c0), var(–c0) .5*$pr,
var(–c1) 0, var(–c1) $pr);

body {
–: 0;
/* layout, Hintergründe und andere irrelevante Sachen */
}

.xor {
/* das gleiche wie vorher */
–c0: #{rgba(#000, var(–a))};
–c1: #{rgba(#000, calc(1 – var (–)))};
Maske: $m;
}

Die alpha-Variablen –eine ist die, die wir animieren Sie, hin und her (von 0 auf 1 und dann auf 0 zurück, wieder) mit ein wenig Vanille JavaScript. Wir beginnen mit der Einstellung einer Gesamtzahl von frames NF die animation geschieht über die aktuelle frame-index f und einen aktuellen animation Richtung dir:

const NF = 50;

lassen f = 0, dir = 1;

Innerhalb einer update() Funktion, wir aktualisieren die aktuelle frame-index f und dann setzen wir die aktuelle progress-Wert (f/NF) auf den aktuellen alpha –ein. Wenn f erreicht hat, entweder 0 NF, ändern wir die Richtung. Dann die update () – Funktion aufgerufen wird, wird wieder auf die nächste Aktualisierung.

(Funktion update() {
f += dir;

Dokument.Körper.Stil.setProperty (‘–‘, (f/NF).toFixed(2));

if(!(f%NF)) dir *= -1;

requestAnimationFrame(update)
})();

Und das ist alles für die JavaScript! Wir haben nun eine animierte Ergebnis:

Ripple alpha animation, linear (live-demo, funktioniert nur im Firefox-53+).

Dies ist eine lineare animation, der alpha-Wert –ein gesetzt werden, um den Fortschritt f/NF. Aber wir können ändern Sie die timing-Funktion, um etwas anderes, wie bereits in einem früheren Artikel schrieb ich über die Emulation CSS-timing-Funktionen mit JavaScript.

Zum Beispiel, wenn wir wollen, eine Leichtigkeit-in der Art von timing-Funktion, so setzen wir den alpha-Wert auf geschwindigkeitanimationsanfang(f/NF), anstatt nur f/NF, wo wir haben, dass geschwindigkeitanimationsanfang() ist:

Funktion geschwindigkeitanimationsanfang(k, e = 1.675) {
return Math.pow(k, e)
}

Das Ergebnis, wenn mit einer Leichtigkeit, timing-Funktion gesehen werden kann, in diesem Stift (funktioniert nur im Firefox-53+). Wenn du daran interessiert bist, wie wir haben diese Funktion, es ist alles erklärt in dem vorher verlinkten Artikel auf timing-Funktionen.

Die exakt gleiche Ansatz funktioniert für die easeOut () – oder der easeInOut():

Funktion easeOut(k, e = 1.675) {
1 zurück – Math.pow(1 – k, e)
};

Funktion easeInOut(k) {
zurück .5*(Math.sin((k – .5)*Math.PI) + 1)
}

Da wir mit JavaScript, wie auch immer, wir können die ganze Sache interaktiv, so dass die animation nur passiert beim klicken/Tippen Sie, zum Beispiel.

Um dies zu tun, fügen wir eine Anfrage-ID-variable (rID), welche zunächst null ist, aber dann nimmt der Rückgabewert von requestAnimationFrame() in der update () – Funktion. Dies ermöglicht es uns, stoppen Sie die animation mit einem stopAni () – Funktion, Wann immer wir wollen:

/* das gleiche wie vorher */

lassen rID = null;

Funktion stopAni() {
cancelAnimationFrame(rID);
rID = null
};

Funktion update() {
/* das gleiche wie vorher */

if(!(f%NF)) {
stopAni();
zurück
}

rID = requestAnimationFrame(update)
};

Auf klicken Sie auf, stoppen wir die animation, die ausgeführt werden können, stornieren Sie die animation Richtung dir und rufen Sie die update () – Funktion:

addEventListener(‘click’, e => {
wenn(rID) stopAni();
dir *= -1;
update()
}, false);

Da starten wir mit der aktuellen frame-index f von 0, wollen wir gehen in die positive Richtung NF auf den ersten Klick. Und da wir die Umkehrung der Richtung, auf jeden Klick, ergibt sich, dass der Initiale Wert für die Richtung muss -1 sein nun, so kommt er Umgekehrt, um +1 auf den ersten Klick.

Das Ergebnis all der oben genannten kann gesehen werden in diesem interaktiven Stift (funktioniert nur im Firefox-53+).

Wir könnten auch einen anderen alpha-variable für jeden stoppen, genau wie im Fall der Strahlen:

$m: Wiederholung-conic-gradient(#000 .5*$pc, transparent 0% $pc) ausschließen,
repeating-radial-gradient(closest-side,
rgba(#000, var(–a0)), rgba(#000, var(–a1)) .5*$pr,
rgba(#000, var(–a2)) 0, rgba(#000, var(–a3)) $pr);

In JavaScript haben wir das ease-in und ease-out-timing-Funktionen:

const TFN = {
“ease-in”: Funktion(k, e = 1.675) {
return Math.pow(k, e)
},
“ease-out”: function(k, e = 1.675) {
1 zurück – Math.pow(1 – k, e)
}
};

In der update () – Funktion, der einzige Unterschied zu den ersten animierten demo ist, dass wir uns nicht ändern, wird der Wert von nur einem CSS-variable—wir haben jetzt vier zu erledigen: –a0 –a1 –a2 –a3. Wir tun das in einer Schleife, über die Leichtigkeit-in-Funktion für diejenigen, die sich bei auch Indizes und die Leichtigkeit-out-Funktion für die anderen. Für die ersten beiden, die Fortschritte, die gegeben ist durch f/NF, während für die letzten beiden, die Fortschritte, die gegeben ist durch 1 – f/NF. Putting all dies in einer Formel, die wir haben:

(Funktion update() {
f += dir;

for(var i = 0; i < 4; i++) {
let j = ~~(i/2);

Dokument.Körper.Stil.setProperty(
`–${i}`,
TFN[i%2 ? “ease-out”: “ease-in’](j + Math.pow(-1, j)*f/NF).toFixed(2)
)
}

if(!(f%NF)) dir *= -1;

requestAnimationFrame(update)
})();

Das Ergebnis kann unten gesehen werden:

Mehrere ripple alpha-Animationen (live-demo, funktioniert nur im Firefox-53+).

Genau wie für die konischen Verläufe, können wir Sie auch animieren, die stop-position zwischen den opaken und den transparenten Teil der Abdeckung radial-gradient. Zu tun, verwenden wir eine CSS-Variablen-p für den Fortschritt dieser Stopp-position:

$m: Wiederholung-conic-gradient(#000 .5*$pc, transparent 0% $pc) ausschließen,
repeating-radial-gradient(closest-side,
#000, #000 calc(var(–p)*#{$pr}),
transparent 0, transparent $pr);

Der JavaScript-Code ist fast identisch mit der ersten alpha-animation, außer wir nicht update eine alpha-variable, sondern eine stop-Fortschritts-variable p und wir verwenden Sie einen ease-in-out Funktion:

/* das gleiche wie vorher */

Funktion easeInOut(k) {
zurück .5*(Math.sin((k – .5)*Math.PI) + 1)
};

(Funktion update() {
f += dir;

Dokument.Körper.Stil.setProperty(‘–p’, easeInOut(f/NF).toFixed(2));

/* das gleiche wie vorher */
})();

Wechselstrom-welligkeit Größe-animation (live-demo, funktioniert nur im Firefox-53+).

Wir können den Effekt noch interessanter, wenn wir einen transparenten Streifen, bevor die undurchsichtige und wir auch animieren, den Fortschritt der stop-position-p0, wohin wir gehen von diesem transparenten Streifen, der undurchsichtig:

$m: Wiederholung-conic-gradient(#000 .5*$pc, transparent 0% $pc) ausschließen,
repeating-radial-gradient(closest-side,
transparent, transparent calc(var(–p0)*#{$pr}),
#000, #000 calc(var(–p1)*#{$pr}),
transparent 0, transparent $pr);

In JavaScript müssen wir animieren Sie zwei CSS-Variablen: –p0 –p1. Wir verwenden eine einfache timing-Funktion für den ersten und einer Leichtigkeit-out für die zweite. Wir haben auch nicht in umgekehrter Richtung animation mehr:

const NL = 120,
TFN = {
“ease-in”: Funktion(k, e = 1.675) {
return Math.pow(k, e)
},
“ease-out”: function(k, e = 1.675) {
1 zurück – Math.pow(1 – k, e)
}
};

sei f = 0;

(Funktion update() {
f = (f + 1)%NF;

for(var i = 0; i < 2; i++)
Dokument.Körper.Stil.setProperty(`–p${i}`, TFN[ich ? “ease-out”: “ease-in”] (f/NF);

requestAnimationFrame(update)
})();

Das bringt uns zu einem ziemlich interessanten Ergebnis:

Doppel-ripple-Größe-animation (live-demo, funktioniert nur im Firefox-53+).