Logiske Operasjoner med CSS-Variabler

0
6

Veldig ofte, når du bruker bryteren variabler (en variabel som er enten 0 eller 1, et konsept som er forklart i større detalj i dette innlegget), jeg skulle ønske jeg kunne utføre logiske operasjoner på dem. Vi har ikke funksjoner som ikke er(var(–jeg)) eller og(var(–jeg), var(–k)) i CSS, men vi kan etterligne disse og flere med aritmetiske operasjoner i en calc () – funksjonen.

Denne artikkelen kommer til å vise deg hva calc() formler vi trenger å bruke for hver logisk drift og forklare hvordan og hvorfor de er brukt med et par tilfeller som fører til skrivingen av denne artikkelen.

Hvordan: formler

ikke

Dette er en ganske enkel en: vi trekker bryteren variabel (la oss kalle det-j) fra 1:

–notj: calc(1 – var(–j))

Hvis –j 0, deretter –notj er 1 (1 – 0). Hvis j er 1, deretter –notj er 0 (1 – 1).

og

Nå, hvis du har noen gang tatt elektronikk klasser (spesielt noe som er Programmert Logikk Systemer eller Integrerte Kretser), så vet du allerede hva formelen vi trenger å bruke her. Men la oss ikke hoppe rett inn.

Den og to operander er sann hvis og bare hvis begge deler er sant. De to operander i vårt tilfelle er to bytter variabler (la oss kalle dem –k –og jeg). Hver av dem kan være enten 0 eller 1, uavhengig av de andre. Dette betyr at vi kan være i én av fire mulige scenarioer:

  • –k: 0, –jeg: 0
  • –k: 0, –i: 1
  • –k: 1, –jeg: 0
  • –k: 1, –i: 1

Resultatet av den, og driften er 1 hvis både vår bytte variabler er 1 og 0 ellers. Ser på det den andre veien, dette resultatet er 0 hvis minst en av de to slår variabler er 0.

Nå er du trenger å tenke på det på denne måten: resultatet av hva regnemåte er 0 hvis minst en av de to operander er 0? Det er multiplikasjon, som å multiplisere noe av 0 gir oss 0!

Så, vår-og formelen er:

–og: calc(var(–k)*var(–jeg))

Vurderer hver av våre fire mulige scenarioer, vi har:

  • for –k: 0, –jeg: 0, vi har det-og er 0 (0*0)
  • for –k: 0, –i: 1, vi har det-og er 0 (0*1)
  • for –k: 1, –jeg: 0, vi har det-og er 0 (1*0)
  • for –k: 1, –i: 1, vi har det-og er 1 (1*1)

nand

Siden nand er det ikke, og vi trenger å erstatte –j i ikke-formelen med formelen for og:

–nand: calc(1 – var(–k)*var(–jeg))

For hver av våre fire mulige scenarioer, får vi:

  • for –k: 0, –jeg: 0, vi har det-nand-er 1 (1 – 0*0 = 1 – 0)
  • for –k: 0, –i: 1, vi har det-nand-er 1 (1 – 0*1 = 1 – 0)
  • for –k: 1, –jeg: 0, vi har det-nand-er 1 (1 – 1*0 = 1 – 0)
  • for –k: 1, –i: 1, vi har det-nand-er 0 (1 – 1*1 = 1 – 1)

eller

Resultatet av eller bruk er 1 hvis minst en av vår bytte variabler er 1 og 0 ellers (hvis begge er 0).

Den første instinkt her er å gå for tillegg, men selv om det gir oss 0 hvis begge –k –og jeg er 0 og 1 hvis man er 0 og den andre er 1, det gir oss 2 hvis begge av dem er 1. Slik at ikke virkelig fungerer.

Men vi kan bruke den gode gamle De Morgan ‘ s lover, en av usa:

ikke (A eller B) = (ikke A) og (ikke B)

Dette betyr at resultatet av den eller drift er negasjonen av og samarbeid mellom negasjoner av –k –og jeg. Å sette dette inn i CSS, vi har:

– eller: calc(1 – (1 – var(–k))*(1 – var(–jeg)))

For hvert scenario, får vi:

  • for –k: 0, –jeg: 0, vi har det-eller er 0 (1 – (1 – 0)*(1 – 0) = 1 – 1*1 = 1 – 1)
  • for –k: 0, –i: 1, vi har det-eller er 1 (1 – (1 – 0)*(1 – 1) = 1 – 1*0 = 1 – 0)
  • for –k: 1, –jeg: 0, vi har det-eller er 1 (1 – (1 – 1)*(1 – 0) = 1 – 0*1 = 1 – 0)
  • for –k: 1, –i: 1, vi har det-eller er 1 (1 – (1 – 1)*(1 – 1) = 1 – 0*0 = 1 – 0)

nor

Siden er heller ikke eller, vi har:

–heller: calc((1 – var(–k))*(1 – var(–jeg)))

For hver av våre fire mulige scenarioer, får vi:

  • for –k: 0, –jeg: 0, vi har det-eller er 1 ((1 – 0)*(1 – 0) = 1*1)
  • for –k: 0, –i: 1, vi har det-eller er 0 ((1 – 0)*(1 – 1) = 1*0)
  • for –k: 1, –jeg: 0, vi har det-eller er 0 ((1 – 1)*(1 – 0) = 0*1)
  • for –k: 1, –i: 1, vi har det-eller er 0 ((1 – 1)*(1 – 1) = 0*0)

xor

Resultatet av xor drift er 1 når en av de to operander er 1 og den andre er 0. Dette føles mer komplisert i begynnelsen, men hvis vi tror at dette betyr to operander må være annerledes for at resultatet skal være 1 (ellers er det 0), kan vi komme på rett regnemåte til å bruke inne calc(): subtraksjon!

Hvis –k –og jeg er like, og deretter trekke –jeg fra –k gir oss 0. Ellers, hvis vi har-k: 0, –jeg: 1, resultatet av det samme subtraksjon er -1; hvis vi har-k: 1, –jeg: 0, resultatet er 1.

Lukk, men ikke helt! Vi får det resultatet vi ønsker i tre av fire scenarier, men vi trenger for å få 1, ikke -1 i –k: 0, –jeg: 1 scenario.

Men, en ting som -1, 0 og 1 har felles, er at multiplisere dem med seg selv gir oss sine absolutte verdi (som er 1 for begge -1 og 1). Så selve løsningen er å multiplisere denne forskjellen med seg selv:

–xor: calc((var(–k) – var(–i))*(var(–k) – var(–jeg)))

Testing av hver av våre fire mulige scenarioer, vi har:

  • for –k: 0, –jeg: 0, vi har det-xor er 0 ((0 – 0)*(0 – 0) = 0*0)
  • for –k: 0, –i: 1, vi har det-xor er 1 ((0 – 1)*(0 – 1) = -1*-1)
  • for –k: 1, –jeg: 0, vi har det-xor er 1 ((1 – 0)*(1 – 0) = 1*1)
  • for –k: 1, –i: 1, vi har det-xor er 0 ((1 – 1)*(1 – 1) = 0*0)

Hvorfor: Bruk saker

La oss se på et par eksempler som gjør bruk av logiske operasjoner i CSS. Merk at jeg vil ikke i detalj andre aspekter av disse demoer som de er utenfor omfanget av denne artikkelen.

Skjul deaktivert panelet bare på små skjermer

Dette er et use case jeg kom over mens du arbeider på en interaktiv demo som lar brukere styre ulike parametere for å endre et visuelt resultat. For mer erfarne brukere, er det også et panel av avanserte kontroller som er deaktivert som standard. Det kan imidlertid være aktivert for å få tilgang til manuelt kontrollere enda flere parametere.

Siden denne demoen er ment å være lydhør, layout endringer med viewport. Vi ønsker heller ikke ting for å få proppfull på mindre skjermer hvis vi kan unngå det, så det er ingen vits i å vise de avanserte kontroller om de er funksjonshemmet og vi er i den smale skjermen tilfelle.

