Kellon luominen uusilla CSS-sin()- ja cos()-trigonometriafunktioilla

Kellon luominen uusilla CSS-sin()- ja cos()-trigonometriafunktioilla

Lähdesolmu: 1999799

CSS-trigonometriafunktiot ovat täällä! No, ne ovat, jos käytät Firefoxin ja Safarin uusimpia versioita. Tällainen matemaattinen voima CSS:ssä avaa koko joukon mahdollisuuksia. Ajattelin tässä opetusohjelmassa upottaa varpaat veteen saadaksemme tuntuman muutamasta uudemmasta toiminnosta: sin() ja cos().

Liukulinjassa on muita trigonometriafunktioita - mukaan lukien tan() - Joten miksi keskittyä vain sin() ja cos()? Ne sopivat täydellisesti ajatukseeni, joka on tekstin sijoittaminen ympyrän reunaan. Sitä on käsitelty täällä CSS-Tricksissä, kun Chris jakoi lähestymistavan, joka käyttää Sass-sekoitusta. Se oli kuusi vuotta sitten, joten annetaan sille verenvuotokäsittely.

Tässä on mitä minulla on mielessä. Jälleen, sitä tuetaan tällä hetkellä vain Firefoxissa ja Safarissa:

Joten se ei ole aivan kuin sanat muodostavat pyöreän muodon, mutta sijoitamme tekstimerkkejä ympyrää pitkin kellotaulun muodostamiseksi. Tässä on joitain merkintöjä, joita voimme käyttää asioiden käynnistämiseen:

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

Seuraavaksi tässä on joitain superperustyylejä .clock-face kontti. Päätin käyttää <time> merkitse a:lla datetime määrite. 

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

Koristelin siellä hieman tavaroita, mutta vain saadakseni perusmuodon ja taustavärin, jotta voimme nähdä, mitä teemme. Huomaa kuinka säästämme width arvo a CSS-muuttuja. Käytämme sitä myöhemmin. Ei paljon katsottavaa toistaiseksi:

Suuri tomaatinvärinen ympyrä, jossa vasemmalla pystysuora luettelo numeroista 1-12.

Se näyttää eräänlaiselle modernin taiteen kokeilulle, eikö? Otetaan käyttöön uusi muuttuja, --_r, tallentaaksesi ympyrän säde, joka on yhtä suuri kuin puolet ympyrän leveydestä. Tällä tavalla, jos leveys (--_w) muuttuu, säteen arvo (--_r) päivittyy myös toisen CSS:n matemaattisen funktion ansiosta, calc():

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

Nyt vähän matematiikkaa. Ympyrä on 360 astetta. Meillä on 12 tarraa kellossamme, joten haluamme sijoittaa numerot 30 asteen välein (360 / 12). Matematiikassa ympyrä alkaa kello 3, joten keskipäivä on itse asiassa miinus 90 astetta siitä, joka on 270 astetta (360 - 90).

Lisätään toinen muuttuja, --_d, jota voimme käyttää asettamaan a aste arvo jokaiselle kellotaulun numerolle. Kasvatamme arvoja 30 astetta täydentääksemme ympyrän:

.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, nyt on aika likata kätemme sin() ja cos() toimintoja! Haluamme käyttää niitä saadaksemme kunkin numeron X- ja Y-koordinaatit, jotta voimme sijoittaa ne oikein kellotaulun ympärille.

X-koordinaatin kaava on radius + (radius * cos(degree)). Kytketään se uuteen --_x muuttuja:

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

Y-koordinaatin kaava on radius + (radius * sin(degree)). Meillä on mitä tarvitsemme laskeaksemme, että:

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

Meidän on tehtävä muutamia siivousasioita numeroiden määrittämiseksi, joten laitetaan niihin perusmuotoilu varmistaaksemme, että ne ovat ehdottomasti paikoillaan ja koordinaattiemme mukaan:

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

Ilmoitus --_sz, jota käytämme width ja height numerot hetkessä. Katsotaan mitä meillä on tähän mennessä.

Suuri tomaatinvärinen ympyrä, jonka reunassa on epäkeskeiset tuntinumerotarrat.

Tämä näyttää ehdottomasti enemmän kellolta! Näetkö, kuinka kunkin numeron vasen yläkulma on oikeassa paikassa ympyrän ympärillä? Meidän on "kutistettava" sädettä laskettaessa kunkin numeron paikkoja. Me voimme vähentää numeron koko (--_sz) ympyrän koosta (--_w), ennen kuin laskemme säteen:

--_r: calc((var(--_w) - var(--_sz)) / 2);
Suuri tomaatinvärinen ympyrä, jonka pyöristettyä reunaa pitkin on tuntinumerotarrat.

Paljon parempi! Vaihdetaan värejä, jotta se näyttää tyylikkäämmältä:

Valkoinen kellotaulu numeroineen tummanharmaata taustaa vasten. Kellossa ei ole käsivarsia.

Voisimme pysähtyä tähän! Saavutimme tavoitteen sijoittaa tekstiä ympyrän ympärille, eikö niin? Mutta mitä on kello ilman käsivarsia tuntien, minuuttien ja sekuntien näyttämiseen?

Käytetään tähän yhtä CSS-animaatiota. Lisätään ensin kolme elementtiä merkintään,

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

