Kella loomine uute CSS-i sin() ja cos() trigonomeetriafunktsioonidega

Kella loomine uute CSS-i sin() ja cos() trigonomeetriafunktsioonidega

Allikasõlm: 1999799

CSS-i trigonomeetria funktsioonid on siin! Noh, need on siis, kui kasutate Firefoxi ja Safari uusimaid versioone. Sellise matemaatilise jõu omamine CSS-is avab terve hulga võimalusi. Selles õpetuses mõtlesin, et kastame oma varbad vette, et tunnetada paari uuemat funktsiooni: sin() ja cos().

Konveieril on ka teisi trigonomeetria funktsioone, sealhulgas tan() — miks siis keskenduda ainult sellele sin() ja cos()? Need sobivad ideaalselt selle ideega, mis mul meeles on, milleks on teksti paigutamine mööda ringi serva. Seda on siin CSS-Tricksis käsitletud Chris jagas lähenemist, mis kasutab Sassi segu. See oli kuus aastat tagasi, nii et anname sellele veritseva serva ravi.

Siin on see, mida ma silmas pean. Jällegi toetatakse seda praegu ainult Firefoxis ja Safaris:

Niisiis, see ei ole täpselt nii, nagu sõnad moodustavad ringikujulise kuju, vaid me paigutame tekstimärgid mööda ringi, et moodustada kella sihver. Siin on mõned märgistused, mida saame asjade käivitamiseks kasutada:

<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>

Järgmisena on siin mõned ülimalt põhistiilid .clock-face konteiner. Otsustasin kasutada <time> märgistage a datetime atribuut. 

.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);
}

Kaunistasin seal asju veidi, kuid ainult selleks, et saada põhikuju ja taustavärv, mis aitaks meil näha, mida teeme. Pange tähele, kuidas me salvestame width väärtus a CSS-i muutuja. Kasutame seda hiljem. Siiani pole palju vaadata:

Suur tomativärviline ring, mille vasakul on vertikaalne loend numbritega 1-12.

See näeb välja nagu mingi moodsa kunsti eksperiment, eks? Tutvustame uut muutujat, --_r, ringide salvestamiseks raadius, mis võrdub poolega ringi laiusest. Sel viisil, kui laius (--_w) muutub, raadiuse väärtus (--_r) värskendatakse ka tänu teisele CSS-i matemaatikafunktsioonile, calc():

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

Nüüd natuke matemaatikat. Ring on 360 kraadi. Meie kellal on 12 silti, seega tahame paigutada numbrid iga 30 kraadi järel (360 / 12). Matemaatikamaal algab ring kell 3, seega on tegelikult keskpäev miinus 90 kraadi sellest, mis on 270 kraadi (360 - 90).

Lisame veel ühe muutuja, --_d, mida saame kasutada a seadmiseks kraad väärtus iga numbri jaoks kella sihverplaadil. Ringi täitmiseks suurendame väärtusi 30 kraadi võrra:

.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, nüüd on aeg oma käed määrida sin() ja cos() funktsioonid! Me tahame neid kasutada iga numbri X- ja Y-koordinaatide saamiseks, et saaksime need korralikult kella sihverplaadi ümber paigutada.

X-koordinaadi valem on radius + (radius * cos(degree)). Ühendame selle meie uuega --_x muutuja:

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

Y-koordinaadi valem on radius + (radius * sin(degree)). Meil on see, mida vajame selle arvutamiseks:

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

Numbrite seadistamiseks peame tegema mõned majapidamistoimingud, nii et paneme neile mõned põhilised stiilid, et veenduda, et need on täpselt paigas ja meie koordinaatidega:

.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);
}

teade --_sz, mida me kasutame width ja height numbritest hetkega. Vaatame, mis meil seni on.

Suur tomativärviline ring, mille servas on tsentreerimata tunninumbrisildid.

See näeb kindlasti rohkem välja nagu kell! Kas näete, kuidas iga numbri vasak ülemine nurk on ringi ümber õiges kohas? Iga numbri positsioonide arvutamisel peame raadiust "kahandama". Me saame maha arvama numbri suurus (--_sz) ringi suurusest (--_w), enne raadiuse arvutamist:

--_r: calc((var(--_w) - var(--_sz)) / 2);
Suur tomativärviline ring, mille ümardatud servas on tunninumbrite sildid.

Palju parem! Muudame värve, nii et see näeb välja elegantsem:

Tumehallil taustal numbritega valge kella sihver. Kellal pole käsi.

Me võiksime siin peatuda! Täitsime eesmärgi asetada tekst ümber ringi, eks? Aga mis on kell ilma käteta tunde, minuteid ja sekundeid näitamiseks?

Kasutame selleks ühte CSS-animatsiooni. Esmalt lisame oma märgistusele veel kolm elementi,

