Logiska Operationer med CSS Variabler

0
6

Mycket ofta, när du använder switch-variabler (en variabel som är antingen 0 eller 1, ett begrepp som förklaras mer i detalj i detta inlägg), jag önskar att jag kunde utföra logiska operationer på dem. Vi har inte funktioner som inte är(var (- jag)) eller(var (- jag), var(–k)) i CSS, men vi kan efterlikna dessa och fler med aritmetiska operationer i en calc () – funktionen.

Denna artikel kommer att visa dig vad calc() formler som vi behöver använda för varje logisk operation och förklara hur och varför de används med ett par användningsfall som leder till skrivandet av denna artikel.

Hur: de formler

inte

Detta är en ganska enkel: vi subtrahera byta variabel (låt oss kalla det –j) från och med den 1:

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

Om –j är 0, då –notj är 1 (1 – 0). Om j är 1, då –notj är 0 (1 – 1).

och

Nu, om du någonsin tagit elektronik klasser (särskilt något som finns Inprogrammerat Logic System eller Integrerade Kretsar), då vet du redan vad formeln måste vi använda här. Men låt oss inte hoppa rakt in i den.

Och två operander är sant om och endast om båda är sanna. De två operander i vårt fall är två växla variabler (låt oss kalla dem-k –och jag). Var och en av dem kan vara antingen 0 eller 1, oberoende av de andra. Detta innebär att vi kan vara i en av fyra möjliga scenarier:

  • –k: 0, –jag: 0
  • –k: 0, –jag: 1
  • –k: 1, –jag: 0
  • –k: 1, –jag: 1

Resultatet av operationen är 1 om både våra byta variabler är 1 och 0 annars. Titta på det andra sättet, det här resultatet är 0 om minst ett av de två byta variabler är 0.

Nu måste du tänka på det här sättet: resultatet av det aritmetiska operationen är 0 om minst ett av de två operander är 0? Det är multiplikation, som att multiplicera allt med 0 ger 0 oss!

Så, våra –och formeln är:

–och: calc(var(–k)*var (- jag))

Med tanke på alla våra fyra möjliga scenarier, som vi har:

  • för –k: 0, –jag: 0, vi har det-och är 0 (0*0)
  • för –k: 0, –jag: 1, har vi det-och är 0 (0*1)
  • för –k: 1, –jag: 0, vi har det-och är 0 (1*0)
  • för –k: 1, –jag: 1, har vi det-och är 1 (1*1)

nand

Eftersom nand är inte, och vi behöver ersätta den –j i inte formel formeln för och:

–nand: calc(1 – var(–k)*var (- jag))

För vart och ett av våra fyra möjliga scenarier, får vi:

  • för –k: 0, –jag: 0, har vi att-nand är 1 (1 – 0*0 = 1 – 0)
  • för –k: 0, –jag: 1, har vi det-nand är 1 (1 – 0*1 = 1 – 0)
  • för –k: 1, –jag: 0, har vi att-nand är 1 (1 – 1*0 = 1 – 0)
  • för –k: 1, –jag: 1, har vi det-nand är 0 (1 – 1*1 = 1 – 1)

eller

Ett resultat av eller-operation är 1 om minst en av våra byta variabler är 1 och 0 annars (om båda är 0).

Den första instinkt här är att gå för addition, men samtidigt att det ger oss 0 om båda –k och –jag är 0 och 1 om man är 0 och den andra är 1, det ger oss 2 om båda av dem är 1. Så det fungerar inte riktigt.

Men vi kan använda den gamla goda De Morgans lagar, av vilka den ena står:

inte (A eller B) = (inte A) och (B)

Detta innebär att resultat av eller-operation är negationen av och samarbete mellan hopp i –k –och jag. Att sätta detta i CSS, vi har:

– eller: calc(1 – (1 – var(–k))*(1 – var – (- jag)))

För varje scenario, får vi:

  • för –k: 0, –jag: 0, har vi att –eller är 0 (1 – (1 – 0)*(1 – 0) = 1 – 1*1 = 1 – 1)
  • för –k: 0, –jag: 1, har vi det-eller är 1 (1 – (1 – 0)*(1 – 1) = 1 – 1*0 = 1 – 0)
  • för –k: 1, –jag: 0, har vi att –eller är 1 (1 – (1 – 1)*(1 – 0) = 1 – 0*1 = 1 – 0)
  • för –k: 1, –jag: 1, har vi det-eller är 1 (1 – (1 – 1)*(1 – 1) = 1 – 0*0 = 1 – 0)