Sitten yhteinen merkintä kaikille kolmelle käsivarrelle. Jälleen suurin osa tästä on vain sen varmistamista, että käsivarret ovat ehdottomasti paikoillaan ja sijoitettu vastaavasti:

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

Käytämme sama animaatio kaikille kolmelle käsivarrelle:

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

Ainoa ero on aika, joka yksittäisiltä käsivarsilta kuluu täyden käännöksen tekemiseen. Varten tunnin käsivarsi, se ottaa 12 tuntia tehdä täysi käännös. The animation-duration ominaisuus hyväksyy arvot vain millisekunteina ja sekunteina. Pysytään sekunneissa, mikä on 43,200 XNUMX sekuntia (60 seconds * 60 minutes * 12 hours).

animation: turn 43200s infinite;

Se kestää 1 tunnissa varten minuutin käsivarsi tehdä täysi käännös. Mutta haluamme tämän olevan a monivaiheinen animaatio joten käsivarsien välinen liike on pikemminkin porrastettua kuin lineaarista. Tarvitsemme 60 askelta, yksi jokaista minuuttia kohden:

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

- sekunnin käsi is melkein sama minuuttivarren, mutta kesto on 60 sekuntia 60 minuutin sijaan:

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

Päivitetään yleisiin tyyleihin luomamme ominaisuudet:

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

Entä jos haluamme aloittaa nykyisestä ajasta? Tarvitsemme hieman 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 lisännyt id="app" kellotauluun ja aseta siihen kaksi uutta mukautettua ominaisuutta, jotka asettavat negatiivisen animation-delay, kuten Mate Marschalko teki kun hän jakoi vain CSS-kellon.  getHours() JavaSciptin menetelmä Date objekti käyttää 24 tunnin muotoa, joten käytämme remainder operaattori muuntaaksesi sen 12 tunnin muotoon.

CSS:ään meidän on lisättävä animation-delay yhtä hyvin:

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

Vielä yksi juttu. CSS: n käyttö @supports ja jo luomamme ominaisuudet, voimme tarjota varavaihtoehdon selaimille, jotka eivät tue sin() ja cos(). (Kiitos, 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à! Meidän kello on valmis! Tässä viimeinen demo vielä kerran. Jälleen, sitä tuetaan tällä hetkellä vain Firefoxissa ja Safarissa.

Mitä muuta voimme tehdä?

Vain sekaisin täällä, mutta voimme nopeasti muuttaa kellomme pyöreäksi kuvagalleriaksi korvaamalla <time> tunnisteet kanssa <img> sitten leveyden päivittäminen (--_w) ja säde (--_r) arvot:

Kokeillaan vielä yhtä. Mainitsin aiemmin, kuinka kello näytti modernin taiteen kokeilulta. Voimme nojautua siihen ja luoda uudelleen kuvion, jonka näin julisteessa (jota en valitettavasti ostanut) taidegalleriassa toissapäivänä. Muistaakseni sitä kutsuttiin "Kuuksi" ja se koostui joukosta pisteitä, jotka muodostivat ympyrän.

Suuri ympyrä, joka muodostui joukosta pienempiä täytettyjä ympyröitä, joilla oli erilaisia ​​maansävyvärejä.

Käytämme tällä kertaa järjestämätöntä luetteloa, koska piirit eivät noudata tiettyä järjestystä. Emme edes aio laittaa kaikkia luettelokohteita merkintöihin. Sen sijaan ruiskutetaan niihin JavaScript ja lisätään muutama ohjausobjekti, joilla voimme manipuloida lopputulosta.

Säätimet ovat aluetuloja (<input type="range">) jonka käärimme a <form> ja kuuntele input tapahtuma.

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

Suoritamme tämän menetelmän "syötteellä", joka luo joukon <li> elementtejä asteella (--_d) -muuttuja, jota käytimme aiemmin, sovellettiin jokaiseen. Voimme myös käyttää uudelleen sädemuuttujaamme (--_r).

Haluan myös, että pisteet ovat erivärisiä. Satunnaistetaan siis (ei täysin satunnaistettu) HSL-väriarvo jokaiselle luettelokohdalle ja tallenna se uutena CSS-muuttujana, --_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() menetelmä valitsee arvon määritetyltä numeroalueelta:

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

Ja siinä se. Käytämme JavaScriptiä merkinnän hahmontamiseen, mutta heti kun se on renderöity, emme todellakaan tarvitse sitä. The sin() ja cos() toiminnot auttavat meitä sijoittamaan kaikki pisteet oikeisiin paikkoihin.

Lopullinen ajatuksia

Asioiden asettaminen ympyrän ympärille on melko perusesimerkki havainnollistamaan trigonometriafunktioiden, kuten esim sin() ja cos(). Mutta se on ihan oikeesti hienoa, että saamme nykyaikaisia ​​CSS-ominaisuuksia, jotka tarjoavat uusia ratkaisuja vanhoihin ratkaisuihin. Olen varma, että tulemme näkemään paljon mielenkiintoisempia, monimutkaisempia ja luovampia käyttötapauksia, etenkin kun selaintuki tulee Chromeen ja Edgeen.

Aikaleima:

Lisää aiheesta CSS-temppuja