Ustvarjanje ure z novimi trigonometričnimi funkcijami CSS sin() in cos().

Ustvarjanje ure z novimi trigonometričnimi funkcijami CSS sin() in cos().

Izvorno vozlišče: 1999799

Trigonometrične funkcije CSS so tukaj! No, so, če uporabljate najnovejši različici Firefoxa in Safarija. Tovrstna matematična moč v CSS odpira cel kup možnosti. V tej vadnici sem mislil, da bi potopili prste v vodo, da bi dobili občutek za nekaj novejših funkcij: sin() in cos().

V pripravi so še druge trigonometrične funkcije – vključno z tan() — zakaj bi se torej osredotočali samo na sin() in cos()? Slučajno so kot nalašč za idejo, ki jo imam v mislih, to je postavitev besedila ob rob kroga. To je bilo obravnavano tukaj na CSS-Tricks, ko Chris je delil pristop, ki uporablja mešanico Sass. To je bilo pred šestimi leti, zato ga obravnavajmo na vrhuncu.

Evo, kar imam v mislih. Še enkrat, trenutno je podprt samo v Firefoxu in Safariju:

Torej ni tako, kot da bi besede tvorile krožno obliko, ampak besedilne znake postavljamo vzdolž kroga, da tvorijo številčnico ure. Tukaj je nekaj oznak, ki jih lahko uporabimo za začetek:

<div class="clock"> <div class="clock-face"> <time datetime="12:00">12</time> <time datetime="1:00">1</time> <time datetime="2:00">2</time> <time datetime="3:00">3</time> <time datetime="4:00">4</time> <time datetime="5:00">5</time> <time datetime="6:00">6</time> <time datetime="7:00">7</time> <time datetime="8:00">8</time> <time datetime="9:00">9</time> <time datetime="10:00">10</time> <time datetime="11:00">11</time> </div>
</div>

Nato je tukaj nekaj super osnovnih stilov za .clock-face posoda. Odločil sem se za uporabo <time> označite z a datetime atribut. 

.clock { --_ow: clamp(5rem, 60vw, 40rem); --_w: 88cqi; aspect-ratio: 1; background-color: tomato; border-radius: 50%; container-type: inline; display: grid; height: var(--_ow); place-content: center; position: relative; width var(--_ow);
}

Stvari sem malo okrasil, a le zato, da sem dobil osnovno obliko in barvo ozadja, da bomo lažje videli, kaj počnemo. Opazite, kako rešujemo width vrednost v a spremenljivka CSS. To bomo uporabili kasneje. Zaenkrat ni veliko za pogledati:

Velik krog v barvi paradižnika z navpičnim seznamom številk 1–12 na levi strani.

Izgleda kot nekakšen moderni umetniški eksperiment, kajne? Uvedimo novo spremenljivko, --_r, za shranjevanje krogov polmer, kar je enako polovici širine kroga. Na ta način, če je širina (--_w) spremeni vrednost polmera (--_r) bo prav tako posodobljen – zahvaljujoč drugi matematični funkciji CSS, calc():

.clock { --_w: 300px; --_r: calc(var(--_w) / 2); /* rest of styles */
}

Zdaj pa malo matematike. Krog je 360 ​​stopinj. Na uri imamo 12 oznak, zato želimo številke postaviti na vsakih 30 stopinj (360 / 12). V deželi matematike se krog začne ob 3. uri, torej je pravzaprav poldne minus 90 stopinj od tega, kar je 270 stopinj (360 - 90).

Dodajmo še eno spremenljivko, --_d, ki ga lahko uporabimo za nastavitev a stopnja vrednost za vsako številko na obrazu ure. Vrednosti bomo povečali za 30 stopinj, da zaključimo naš krog:

.clock time:nth-child(1) { --_d: 270deg; }
.clock time:nth-child(2) { --_d: 300deg; }
.clock time:nth-child(3) { --_d: 330deg; }
.clock time:nth-child(4) { --_d: 0deg; }
.clock time:nth-child(5) { --_d: 30deg; }
.clock time:nth-child(6) { --_d: 60deg; }
.clock time:nth-child(7) { --_d: 90deg; }
.clock time:nth-child(8) { --_d: 120deg; }
.clock time:nth-child(9) { --_d: 150deg; }
.clock time:nth-child(10) { --_d: 180deg; }
.clock time:nth-child(11) { --_d: 210deg; }
.clock time:nth-child(12) { --_d: 240deg; }

OK, zdaj je čas, da si umažemo roke z sin() in cos() funkcije! Kar želimo storiti, je, da jih uporabimo za pridobitev koordinat X in Y za vsako število, da jih lahko pravilno postavimo okoli številčnice ure.

