Ich habe neulich an einer Sache gearbeitet, bei der ein sichtbarer Timer benötigt wurde. Es gab auf dem Projekt bereits UI-Präzedenzfälle für diese Art von Timer. Die Leute wollten keine Zahlen nach unten ticken sehen; es war besser, einen "Balken" zu sehen, der von voll zu leer abnimmt. Ich erwähne das, weil es unzählige Möglichkeiten gibt, eine "Timer"-UI zu gestalten. Dies ist keine Erkundung all dieser Möglichkeiten (eine Suche auf CodePen wäre dort hilfreicher), sondern eine Erkundung der einen Methode, die für mich nützlich war.
Die Art von Timer, die ich brauchte, war das, was das Projekt als "Rundenzeit"-Balken bezeichnete. Eine Aktion wird ausgeführt. Sie kann eine Rundenzeit verursachen, und die meisten weiteren Aktionen sind blockiert, bis die Rundenzeit vorbei ist. Also war ein klarer roter Balken, der abläuft, die richtige UI. Er vermittelt ein Gefühl von Rhythmus und Fluss, bei dem man das Ende des Timers spüren und seine nächste Aktion timen kann.

linear-Animation, die den Balken auf Null schrumpfen lässt.Das einzurichten ist ziemlich einfach…
Geben wir uns ein Eltern/Kind-Konstrukt, nur für den Fall, dass wir den leeren Teil des Containers irgendwann stylen wollen.
<div class="round-time-bar">
<div></div>
</div>
Vorerst stylen wir nur den Balken darin.
.round-time-bar div {
height: 5px;
background: linear-gradient(to bottom, red, #900);
}
Das gibt uns einen schönen kleinen roten Balken, den wir für die Zeitanzeige verwenden können.
Als Nächstes müssen wir ihn zum Ticken bringen, aber hier müssen wir über die Funktionalität nachdenken. Ein Timer wie dieser muss wissen, wie lange er zählt! Wir können ihm diese Information direkt im HTML mitgeben. Das bedeutet nicht, dass wir JavaScript vermeiden – wir umarmen es. Wir sagen: "Hey JavaScript, gib uns bitte die Dauer als Variable, und wir kümmern uns von da an darum."
<div class="round-time-bar" style="--duration: 5;">
<div></div>
</div>
Tatsächlich ist dieser Weg sehr freundlich zu modernem DOM-Handling mit JavaScript. Solange diese --variable korrekt ist, kann dieses DOM-Element jederzeit neu gerendert werden, und wir können sicherstellen, dass das Design dies problemlos bewältigt. Wir werden eine Variante erstellen, die das tut.
Vorerst lassen wir die Animation ablaufen. Gute Nachrichten, es ist einfach. Hier ist ein Einzeiler-Keyframe
@keyframes roundtime {
to {
/* More performant than animating `width` */
transform: scaleX(0);
}
}
Wir können den Balken "zusammendrücken", da das Design des Balkens nichts hat, das beim horizontalen Skalieren gequetscht aussehen würde. Wenn wir etwas hätten, könnten wir die width animieren. Es ist nicht so schlimm, besonders da es nichts anderes umbrechen muss.
Jetzt wenden wir es auf den Balken an
.round-time-bar div {
/* ... */
animation: roundtime calc(var(--duration) * 1s) steps(var(--duration)) forwards;
transform-origin: left center;
}
Sehen Sie, wie wir die Variable --duration verwenden, um die Dauer der Animation festzulegen? Das macht die Hauptarbeit. Ich verwende sie auch, um die gleiche Anzahl von steps() festzulegen, damit sie "heruntertickt". Dieses "Ticken" könnte ein visuelles UI-Element sein, das Ihnen gefällt (mir gefällt es), aber es kommt auch der Idee entgegen, dass JavaScript diesen Balken jederzeit neu rendern könnte, und das Ticken macht es weniger wahrscheinlich, dass Sie es bemerken. Ich habe eine Ganzzahl für den Dauerwert verwendet, damit er diese Doppelfunktion erfüllen kann.
Wenn Sie jedoch eine flüssige Animation wünschen, könnten wir das als Variante machen, wie zum Beispiel:
<div class="round-time-bar" data-style="smooth" ... />
Dann nicht die Schritte machen
.round-time-bar[data-style="smooth"] div {
animation: roundtime calc(var(--duration) * 1s) linear forwards;
}
Beachten Sie, dass wir auch eine linear-Animation verwenden, was für einen Timer sinnvoll zu sein scheint. Die Zeit verlangsamt sich, sozusagen, nicht. Oder tut sie das? Egal, das ist Ihre Entscheidung. Wenn Sie einen Timer möchten, der an bestimmten Punkten zu beschleunigen oder zu verlangsamen scheint, legen Sie los.
Wir können die gleiche API, die auf Datenattributen basiert, für Variationen wie Farbvariationen verwenden
.round-time-bar[data-color="blue"] div {
background: linear-gradient(to bottom, #64b5f6, #1565c0);
}
Und eine letzte Variante ist, jede "Sekunde" eine feste Breite zu geben. So wird ein 10-Sekunden-Timer buchstäblich länger aussehen als ein 5-Sekunden-Timer
.round-time-bar[data-style="fixed"] div {
width: calc(var(--duration) * 5%);
}
Hier ist die Demo
Beachten Sie den kleinen Trick dort, um CSS-Animationen neu zu starten.
Oh, und hey, ich weiß, es gibt ein <meter>-Element, das vielleicht etwas semantischer ist, aber es bringt seine eigene UI mit, die nicht so animierbar ist, wie ich es hier wollte – zumindest nicht, ohne dagegen anzukämpfen. Aber ich frage mich, ob es zugänglicher ist? Kündigt es seinen aktuellen Wert auf nützliche Weise an? Wäre es ein zugänglicheres Timer, wenn wir einen <meter> in Echtzeit mit JavaScript aktualisieren würden? Wenn jemand es weiß, kann ich hier eine Lösung verlinken.
Erfordert die Verwendung von Style nicht eine CSP, die Inline-Styles erlaubt (was, soweit ich weiß, nicht empfohlen wird)?
Ich gehe davon aus, dass Sie das tun könnten
und fügen Sie
20secdurationzur Klassennamenliste fürdiv.round-time-barhinzu.Könnten Sie auch
data-duration=20verwenden undvar(--duration)zuattr(data-duration)ändern?Das Element
<progress>ist möglicherweise semantisch korrekter als<meter>, ich bin mir nicht sicher… beide sind sicherlich angemessener als ein<div>.Und
<progress>kann in CSS gestylt werden. Das Animieren des Werts müsste jedoch wahrscheinlich in JavaScript erfolgen (durch Manipulation seinesvalue-Attributs).meterwird für assistierende Technologien alsprogressbarangekündigt. Der aktuelle Wert wird zusammen mit dem Minimal- und Maximalwert angegeben. Die UI-Komponente hier ist generisch und würde einige ARIA-Attribute benötigen, um das Verhalten zu imitieren. Ich weiß jedoch nicht wirklich, wie es von den Geräten gehandhabt wird. Auf jeden Fall brauchen wir flexiblere Styling-Optionen für native UI-Elemente!Ich war neugierig, wie schwierig es wäre, den Balken inkrementell zu gestalten und gleichzeitig flüssig zwischen den Sekunden zu animieren. Es stellt sich heraus, dass es ziemlich einfach ist. Anstatt die Anzahl der Sekunden mit einer Variable festzulegen, wird die Anzahl der Sekunden durch die Anzahl der Kind-Objekte bestimmt, die Sie in den Container legen. Jedes davon hat eine Animation mit einer Verzögerung von
n-1 Sekunden, und der Container ist so eingestellt, dass er sie mit Flexbox in umgekehrter Reihenfolge anzeigt.Link, falls jemand interessiert ist
Das ist super.
Sehr schön!
Danke Chris Coyier.
Ich suche seit Tagen danach.
Ich würde diese Timer gerne zu einer von mir erstellten Bildergalerie hinzufügen, damit sie gleichzeitig mit den Folien laufen, ähnlich wie bei Instagram Stories. Aber ich weiß nicht, wie ich das zum Laufen bringen kann.
Ich würde mich über Hilfe freuen.
Ich bin neu hier.
Nochmal vielen Dank.
Gibt es eine Möglichkeit, die Animation umzukehren? Um den farbigen Timer-Balken von links nach rechts füllen zu lassen, anstatt ihn verschwinden zu lassen?