<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>

Seejärel mõned ühised märgistused kõigile kolmele käele. Jällegi, suurem osa sellest on lihtsalt veendumine, et käed on absoluutselt paigutatud ja paigutatud vastavalt:

.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);
}

Me kasutame sama animatsioon kõigi kolme käe jaoks:

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

Ainus erinevus on aeg, mis üksikutel kätel kulub täispöörde tegemiseks. Jaoks tundi arm, see võtab 12 tundi täispööret teha. The animation-duration atribuut aktsepteerib väärtusi ainult millisekundites ja sekundites. Jääme sekundite juurde, mis on 43,200 XNUMX sekundit (60 seconds * 60 minutes * 12 hours).

animation: turn 43200s infinite;

See võtab 1 tunnis jaoks minuti arm täispööret teha. Kuid me tahame, et see oleks a mitmeastmeline animatsioon nii et liikumine käte vahel on pigem astmeline kui lineaarne. Vajame 60 sammu, üks iga minuti kohta:

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

. sekundit käsi is peaaegu sama minutite õlana, kuid kestus on 60 minuti asemel 60 sekundit:

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

Värskendame levinud stiilides loodud atribuute:

.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;
}

Mis siis, kui tahame alustada praegusel kellaajal? Vajame natuke JavaScripti:

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`);

Olen lisanud id="app" kella numbrilauale ja määrake sellele kaks uut kohandatud atribuuti, mis määravad negatiivse animation-delay, nagu Mate Marschalko tegi kui ta jagas ainult CSS-i kella.  getHours() JavaScipti meetod Date objekt kasutab 24-tunnist vormingut, seega kasutame remainder operaator et teisendada see 12-tunnisesse vormingusse.

CSS-is peame lisama animation-delay samuti:

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

Ainult üks asi veel. CSS-i kasutamine @supports ja atribuudid, mille oleme juba loonud, saame pakkuda varundamist brauseritele, mis ei toeta sin() ja cos(). (Aitäh, 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)))
  }
}

Ja voilà! Meie kell on valmis! Siin on viimane demo veel kord. Jällegi toetatakse seda praegu ainult Firefoxis ja Safaris.

Mida saaksime veel teha?

Lihtsalt jama siin, aga me saame oma kella kiiresti ringikujuliseks pildigaleriiks muuta, asendades <time> sildid koos <img> seejärel värskendage laiust (--_w) ja raadius (--_r) väärtused:

Proovime veel ühe. Mainisin varem, kuidas kell nägi välja nagu moodsa kunsti eksperiment. Võime sellele tugineda ja uuesti luua mustri, mida nägin eelmisel päeval kunstigalerii plakatil (mida ma kahjuks ei ostnud). Nagu ma mäletan, nimetati seda "Kuu" ja see koosnes hunnikust täppidest, mis moodustasid ringi.

Suur ring, mis moodustati hunnikust väiksematest erinevate maatoonide värvidega täidetud ringidest.

Seekord kasutame järjestamata loendit, kuna ringid ei järgi kindlat järjekorda. Me ei pane isegi kõiki loendi üksusi märgistusele. Selle asemel sisestame neile JavaScripti ja lisame mõned juhtelemendid, mida saame kasutada lõpptulemusega manipuleerimiseks.

Juhtnupud on vahemiku sisendid (<input type="range">) mille mähime a <form> ja kuulake input sündmus.

<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>

Käitame seda meetodit sisendil, mis loob hulga <li> elemendid kraadiga (--_d) muutuja, mida me varem kasutasime, rakendati igaühele. Samuti saame oma raadiuse muutuja (--_r).

Samuti tahan, et täpid oleksid erinevat värvi. Niisiis, randomiseerime (noh, mitte täiesti randomiseeritud) HSL-i värviväärtus iga loendiüksuse jaoks ja salvestada see uue CSS-muutujana, --_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;
}

. random() meetod valib väärtuse teatud arvude vahemikus:

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

Ja see ongi kõik. Kasutame märgistuse renderdamiseks JavaScripti, kuid niipea, kui see on renderdatud, pole meil seda tegelikult vaja. The sin() ja cos() funktsioonid aitavad meil paigutada kõik punktid õigetesse kohtadesse.

Lõplik mõtted

Asjade paigutamine ringi ümber on üsna põhinäide, mis demonstreerib trigonomeetria funktsioonide võimeid sin() ja cos(). Aga see on tõesti lahe, et saame kaasaegsed CSS-i funktsioonid, mis pakuvad uusi lahendusi vanade lahenduste jaoks. Olen kindel, et näeme palju huvitavamaid, keerukamaid ja loomingulisemaid kasutusjuhtumeid, eriti kui brauseri tugi tuleb Chrome'i ja Edge'i.

Ajatempel:

Veel alates CSSi trikid