Formula za koordinato X je radius + (radius * cos(degree)). Vključimo to v naš novi --_x spremenljivka:

--_x: calc(var(--_r) + (var(--_r) * cos(var(--_d))));

Formula za koordinato Y je radius + (radius * sin(degree)). Imamo vse, kar potrebujemo za izračun:

--_y: calc(var(--_r) + (var(--_r) * sin(var(--_d))));

Za nastavitev številk moramo opraviti nekaj gospodinjskih stvari, zato jim dodajmo nekaj osnovnega sloga, da se prepričamo, da so absolutno postavljene in postavljene z našimi koordinatami:

.clock-face time { --_x: calc(var(--_r) + (var(--_r) * cos(var(--_d)))); --_y: calc(var(--_r) + (var(--_r) * sin(var(--_d)))); --_sz: 12cqi; display: grid; height: var(--_sz); left: var(--_x); place-content: center; position: absolute; top: var(--_y); width: var(--_sz);
}

Opaziti --_sz, ki ga bomo uporabili za width in height številk v trenutku. Poglejmo, kaj imamo do zdaj.

Velik krog v barvi paradižnika z nalepkami s številkami ur ob robu, ki niso na sredini.

To zagotovo izgleda bolj kot ura! Vidite, kako je zgornji levi kot vsake številke nameščen na pravilnem mestu okoli kroga? Pri izračunu položajev za vsako številko moramo "zmanjšati" polmer. Mi lahko odšteti velikost številke (--_sz) od velikosti kroga (--_w), preden izračunamo polmer:

--_r: calc((var(--_w) - var(--_sz)) / 2);
Velik krog v barvi paradižnika z nalepkami s številko ure vzdolž zaobljenega roba.

Precej bolje! Spremenimo barve, da bo videti bolj elegantno:

Bela številčnica ure s številkami na temno sivem ozadju. Ura je brez krakov.

Lahko bi se ustavili kar tukaj! Dosegli smo cilj postaviti besedilo okoli kroga, kajne? Toda kaj je ura brez krakov, ki bi kazala ure, minute in sekunde?

Za to uporabimo eno samo animacijo CSS. Najprej dodajmo še tri elemente naši oznaki,

<div class="clock"> <!-- after <time>-tags --> <span class="arm seconds"></span> <span class="arm minutes"></span> <span class="arm hours"></span> <span class="arm center"></span>
</div>

Nato nekaj skupnih oznak za vse tri krake. Še enkrat, večina tega je samo zagotoviti, da so roke absolutno nameščene in ustrezno nameščene:

.arm { background-color: var(--_abg); border-radius: calc(var(--_aw) * 2); display: block; height: var(--_ah); left: calc((var(--_w) - var(--_aw)) / 2); position: absolute; top: calc((var(--_w) / 2) - var(--_ah)); transform: rotate(0deg); transform-origin: bottom; width: var(--_aw);
}

Uporabili bomo ista animacija za vse tri roke:

@keyframes turn { to { transform: rotate(1turn); }
}

Edina razlika je čas, ki ga posamezne roke potrebujejo za polni obrat. Za ure rok, vzame 12 ur narediti polni obrat. The animation-duration Lastnost sprejema samo vrednosti v milisekundah in sekundah. Ostanimo pri sekundah, kar je 43,200 sekund (60 seconds * 60 minutes * 12 hours).

animation: turn 43200s infinite;

To traja 1 uro za minuta roko narediti polni obrat. Toda želimo, da je to a večstopenjska animacija tako je gibanje med rokama zamaknjeno in ne linearno. Potrebovali bomo 60 korakov, enega za vsako minuto:

animation: turn 3600s steps(60, end) infinite;

O sekundna roka is skoraj isto kot minutni krak, vendar je trajanje 60 sekund namesto 60 minut:

animation: turn 60s steps(60, end) infinite;

Posodobimo lastnosti, ki smo jih ustvarili v običajnih slogih:

.seconds { --_abg: hsl(0, 5%, 40%); --_ah: 145px; --_aw: 2px; animation: turn 60s steps(60, end) infinite;
}
.minutes { --_abg: #333; --_ah: 145px; --_aw: 6px; animation: turn 3600s steps(60, end) infinite;
}
.hours { --_abg: #333; --_ah: 110px; --_aw: 6px; animation: turn 43200s linear infinite;
}

Kaj pa, če želimo začeti ob trenutnem času? Potrebujemo malo JavaScripta:

const time = new Date();
const hour = -3600 * (time.getHours() % 12);
const mins = -60 * time.getMinutes();
app.style.setProperty('--_dm', `${mins}s`);
app.style.setProperty('--_dh', `${(hour+mins)}s`);