eller

Eftersom det heller inte är, eller har vi:

–inte heller: calc((1 – var(–k))*(1 – var – (- jag)))

För vart och ett av våra fyra möjliga scenarier, får vi:

  • för –k: 0, –jag: 0, har vi att –eller är 1 ((1 – 0)*(1 – 0) = 1*1)
  • för –k: 0, –jag: 1, har vi det-eller är 0 ((1 – 0)*(1 – 1) = 1*0)
  • för –k: 1, –jag: 0, har vi att –eller är 0 ((1 – 1)*(1 – 0) = 0*1)
  • för –k: 1, –jag: 1, har vi det-eller är 0 ((1 – 1)*(1 – 1) = 0*0)

xor

Resultatet av xor-operation är 1 när en av de två operander är 1 och den andra är 0. Detta känns svårare i början, men om vi tror att detta innebär att de två operander måste vara olika för att resultatet skall vara 1, annars 0), vi snubblar rätt aritmetisk operation för att använda inomhus calc(): subtraktion!

Om –k –och jag är lika, då subtrahera –i –k ger oss 0. Annars, om vi har –k: 0, –jag: 1, resultatet av samma subtraktion är -1, om vi har –k: 1, –jag: 0, resultatet är 1.

Nära, men inte riktigt! Vi får det resultat vi vill ha i tre av fyra scenarier, men vi behöver få med 1, inte -1 i –k: 0, –jag: 1 scenario.

Men, en sak som -1, 0 och 1 har gemensamt är att multiplicera dem med sig själva och ger oss deras absoluta värde (som är 1 för både -1 och 1). Så den verkliga lösningen är att multiplicera denna skillnad med sig själv:

–xor: calc((var(–k) – var – (- jag))*(var(–k) – var – (- jag)))

Testa alla våra fyra möjliga scenarier, som vi har:

  • för –k: 0, –jag: 0, har vi att –xor är 0 ((0 – 0)*(0 – 0) = 0*0)
  • för –k: 0, –jag: 1, har vi som –xor är 1 ((0 – 1)*(0 – 1) = -1*-1)
  • för –k: 1, –jag: 0, har vi att –xor är 1 ((1 – 0)*(1 – 0) = 1*1)
  • för –k: 1, –jag: 1, har vi som –xor är 0 ((1 – 1)*(1 – 1) = 0*0)

Varför: Använd fall

Låt oss se ett par exempel för att göra användningen av logiska operationer i CSS. Observera att jag kommer inte i detalj andra aspekter av dessa demos som de är utanför omfånget för denna artikel.

Dölj funktionshindrade panelen endast på små skärmar

Detta är en händelse kom jag över medan du arbetar på en interaktiv demo som låter användare styra olika parametrar för att ändra ett visuellt resultat. För mer kunnig användare, det är också en panel av avancerade kontroller som är inaktiverat som standard. Det kan dock vara aktiverad för att få tillgång till manuellt styra ännu fler parametrar.

Eftersom denna demo är tänkt att vara lyhörd, layout förändringar med det virtuella. Vi behöver inte vill att saker ska bli proppfull på mindre skärmar om vi kan undvika det, så det finns ingen poäng i att visa de avancerade kontroller om de är funktionshindrade och vi är i den smala skärmen fall.

Skärmdump collage nedan visar de resultat vi får för alla de fyra möjliga scenarier.

Collage av möjliga fall.

Så låt oss se vad detta innebär i form av CSS!

Först ut, på <body> – vi använder en switch som går från 0 i den smala skärmen fall till 1 i den breda skärmen fall. Vi också ändra flex-riktning det här sättet (om du vill ha en mer detaljerad förklaring av hur det fungerar, kolla in min andra artikel på TORR byta med CSS-variabler).

body {
–k: var(–bred, 0);
display: flex;
flex-riktning: var(–bred, kolumn);

@media (orientering: liggande) { –bred: 1 }
}

Sedan har vi en andra slår du på avancerade kontroller på panelen. Denna andra växeln är 0 om kryssrutan är avmarkerad och 1 om den här kryssrutan är :kontrolleras. Med hjälp av denna övergång, vi ger våra avancerade kontroller panel för en funktionshindrad att se (via ett filter kedja) och vi också inaktivera det (via pekaren-händelser). Här, inte kommer väl till pass, eftersom vi vill minska kontrasten och opacitet, funktionshindrade fall:

.avancerad {
–jag: var(–aktiverad, 0);
–anmälda: calc(1 – var(–i));
filter:
kontrast(calc(1 – var(–anmälda)*.9))
opacitet(calc(1 – var(–anmälda)*.7));
pekare-händelser: var(–aktiverad, ingen);

[id=’växla’]:kollade ~ & { –aktiverad: 1 }
}

Vi vill att de avancerade kontrollerna på panelen för att stanna utvidgas om vi är i widescreen fall (så om –k är 1) oberoende av om kryssrutan är :kontrolleras eller inte, eller om kryssrutan är :är markerad (så om –jag är 1) oberoende av om vi är i widescreen fallet eller inte.

Det är just den eller drift!

Så vi beräkna ett-eller variabla:

.avancerad {
/* samma som innan */
– eller: calc(1 – (1 – var(–k))*(1 – var(–i)));
}

Om detta –eller variabeln är 0 betyder det att vi är i den smala skärmen mål och vår kryssrutan är avmarkerad, så vi vill noll höjden av avancerade kontroller panel och även dess vertikala marginal:

.avancerad {
/* samma som innan */
marginal: calc(var(–eller)*#{$mv}) 0;
höjd: calc(var(–eller)*#{$h});
}

Detta ger oss det önskade resultatet (demo).

Använd samma formler för att placera flera ansikten av en 3D-form

Detta är en händelse kom jag över medan du arbetar på det personliga projektet av CSS-ing Johnson fasta ämnen i sommar.

Låt oss ta en titt på en av dessa former, till exempel gyroelongated femsidig rotunda (25), för att se hur logiska operationer är användbara här.

Den form vi vill ha.

Denna form består av en femsidig rotunda utan stora decagonal bas och en decagonal antiprism utan dess topp decagon. Interaktiv demo nedan visar hur dessa två komponenter kan byggas genom att vika sina nät av ansikten i 3D och gick sedan för att ge oss den form vi vill ha.

Se Pennan genom att thebabydino (@thebabydino) på CodePen.

Som kan ses ovan, ansikten är antingen en del av antiprism eller en del av rotunda. Det är där vi presentera vår första växla variabel –jag. Den här är 0 för ansikten som är en del av antiprism och 1 för ansikten som är en del av rotunda. Den antiprism ansikten har en klass av .mid eftersom vi kan lägga till ytterligare rotunda till andra antiprism bas och sedan antiprism skulle vara i mitten. Rotundan ansikten har en klass av .bägare eftersom denna del inte se ut som en kopp kaffe… utan handtag!

Rotundan ser ut som en upp och ner upp kopp utan handtag.

.mid { –i: 0 }
.cup { –jag: 1 }

Att fokusera enbart på den laterala ansikten, dessa kan ha en vertex som pekar upp eller ner. Det är där vi presentera vår andra variabeln –k. Detta är 0 om de har en brytpunkt som pekar uppåt (dessa ansikten har en .dir klass) och 1 om de är omvända och har en vertex pekar nedåt (dessa ansikten har en klass av .rev)

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

Den antiprism har 10 sidoytor (alla trianglar) som pekar upp, varje ansluten till en kant av sin decagonal bas som är också en bas för den sammansatta formen. Det har också 10 sidoytor (alla trianglar som också) som pekar nedåt, varje ansluten till en kant på sin andra decagonal bas (som också decagonal basen av rotunda och är därför inte en bas för den sammansatta formen).

Rotundan har 10 sidoytor som pekar upp, omväxlande trianglar och pentagoner, varje ansluten till decagonal bas som är också en bas för antiprism (så det är inte en bas för den sammansatta formen också). Det har också 5 sidoytor, alla trianglar, som pekar nedåt, varje ansluten till en kant av sin femsidig bas.

Interaktiv demo nedan tillåter oss att bättre se var och en av dessa fyra grupper av ansikten genom att markera en i taget. Du kan använda pilarna längst ner för att välja vilken grupp av ansikten blir markerat. Du kan också aktivera rotation kring y-axeln och ändra form lutning.

Se Pennan genom att thebabydino (@thebabydino) på CodePen.

Som tidigare nämnts, sidoytor, kan vara antingen trianglar eller pentagoner:

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

Eftersom alla sina sidoytor (.lat) av både antiprism och rotundan har en kant i likhet med en av de två bas ansikten i varje form, vi kallar dessa för gemensamma kanter basen kanterna av sidoytor.

Interaktiv demo nedan visar dessa kanter, sina slutpunkter och deras mitten av poäng och möjliggör visning former från olika vinklar tack vare den auto-rotationer runt y-axeln som kan startas/ pausade vid varje tidpunkt och att den manuella rotationer runt x-axeln, vilket kan kontrolleras via reglagen.

Se Pennan genom att thebabydino (@thebabydino) på CodePen.

För att göra saker enklare för oss själva, som vi förändra-ursprung .lat ansikten på mitten av deras bas kanter (nedre horisontella kanter).

Att belysa bas kanter och deras mittpunkter (live).

Vi också se till att vi placerar dessa ansikten som att ha dessa mittpunkter död i mitten av scenen element som innehåller hela vårt 3D-form.

Med transform-ursprung sammanfaller med mittpunkten basen kant innebär att någon rotation som vi utför på ett ansikte som kommer att hända runt mittpunkten av sin bas kanten, vilket framgår av den interaktiva demo nedan:

Se Pennan genom att thebabydino (@thebabydino) på CodePen.

Vi lägger vår sidoytor, där vi vill ha dem i fyra steg:

  1. Vi rotera dem runt deras y-axeln så att deras bas kanter är nu parallell till sina slutliga positioner. (Detta gäller även roterar sina lokala koordinatsystemet — z-axeln i ett element pekar alltid i den riktning som objektet står inför.)
  2. Vi översätta dem så att deras bas kanter sammanfaller med deras slutliga positioner (längs kanterna av bas ansikten av två komponenter).
  3. Om de måste ha en vertex som pekar nedåt, vi rotera dem runt z-axeln med ett halvt varv.
  4. Vi rotera dem runt x-axeln i sina slutliga positioner

Dessa åtgärder är illustrerad av den interaktiva demo nedan, där du kan gå igenom dem och även rotera hela formen (med play/paus-knappen för y-axelns rotation och reglaget för x-axelns rotation).

Se Pennan genom att thebabydino (@thebabydino) på CodePen.

Y-axis rotation värde är baserat främst på face index och mindre på våra byta variabler, men det beror på dessa också.

Strukturen är följande:

– var n = 5; / / antal kanter/ hörn för liten bas

avsnitt.scen
//- 3D-form element
.s3d
//- ansikten, var och en 2D-form element (.s2d)

//- laterala (.lat) antiprism (.i mitten) ansikten,
//- första halvåret pekar uppåt (.dir), andra pekar nedåt (.rev)
//- alla av dem är trianglar (.s3gon)
– for(var j = 0; j < 4*n; j++)
.s2d.mid.lat.s3gon(class=j < 2*n ? ‘dir’ : ‘rev’)

//- laterala (.lat) rotunda (.cup) ansikten som punkt (.dir),
//- både trianglar (.s3gon) och pentagoner (.s5gon)
– for(var j = 0; j < n; j++)
.s2d.cupen.lat.s3gon.dir
.s2d.cupen.lat.s5gon.dir
//- laterala (.lat) rotunda (.cup) ansikten att peka nedåt (.rev)
//- alla av dem trianglar (.s3gon)
– for(var j = 0; j < n; j++)
.s2d.cupen.lat.s3gon.rev

//- bas ansikten,
//- en för antiprism (.i mitten),
//- andra för rotundan (.cup)
.s2d.mid.bas(class=`s${2*n}gon`)
.s2d.cupen.bas(class=`s${n}gon`)

Vilket ger oss följande HTML HTML:

<section class=”scenen”>
<div class=”s3d”>
<!– Sidoytor, — >
<div class=”s2d mitten av lat s3gon dir”></div>
<!– 9 fler identiska ansikten,
så vi har 10 lateral antiprism ansikten pekar uppåt –>

<div class=”s2d mitten av lat s3gon rev”></div>
<!– 9 fler identiska ansikten,
så vi har 10 lateral antiprism ansikten som pekar nedåt –>

<div class=”s2d kopp lat s3gon dir”></div>
<div class=”s2d kopp lat s5gon dir”></div>
<!– 4 fler identiska par,
så vi har 10 lateral rotunda ansikten pekar uppåt –>

<div class=”s2d kopp lat s3gon rev”></div>
<!– 4 fler identiska ansikten,
så vi har 5 lateral rotunda ansikten som pekar nedåt –>

<!– BAS ansikten –>
<div class=”s2d mitten av bas s10gon”></div>
<div class=”s2d cup bas s5gon”></div>
</div>
</section>

Detta innebär ansikten 0… 9 10 lateral antiprism ansikten som pekar upp, ansikten 10… 19 är 10 lateral antiprism ansikten som pekar nedåt, ansikten 20… 29 är de 10 lateral rotunda ansikten som pekar upp och ansikten 30… 34 5 lateral rotunda ansikten som pekar nedåt.

Så vad vi gör här ligger ett index –idx på sidoytor.

$n: 5; // antalet kanter/ hörn för liten bas

.lat {
@och $jag från 0 till 2*$n {
&:nth-child(#{2*$n}n + #{$i + 1}) { –idx: #{$i} }
}
}

Detta index börjar på 0 för varje grupp av ansikten, vilket innebär att index för ansikten 0… 9, 10… 19 och 20… 29 gå från 0 till 9, medan index för ansikten 30… 34 gå från 0 till 4. Bra, men om vi bara multiplicera dessa index med bas angle1 av den gemensamma decagon att få y axis rotation vi vill i detta steg:

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

förändra: rotatey(var(–ay))

…då får vi följande slutliga resultatet. Jag visar det slutliga resultatet här eftersom det är lite svårt att se vad som är fel genom att titta på de mellanliggande resultatet vi får efter endast tillämpar rotation kring y-axeln.

Se Pennan genom att thebabydino (@thebabydino) på CodePen.

Detta är… inte riktigt vad vi går för!

Så låt oss se vilka problem ovanstående resultat har och hur man kan lösa dem med hjälp av våra byta variabler och booleska operationer på dem.

Den första frågan är att den laterala antiprism ansikten som pekar upp måste kunna kompenseras av hälften av en vanlig decagon bas vinkel. Detta innebär att addera eller subtrahera .5 från –idx innan multiplicera med bas vinkel, men bara för dessa ytor.

Se Pennan genom att thebabydino (@thebabydino) på CodePen.

De ansikten vi vill att målet är ansikten som både för-i och –k är 0, så vad vi behöver här är multiplicera resultatet av deras heller .5:

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

förändra: rotatey(var(–ay));

Den andra frågan är att den laterala rotunda ansikten som pekar nedåt finns inte ut som de borde vara, så att var och en av dem har en bas kanten gemensamt med bas pentagon och vertex motsatta basen i likhet med de trekantiga rotunda ansikten som pekar uppåt. Detta innebär att multiplicera –idx med 2, men endast för dessa ytor.

Se Pennan genom att thebabydino (@thebabydino) på CodePen.

Vad vi riktar nu är ansikten som både –och jag –k 1 (så de ansikten som resultat av den och drift 1), så vad vi behöver är att multiplicera –idx med 1 plus sina och:

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

förändra: rotatey(var(–ay));

Nästa steg är den översättning som vi använder translate3d(). Vi behöver inte flytta någon av våra ansikten vänster eller höger, så värdet längs x-axeln är alltid 0. Vi gör flytta dem dock vertikalt (längs y-axeln) och framåt (längs z-axeln)

Vertikalt, vi vill cup ansikten som kommer senare får vridas för att peka nedåt för att ha sin bas kant i planet av den lilla (femsidig) bas cup (och sammansatta form). Detta innebär att de ansikten som –jag är 1 och –k 1 flyttas upp (i negativ riktning) med hälften av det totala höjden för den sammansatta formen (en total höjd som vi har beräknat att vara $h). Så vi behöver och drift här.

// samma som innan
–och: calc(var (- jag)*var(–k));
–y: calc(var(–och)*#{-.5*$h});

förändra: rotatey(var(–ay))
translate3d(0, var(–y, 0), var(–z, 0));

Vi vill också att alla andra kopp ansikten liksom antiprism ansikten som så småningom kommer att peka nedåt för att ha sin bas kanten i den gemensamma planet mellan cup och antiprism. Detta innebär att de ansikten som –jag är 1 och –k är 0 samt ansikten som –jag är 0 och –k 1 översatta ner (i positiv riktning) från halva höjden av den sammansatta formen och sedan tillbaka upp (i negativ riktning) av höjd antiprism ($h-i mitten). Och vet ni vad, detta är xor-operation!

// samma som innan
–xor: calc((var(–k) – var – (- jag))*(var(–k) – var(–i)));
–och: calc(var (- jag)*var(–k));
–y: calc(var(–xor)*#{.5*$h – $h-mitten av} –
var(–och)*#{.5*$h});

förändra: rotatey(var(–ay))
translate3d(0, var(–y, 0), var(–z, 0));

Slutligen, vi vill antiprism ansikten som kommer att vara kvar pekande upp för att vara i botten bas plan sammansatt form (och antiprism). Detta innebär att de ansikten som –jag är 0 och –k är 0 blir översatta ner (i positiv riktning) med hälften av det totala höjden för den sammansatta formen. Så vad vi här använder oss av är inte heller drift!

// samma som innan
–inte heller: calc((1 – var(–k))*(1 – var(–i)));
–xor: calc((var(–k) – var – (- jag))*(var(–k) – var(–i)));
–och: calc(var (- jag)*var(–k));

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

förändra: rotatey(var(–ay))
translate3d(0, var(–y, 0), var(–z, 0));

Se Pennan genom att thebabydino (@thebabydino) på CodePen.

Längs z-riktning, vi vill flytta ansikten så att deras bas kanter sammanfaller med kanter av bas ansikten förening form eller i kanterna av den gemensamma basen (som inte är ett ansikte av den sammansatta formen) som delas av de två 3D-komponenter. Till toppen ansikten cup (som vi senare kom att rotera för att peka nedåt), placeringen är på kanterna av en pentagon, medan alla andra sidor av den sammansatta formen, placeringen är på kanterna av en decagon.

Detta innebär att de ansikten som –jag är 1 och –k 1 översatta fram av inradius av femsidig bas, medan alla andra står inför att få översatt fram av inradius av en decagonal bas. Så den verksamhet vi behöver här är och och nand!

// samma som innan
–och: calc(var (- jag)*var(–k));
–nand: calc(1 – var(–och));
–z: calc(var(–och)*#{$ri5gon} + var(–nand)*#{$ri10gon});

förändra: rotatey(var(–ay))
translate3d(0, var(–y, 0), var(–z, 0));

Se Pennan genom att thebabydino (@thebabydino) på CodePen.

Nästa, vi vill göra allt .rev (för som –k 1) ansikten peka nedåt. Detta är ganska enkelt och kräver inte någon logisk operation, behöver vi bara lägga till ett halvt varv rotation kring z-axeln för att förändra den kedjan, men bara för de ansikten som –k är 1:

// samma som innan
–az: calc(var(–k)*.5turn);

förändra: rotatey(var(–ay))
translate3d(0, var(–y), var(–z))
rotera(var(–az));

Se Pennan genom att thebabydino (@thebabydino) på CodePen.

Femsidig ansikten (som –p-1) är då alla roteras kring x-axeln med en viss vinkel:

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

I fallet av den triangulära ytor (för som –p är 0, vilket betyder att vi måste använda –notp), vi har en viss rotation vinkeln för ansikten antiprism ($ax3-mid), en annan vinkel för ansikten rotunda att peka uppåt ($ax3-cup-dir) och ännu en annan vinkel för rotundan ansikten som pekar nedåt ($ax3-cup-röd).

Den antiprism ansikten är sådana där –jag är 0, så måste vi multiplicera deras motsvarande vinkel värde med –anmälda här. Rotundan ansikten är sådana där –jag är 1, och av alla dessa, de som pekar uppåt är de som –k är 0 och de som pekar nedåt, är de som –k är 1.

–notk: calc(1 – var(–k));
–anmälda: calc(1 – var(–i));
–notp: calc(1 – var (- p));

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

förändra: rotatey(var(–ay))
translate3d(0, var(–y), var(–z))
rotera(var(–az))
rotatex(var(–ax));

Detta ger oss det slutliga resultatet!

Se Pennan genom att thebabydino (@thebabydino) på CodePen.

1 För någon regelbunden polygon (som något av ansiktena från våra former), arc motsvarar en kant, samt vinkeln mellan circumradii att detta edge är slut (vår bas vinkel) är ett helt varv (360°) över antalet kanter. I fallet av en liksidig triangel har en vinkel 360°/3 = 120°. För en regelbunden femhörning, vinkeln är 360°/5 = 72°. För en vanlig decagon, vinkeln är 360°/10 = 36°. ↪️

Se Pennan genom att thebabydino (@thebabydino) på CodePen.