HomeDesignerScript Clock Progress Script Clock Progress འᴉⱫզվ Ⱥℓąʍʂվąհ December 15, 2023 0 0 5 10 15 20 25 30 35 40 45 50 55 0 5 10 15 20 25 30 35 40 45 50 55 12 1 2 3 4 5 6 7 8 9 10 11 CSS * { border: 0; box-sizing: border-box; margin: 0; padding: 0; } :root { --hue: 223; --bg: hsl(var(--hue),10%,5%); --fg: hsl(var(--hue),10%,90%); --primary: hsl(var(--hue),90%,50%); --trans-dur: 0.3s; font-size: calc(16px + (32 - 16) * (100vw - 320px) / (2560 - 320)); } .clock { --hue1: 343; --hue2: 33; --hue3: 223; --hOffset: 0; --mOffset: 0; --sOffset: 0; display: block; margin: auto; width: 16em; height: 16em; } .clock line { stroke: hsl(var(--hue),10%,40%); transition: stroke var(--trans-dur) ease-in-out; } .clock text { fill: hsl(var(--hue),10%,40%); font-weight: 700; stroke-width: 0; transition: fill var(--trans-dur) ease-in-out; } .clock .clock__progress, .clock .clock__progress-track { transition: opacity 0s var(--trans-dur) ease-in-out, stroke-dashoffset var(--trans-dur) ease-in-out; } [data-unit="h"] .active { fill: hsl(var(--hue1),90%,60%); } [data-unit="h"] .clock__progress { stroke: hsl(var(--hue1),90%,50%); stroke-dashoffset: var(--hOffset); } [data-unit="h"] .clock__progress-track { stroke: hsla(var(--hue1),90%,50%,0.3); } [data-unit="m"] .active { fill: hsl(var(--hue2),90%,60%); stroke: hsl(var(--hue2),90%,60%); } [data-unit="m"] .clock__progress { stroke: hsl(var(--hue2),90%,50%); stroke-dashoffset: var(--mOffset); } [data-unit="m"] .clock__progress-track { stroke: hsla(var(--hue2),90%,50%,0.3); } [data-unit="s"] .active { fill: hsl(var(--hue3),90%,60%); stroke: hsl(var(--hue3),90%,60%); } [data-unit="s"] .clock__progress { stroke: hsl(var(--hue3),90%,50%); stroke-dashoffset: var(--sOffset); } [data-unit="s"] .clock__progress-track { stroke: hsla(var(--hue3),90%,50%,0.3); } .full .clock__progress { opacity: 0; stroke-dashoffset: 0; transition-duration: var(--trans-dur); } .full[data-unit="m"] line, .full[data-unit="m"] text { fill: hsl(var(--hue2),90%,60%); stroke: hsl(var(--hue2),90%,60%); } .full[data-unit="s"] line, .full[data-unit="s"] text { fill: hsl(var(--hue3),90%,60%); stroke: hsl(var(--hue3),90%,60%); } Html 0 5 10 15 20 25 30 35 40 45 50 55 0 5 10 15 20 25 30 35 40 45 50 55 12 1 2 3 4 5 6 7 8 9 10 11 javascriptwindow.addEventListener("DOMContentLoaded",() => { const c = new Clock23(".clock"); }); class Clock23 { fullClass = "full"; constructor(el) { this.el = document.querySelector(el); this.init(); } init() { this.timeUpdate(); } get timeAsObject() { const date = new Date(); const h = date.getHours(); const m = date.getMinutes(); const s = date.getSeconds(); return { h, m, s }; } get timeAsString() { const [h,m,s,ap] = this.timeDigitsGrouped; return `${h}:${m}:${s} ${ap}`; } get timeDigitsGrouped() { // this accessible string uses the 12-hour clock let { h, m, s } = this.timeAsObject; const ap = h > 11 ? "PM" : "AM"; // deal with midnight if (h === 0) h += 12; else if (h > 12) h -= 12; // prepend 0 to the minute and second if single digits if (m < 10) m = `0${m}`; if (s < 10) s = `0${s}`; return [h,m,s,ap]; } checkFills(hands) { for (let hand of hands) { const unit = this.el?.querySelector(`[data-unit="${hand.name}"]`); if (hand.fraction === 0) unit?.classList.add(this.fullClass); } } clearFills() { const fills = Array.from(this.el?.querySelectorAll("[data-unit]")); for (let fill of fills) fill.classList.remove(this.fullClass); } timeUpdate() { // update the accessible timestamp in the `aria-label` this.el?.setAttribute("aria-label", this.timeAsString); // move the hands const time = this.timeAsObject; const minFraction = time.s / 60; const hrFraction = (time.m + minFraction) / 60; const twelveHrFraction = (time.h % 12 + hrFraction) / 12; const hands = [ { name: "h", fraction: twelveHrFraction, value: 376.99 }, { name: "m", fraction: hrFraction, value: 578.05 }, { name: "s", fraction: minFraction, value: 779.11 } ]; const activeClass = "active"; for (let hand of hands) { this.el?.style.setProperty( `--${hand.name}Offset`, Utils.decPlaces(hand.value * (1 - hand.fraction),3) ); const unit = this.el?.querySelector(`[data-unit="${hand.name}"]`); const ticks = Array.from(unit?.querySelectorAll("[data-value]")); for (let tick of ticks) { const dataValue = +tick.getAttribute("data-value"); let timeValue = time[hand.name]; if (hand.name === "h") timeValue %= 12; if (dataValue <= timeValue) tick.classList.add(activeClass); else tick.removeAttribute("class"); } } this.checkFills(hands); // loop clearTimeout(this.clearFillsLoop); this.clearFillsLoop = setTimeout(this.clearFills.bind(this),600); clearTimeout(this.timeUpdateLoop); this.timeUpdateLoop = setTimeout(this.timeUpdate.bind(this),1e3); } } class Utils { static decPlaces(n,d) { return Math.round(n * 10 ** d) / 10 ** d; } } Tags Designer Facebook Twitter Whatsapp Share to other apps Script Clock Progress Designer Newer Older