Dodal sem id="app" na številčnico ure in na njej nastavite dve novi lastnosti po meri, ki nastavita negativno animation-delay, kot je to storil Mate Marschalko ko je delil uro samo za CSSgetHours() metoda JavaScipta Date objekt uporablja 24-urni format, zato uporabljamo remainder operater da ga pretvorite v 12-urni format.

V CSS moramo dodati animation-delay tudi:

.minutes { animation-delay: var(--_dm, 0s); /* other styles */
} .hours { animation-delay: var(--_dh, 0s); /* other styles */
}

Samo še nekaj. Uporaba CSS @supports in lastnosti, ki smo jih že ustvarili, lahko zagotovimo nadomestno možnost za brskalnike, ki ne podpirajo supprt sin() in cos(). (Hvala, Temani Afif!):

@supports not (left: calc(1px * cos(45deg))) {
  time {
    left: 50% !important;
    top: 50% !important;
    transform: translate(-50%,-50%) rotate(var(--_d)) translate(var(--_r)) rotate(calc(-1*var(--_d)))
  }
}

In, voilà! Naša ura je končana! Evo še zadnji demo. Še enkrat, trenutno je podprt samo v Firefoxu in Safariju.

Kaj še lahko storimo?

Tukaj se samo zafrkavamo, vendar lahko svojo uro hitro spremenimo v krožno galerijo slik, tako da zamenjamo <time> oznake z <img> nato posodabljanje širine (--_w) in polmer (--_r) vrednote:

Poskusimo še enega. Prej sem omenil, kako je ura izgledala kot eksperiment sodobne umetnosti. Lahko se zanesemo na to in ponovno ustvarimo vzorec, ki sem ga prejšnji dan videl na plakatu (ki ga žal nisem kupil) v umetniški galeriji. Kolikor se spomnim, se je imenovala "Luna" in je bila sestavljena iz množice pik, ki tvorijo krog.

Velik krog je nastal iz množice manjših zapolnjenih krogov različnih zemeljskih barv.

Tokrat bomo uporabili neurejen seznam, saj krogi ne sledijo določenemu vrstnemu redu. Sploh ne bomo dali vseh elementov seznama v oznako. Namesto tega jih vstavimo z JavaScriptom in dodamo nekaj kontrolnikov, s katerimi lahko manipuliramo s končnim rezultatom.

Kontrolniki so vnosi obsega (<input type="range">) ki ga bomo zavili v a <form> in poslušaj input dogodek.

<form id="controls"> <fieldset> <label>Number of rings <input type="range" min="2" max="12" value="10" id="rings" /> </label> <label>Dots per ring <input type="range" min="5" max="12" value="7" id="dots" /> </label> <label>Spread <input type="range" min="10" max="40" value="40" id="spread" /> </label> </fieldset>
</form>

To metodo bomo zagnali na "vhodu", kar bo ustvarilo kup <li> elementi z diplomo (--_d) spremenljivka, ki smo jo uporabili prej, je bila uporabljena za vsakega. Spremenljivko polmera lahko tudi spremenimo v namen (--_r).

Želim tudi, da so pike različnih barv. Torej, naključno določimo (no, ne popolnoma naključno) barvno vrednost HSL za vsak element seznama in jo shranite kot novo spremenljivko CSS, --_bgc:

const update = () => { let s = ""; for (let i = 1; i <= rings.valueAsNumber; i++) { const r = spread.valueAsNumber * i; const theta = coords(dots.valueAsNumber * i); for (let j = 0; j < theta.length; j++) { s += `<li style="--_d:${theta[j]};--_r:${r}px;--_bgc:hsl(${random( 50, 25 )},${random(90, 50)}%,${random(90, 60)}%)"></li>`; } } app.innerHTML = s;
}

O random() metoda izbere vrednost znotraj določenega obsega števil:

const random = (max, min = 0, f = true) => f ? Math.floor(Math.random() * (max - min) + min) : Math.random() * max;

In to je to. Za upodabljanje oznake uporabljamo JavaScript, a takoj ko je upodobljena, je v resnici ne potrebujemo. The sin() in cos() funkcije nam pomagajo postaviti vse pike na prava mesta.

Končne misli

Postavljanje stvari okoli kroga je precej osnovni primer za prikaz moči trigonometričnih funkcij, kot je sin() in cos(). Ampak je res super, da dobivamo sodobne funkcije CSS, ki ponujajo nove rešitve za stare rešitve. Prepričan sem, da bomo videli veliko bolj zanimive, zapletene in ustvarjalne primere uporabe, zlasti ko bo podpora za brskalnike prišla v Chrome in Edge.

Časovni žig:

Več od Triki CSS