Screenshot collage nedenfor viser resultatene får vi for hver av de fire mulige scenarier.

Collage av mulige tilfeller.

Så la oss se hva dette betyr i form av CSS!

First off, på <body> vi bruke en bryter som går fra 0 i den smale skjermen saken til 1 i den brede skjermen tilfelle. Vi har også endre flex-retning denne måten (hvis du ønsker en mer detaljert forklaring på hvordan dette fungerer, sjekk ut min andre artikkel på TØRRE å bytte med CSS-variabler).

body {
–k: var(–bredt, 0);
skjerm: flex;
flex-retning: var(–bredt, kolonne);

@media (retning: landskap) { –bredt: 1 }
}

Vi har da et sekund slå på avanserte kontroller panelet. Denne andre bryteren er 0 hvis avmerkingsboksen ikke er merket og 1 hvis avmerkingsboksen er :kontrollert. Med hjelp av denne bryteren, gir vi våre avanserte kontroller panelet en deaktivert se (via et filter kjede), og vi har også deaktivere (via pekeren-hendelser). Her, som ikke kommer i hendig, som vi ønsker å redusere kontrasten og tettheten i den deaktivert saken:

.avansert {
–jeg: var(–aktivert, 0);
–noti: calc(1 – var(–i));
filter:
kontrast(calc(1 – var(–noti)*.9))
dekkevne(calc(1 – var(–noti)*.7));
peker-hendelser: var(–aktivert, ingen);

[id=’slå’]:sjekket ~ & { –aktivert: 1 }
}

Vi ønsker den avanserte kontroller panelet for å holde utvidet hvis vi er i den brede skjermen saken (så hvis –k er 1), uavhengig av om boksen er :kontrollert eller ikke, eller hvis avmerkingsboksen er :sjekket (så hvis-jeg er 1), uavhengig av om vi er i den brede skjermen sak eller ikke.

Dette er nøyaktig eller bruk!

Så vi beregner et-eller-variabel:

.avansert {
/* samme som før */
– eller: calc(1 – (1 – var(–k))*(1 – var(–i)));
}

Hvis dette –eller variabel er 0, betyr dette at vi er i den smale skjermen saken og våre avmerkingsboksen ikke er merket, så vi ønsker å null høyden av avanserte kontroller panelet, og også dens vertikale margin:

.avansert {
/* samme som før */
margin: calc(var(–eller)*#{$mv}) 0;
høyde: calc(var(–eller)*#{$h});
}

Dette gir oss den ønskede resultat (live demo).

Bruk samme formler til å plassere flere ansikter av en 3D-form

Dette er et use case jeg kom over mens du arbeider på personlig prosjekt av CSS-ing Johnson tørrstoff denne sommeren.

La oss ta en titt på en av disse figurene, for eksempel gyroelongated pentagonal rotunden (J25), for å se hvordan logiske operasjoner er nyttig her.

Den formen vi ønsker å få.

Denne figuren er laget ut av en femkantet rotunda uten den store decagonal base og en decagonal antiprism uten sin topp decagon. Interaktiv demo nedenfor viser hvordan disse to komponentene kan bli bygget ved å brette deres garn av ansikter i 3D og deretter kom for å gi oss den form vi ønsker.

Se Pennen av thebabydino (@thebabydino) på CodePen.

Som det kan sees ovenfor, ansiktene er enten en del av antiprism eller en del av rotunda. Dette er hvor vi presentere vår første bytte variabel –jeg. Dette er 0 for ansikter som er en del av antiprism og 1 for ansikter som er en del av rotunda. Den antiprism ansikter har en klasse av .mid fordi vi kan legge til en annen rotunda til andre antiprism base og deretter antiprism ville være i midten. Rotunda ansikter har en klasse av .cup fordi denne delen ser ut som en kaffekopp… uten håndtak!

Rotunda ser ut som en opp-ned-opp cup uten håndtak.

.mid { –jeg: 0 }
.cup { –jeg: 1 }

Å fokusere bare på den laterale ansikter, disse kan ha et toppunkt som peker opp eller ned. Dette er hvor vi presentere vår andre variable –k. Dette er 0 hvis de har et toppunkt som peker opp (slik ansikter har en .dir klasse) og 1 hvis de er reversert, og har et toppunkt peker ned (disse overflatene har en klasse av .rev)

.dir { –k: 0 }
.rev { –k: 1 }

Den antiprism har 10 lateral ansikter (alle trekanter) peker opp, hver knyttet til en kant av sin decagonal base som også er base for den sammensatte formen. Det har også 10 lateral ansikter (alle trekanter så vel) peker ned, som hver er knyttet til en kant på sin andre decagonal base (det er også decagonal base av rotunda, og er derfor ikke grunnlag for den sammensatte formen).

Rotunda har 10 lateral ansikter peker opp, vekslende trekanter og pentagons, hver knyttet til decagonal base som også er en base for antiprism (så det er ikke et utgangspunkt for den sammensatte formen så godt). Det har også 5 lateral ansikter, alle trekanter, peker ned, som hver er knyttet til en kant av sin pentagonal base.

Interaktiv demo nedenfor gjør oss til bedre å se hver enkelt av disse fire gruppene av ansiktene ved å trykke på kun én av gangen. Du kan bruke pilene nederst for å velge hvilken gruppe av ansikter blir uthevet. Du kan også aktivere rotasjon rundt y-aksen og endre formen er på tilt.

Se Pennen av thebabydino (@thebabydino) på CodePen.

Som tidligere nevnt, den laterale ansikter kan være enten trekanter eller pentagons:

.s3gon { –p: 0 }
.s5gon { –s: 1 }

Siden alle sine lateral ansikter (.lat) av både antiprism og rotunda har en kant til felles med en av de to base ansikter av hver form, kaller vi disse felles kanter base kantene på den laterale ansikter.

Interaktiv demo nedenfor fremhever disse kanter, deres slutt-poeng og sine mid poeng og tillater visning av figurer fra ulike vinkler takk til auto-rotasjoner rundt y-aksen som kan startes/ stoppes midlertidig når som helst, og til manuell rotasjon rundt x-aksen som kan styres via glidere.

Se Pennen av thebabydino (@thebabydino) på CodePen.

For å gjøre ting enklere for oss selv, og vi har satt transform-opprinnelse .lat ansikter på midten av deres base kanter (nederste horisontale kantene).

Fremhever base kantene og deres midtpunkt (live).

Vi også gjøre at vi plasserer disse ansikter slik som å ha disse midtverdiene døde i midten av scenen element som inneholder hele vårt 3D-form.

Etter å ha transform-opprinnelse sammenfaller med midtpunkt-base-edge betyr at alle rotasjon vi utfører på et ansikt kommer til å skje rundt midtpunktet i basen sin kant, illustrert med interaktiv demo nedenfor:

Se Pennen av thebabydino (@thebabydino) på CodePen.

Vi legger vår lateral ansikter der vi vil ha dem til å være i fire trinn:

  1. Vi roterer dem rundt y-aksen slik at deres base kantene er nå parallell til deres endelige posisjoner. (Dette gjelder også roterer sitt lokale system av koordinater — z-aksen av et grunnstoff som alltid peker i den retning at element ansikter.)
  2. Vi oversetter dem slik at deres base kantene sammenfaller med deres siste posisjoner (langs kantene av base ansikter av to komponenter).
  3. Hvis de trenger for å ha et toppunkt peker ned, vi roterer dem rundt z-aksen med en halv omdreining.
  4. Vi roterer dem rundt x-aksen i sitt siste posisjoner

Disse trinnene er illustrert med interaktiv demo nedenfor, der du kan gå gjennom dem og også rotere hele formen (med play/pause-knappen for y-aksen rotasjon og glidebryteren for x-aksen rotasjon).

Se Pennen av thebabydino (@thebabydino) på CodePen.

Y-aksen rotasjon verdi er i hovedsak basert på forsiden indekser og mindre på vår bytte variabler, men det er avhengig av disse som godt.

Strukturen er som følger:

– var n = 5; //- antall kanter/ hjørner av små base

delen.scene
//- 3D-form-element
.s3d
//- ansiktene, hver en 2D-form-element (.s2d)

//- lateral (.lat) antiprism (.mid) ansikter,
//- første halvdel peker opp (.dir), andre peker ned (.rev)
//- alle av dem er trekanter (.s3gon)
– for(var j = 0; j < 4*n; j++)
.s2d.mid.lat.s3gon(class=j < 2*n ? ‘dir’ : ‘rev’)

//- lateral (.lat) rotunden (.cup) ansikter som peker opp (.dir),
//- begge trekantene (.s3gon) og pentagons (.s5gon)
– for(var j = 0; j < n; j++)
.s2d.cup.lat.s3gon.dir
.s2d.cup.lat.s5gon.dir
//- lateral (.lat) rotunden (.cup) ansikter som peker ned (.rev)
//- alle av dem trekanter (.s3gon)
– for(var j = 0; j < n; j++)
.s2d.cup.lat.s3gon.rev

//- base ansikter,
//- en for antiprism (.mid),
//- den andre til rotunda (.cup)
.s2d.mid.base(class=`s${2*n}gon`)
.s2d.cup.base(class=`s${n}gon`)

Som gir oss følgende HTML:

<delen class=”scene”>
<div class=”s3d”>
<!– LATERAL ansikter –>
<div class=”s2d midten av lat s3gon dir”></div>
<!– 9 flere identiske ansikter,
så vi har 10 lateral antiprism ansikter peker oppover –>

<div class=”s2d midten av lat s3gon rev”></div>
<!– 9 flere identiske ansikter,
så vi har 10 lateral antiprism ansikter peker ned –>

<div class=”s2d cup lat s3gon dir”></div>
<div class=”s2d cup lat s5gon dir”></div>
<!– 4 flere identiske par,
så vi har 10 lateral rotunda ansikter peker oppover –>

<div class=”s2d cup lat s3gon rev”></div>
<!– 4 flere identiske ansikter,
så vi har 5 lateral rotunda ansikter peker ned –>

<!– BASE ansikter –>
<div class=”s2d midten av base s10gon”></div>
<div class=”s2d cup base s5gon”></div>
</div>
</avsnitt>

Dette betyr ansikter 0… 9 er 10 lateral antiprism ansikter peker opp, ansiktene 10… 19 10 lateral antiprism ansikter peker ned og vender mot 20… 29 10 lateral rotunda ansikter peker opp, og vender mot 30… 34 5 lateral rotunda ansikter peker ned.

Så hva vi gjør her er å sette et index – –idx på den laterale ansikter.

$n: 5; // antall kanter/ hjørner av små base

.lat {
@for $jeg fra 0 til 2*$n {
&:nth-child(#{2*$n}n + #{$i + 1}) { –idx: #{$jeg} }
}
}

Denne indeksen starter på 0 for hver gruppe av ansikter, noe som betyr at indeksene for ansikter 0… 9, 10… 19 og 20… 29 går fra 0 til 9, mens indeksene for ansikter 30… 34 gå fra 0 til 4. Flott, men hvis vi bare multiplisere disse indeksene med base angle1 av felles decagon for å få y-aksen rotasjon vi vil på dette trinnet:

–ay: calc(var(–idx)*#{$ba10gon});

forvandle: rotatey(var(–ay))

…så får vi følgende endelige resultatet. Jeg viser det endelige resultatet her fordi det er litt vanskelig å se hva som er galt ved å se på middels resultat vi får etter bare søker rotasjon rundt y-aksen.

Se Pennen av thebabydino (@thebabydino) på CodePen.

Dette er… ikke helt hva vi var på vei for!

Så la oss se hvilke problemer over resultatet og hvordan du kan løse dem ved hjelp av vår bytte variabler og boolske operasjoner på dem.

Det første problemet er at de laterale antiprism ansikter peker opp, trenger å bli oppveid av halvparten av en vanlig decagon base vinkel. Dette betyr å legge til eller trekke fra .5 fra –idx før å multiplisere med base vinkel, men kun for disse overflatene.

Se Pennen av thebabydino (@thebabydino) på CodePen.

Ansiktene vi ønsker å målrette er ansiktene som begge –jeg og –k er 0, så er det vi trenger her er multipliser resultatet av deres heller med .5:

–heller: calc((1 – var(–k))*(1 – var(–i)));
–j: calc(var(–idx) + var(–nor)*.5);
–ay: calc(var(–j)*#{$ba10gon});

forvandle: rotatey(var(–ay));

Det andre problemet er at de laterale rotunda ansikter peker ned, er ikke fordelt som de burde være, slik at hver av dem har en base kanten til felles med base pentagon og toppunktet motstanderens base i felles med den trekantede rotunda ansikter peker opp. Dette betyr å multiplisere –idx av 2, men bare for disse overflatene.

Se Pennen av thebabydino (@thebabydino) på CodePen.

Hva vi målretter nå er ansiktene som begge –jeg og –k 1 (så ansiktene som følge av den, og driften er 1), så er det vi trenger er å multiplisere –idx med 1 pluss deres og:

–og: calc(var(–k)*var(–i));
–heller: calc((1 – var(–k))*(1 – var(–i)));
–j: calc((1 + var(–og))*var(–idx) + var(–nor)*.5);
–ay: calc(var(–j)*#{$ba10gon});

forvandle: rotatey(var(–ay));

Neste trinn er oversettelse som vi bruker translate3d(). Vi trenger ikke flytte noen av våre vendt mot venstre eller høyre, så verdien langs x-aksen er alltid 0. Vi flytter dem imidlertid vertikalt (langs y-aksen) og fremover (langs z-aksen)

Vertikalt, vil vi kopp ansikter som senere vil bli rotert til å peke ned til å ha basen sin kant i flyet av de små (pentagonal) bunnen av koppen (og av sammensatte form). Dette betyr ansiktene som-jeg er 1 og –k er 1 får flyttet opp (i negativ retning) halvparten av den totale høyden av den sammensatte formen (en total høyde som vi har beregnet til å være $h). Så vi trenger og drift her.

// samme som før
–og: calc(var(–jeg)*var(–k));
–y: calc(var(–og)*#{-.5*$h});

forvandle: rotatey(var(–ay))
translate3d(0, var(–y, 0), var(–z, 0));

Vi ønsker også alle de andre cup ansikter samt antiprism ansikter som vil til slutt peke ned til å ha basen sin kant i vanlig fly mellom kopp og antiprism. Dette betyr ansiktene som-jeg er 1 og –k er 0, så vel som de ansikter som-jeg er 0 og k –er 1 få oversatt nede (i positiv retning) til det halve høyden på den sammensatte formen og deretter tilbake opp (i negativ retning) til høyden av den antiprism ($h-mid). Og vet du hva, dette er xor drift!

// samme som før
–xor: calc((var(–k) – var(–i))*(var(–k) – var(–i)));
–og: calc(var(–jeg)*var(–k));
–y: calc(var(–xor)*#{.5*$h – $h-midt} –
var(–og)*#{.5*$h});

forvandle: rotatey(var(–ay))
translate3d(0, var(–y, 0), var(–z, 0));

Til slutt, vil vi antiprism ansikter som vil forbli som peker opp til å være i bunnen base fly av den sammensatte formen (og av antiprism). Dette betyr ansiktene som-jeg er 0 og –k er 0, blir oversatt nede (i positiv retning) halvparten av den totale høyden av den sammensatte formen. Så hva vi bruker her er heller drift!

// samme som før
–heller: calc((1 – var(–k))*(1 – var(–i)));
–xor: calc((var(–k) – var(–i))*(var(–k) – var(–i)));
–og: calc(var(–jeg)*var(–k));

–y: calc(var(–nor)*#{.5*$h} +
var(–xor)*#{.5*$h – $h-midt} –
var(–og)*#{.5*$h});

forvandle: rotatey(var(–ay))
translate3d(0, var(–y, 0), var(–z, 0));

Se Pennen av thebabydino (@thebabydino) på CodePen.

Langs z-retning, vi ønsker å flytte ansikter slik at deres base kantene sammenfaller med kantene av base ansikter av den sammensatte formen, eller kantene av felles base (som ikke er et ansikt av den sammensatte formen) som deles av de to 3D-komponenter. Til toppen ansikter av koppen (som vi senere roter til å peke nedover), og plasseringen er på kanten av en pentagon, mens for alle de andre ansiktene til de sammensatte form, plassering er på kanten av en decagon.

Dette betyr ansiktene som-jeg er 1 og –k er 1 få oversatt frem av inradius av pentagonal base mens alle de andre ansiktene få oversatt frem av inradius av en decagonal base. Så de operasjoner vi trenger her er og og nand!

// samme som før
–og: calc(var(–jeg)*var(–k));
–nand: calc(1 – var(–og));
–z: calc(var(–og)*#{$ri5gon} + var(–nand -)*#{$ri10gon});

forvandle: rotatey(var(–ay))
translate3d(0, var(–y, 0), var(–z, 0));

Se Pennen av thebabydino (@thebabydino) på CodePen.

Neste, vi ønsker å gjøre alle .rev (som –k er 1) vender peker ned. Dette er ganske enkel og krever ikke noen logisk drift, vi trenger bare å legge til en halv omdreining rotasjon rundt z-aksen til å forvandle kjede, men bare for ansikter som –k er 1:

// samme som før
–az: calc(var(–k)*.5turn);

forvandle: rotatey(var(–ay))
translate3d(0, var(–y), var(–z))
roter(var(–az));

Se Pennen av thebabydino (@thebabydino) på CodePen.

Pentagonal ansikter (som –p er 1) er da alle rotert rundt x-aksen med en viss vinkel:

–ax: calc(var(–p)*#{$ax5});

I tilfelle av den trekantede ansikter (som –p er 0, som betyr at vi trenger å bruke –notp), vi har en viss rotasjon vinkel til ansikter av antiprism ($ax3-mid), en annen vinkel til ansikter av rotunda som peker opp ($ax3-cup-dir) og enda en annen vinkel for rotunda ansikter peker ned ($ax3-kopp-rød).

Den antiprism ansiktene er de som-jeg er 0, så vi trenger å multiplisere deres tilsvarende vinkel verdi med –noti her. Rotunda ansiktene er de som-jeg er 1, og ut av disse, de peker opp, er de som –k er 0, og de peker ned, er de som –k er 1.

–notk: calc(1 – var(–k));
–noti: calc(1 – var(–i));
–notp: calc(1 – var(–p));

–ax: calc(var(–notp)*(var(–noti)*#{$ax3-midt} +
var(–i)*(var(–notk)*#{$ax3-cup-dir} + var(–k)*#{$ax3-cup-rev})) +
var(–p)*#{$ax5});

forvandle: rotatey(var(–ay))
translate3d(0, var(–y), var(–z))
roter(var(–az))
rotatex(var(–ax));

Dette gir oss det endelige resultatet!

Se Pennen av thebabydino (@thebabydino) på CodePen.

1 For ethvert regulært polygon (for eksempel noen av ansiktene våre-figurer), arc tilsvarende en kant, samt vinkelen mellom circumradii til denne kanten er ferdig (vår base vinkel) er en full sirkel (360°) over antall kanter. I tilfelle av en likesidet trekant, vinkelen er 360°/3 = 120°. For en vanlig pentagon, vinkelen er 360°/5 = 72°. For en vanlig decagon, vinkelen er 360°/10 = 36°. ↪️

Se Pennen av thebabydino (@thebabydino) på CodePen.