Pentru acest al patrulea și ultim articol al nostru serie mică pe încărcătoare cu un singur element, vom explora modele 3D. Când creați un element 3D, este greu de imaginat că un singur element HTML este suficient pentru a simula ceva ca toate cele șase fețe ale unui cub. Dar poate putem scăpa cu ceva mai cub-ca în schimb, arătând doar cele trei părți din față ale formei - este total posibil și asta vom face împreună.
Seria de articole
- Încărcătoare cu un singur element: Spinner
- Încărcătoare cu un singur element: punctele
- Încărcătoare cu un singur element: Barele
- Încărcătoare cu un singur element: Trecerea în 3D — Eşti aici
Încărcătorul de cuburi divizate
Iată un încărcător 3D în care un cub este împărțit în două părți, dar este realizat doar cu un singur element:
Fiecare jumătate a cubului este realizată folosind un pseudo-element:
Cool, nu?! Putem folosi un gradient conic cu CSS clip-path
pe elementul ::before
și ::after
pseudos pentru a simula cele trei fețe vizibile ale unui cub 3D. Marja negativă este ceea ce trage cele două pseudo-uri împreună pentru a se suprapune și a simula un cub plin. Restul muncii noastre este în principal animarea celor două jumătăți pentru a obține încărcătoare cu aspect frumos!
Să verificăm o imagine care explică matematica din spatele punctelor traseului de clipare utilizate pentru a crea acest element asemănător cubului:
Avem variabilele noastre și o ecuație, așa că să le punem la lucru. Mai întâi, vom stabili variabilele noastre și vom stabili dimensionarea pentru principal .loader
element:
.loader { --s: 150px; /* control the size */ --_d: calc(0.353 * var(--s)); /* 0.353 = sin(45deg)/2 */ width: calc(var(--s) + var(--_d)); aspect-ratio: 1; display: flex;
}
Nimic prea nebunesc până acum. Noi avem o 150px
pătrat care este configurat ca un container flexibil. Acum stabilim pseudo-urile noastre:
.loader::before,
.loader::after { content: ""; flex: 1;
}
Acestea sunt două jumătăți în .loader
recipient. Trebuie să le pictăm, așa că acolo este locul nostru gradient conic lansează:
.loader::before,
.loader::after { content: ""; flex: 1; background: conic-gradient(from -90deg at calc(100% - var(--_d)) var(--_d), #fff 135deg, #666 0 270deg, #aaa 0);
}
Gradientul este acolo, dar pare ciudat. Avem nevoie să prindeți-o de element:
.loader::before,
.loader::after { content: ""; flex: 1; background: conic-gradient(from -90deg at calc(100% - var(--_d)) var(--_d), #fff 135deg, #666 0 270deg, #aaa 0); clip-path: polygon(var(--_d) 0, 100% 0, 100% calc(100% - var(--_d)), calc(100% - var(--_d)) 100%, 0 100%, 0 var(--_d));
}
Să ne asigurăm că cele două jumătăți se suprapun cu a marja negativa:
.loader::before { margin-right: calc(var(--_d) / -2);
} .loader::after { margin-left: calc(var(--_d) / -2);
}
Acum să-i facem să se miște!
.loader::before,
.loader::after { /* same as before */ animation: load 1.5s infinite cubic-bezier(0, .5, .5, 1.8) alternate;
} .loader::after { /* same as before */ animation-delay: -.75s
} @keyframes load{ 0%, 40% { transform: translateY(calc(var(--s) / -4)) } 60%, 100% { transform: translateY(calc(var(--s) / 4)) }
}
Iată încă o dată demonstrația finală:
Încărcătorul de cuburi de progres
Să folosim aceeași tehnică pentru a crea un încărcător de progres 3D. Da, tot un singur element!
Nu modificăm nimic în ceea ce privește simularea cubului în același mod în care am făcut-o înainte, în afară de modificarea înălțimii încărcătorului și a raportului de aspect. Animația pe care o facem se bazează pe o tehnică surprinzător de ușoară în care actualizăm lățimea părții stângi, în timp ce partea dreaptă umple spațiul rămas, datorită flex-grow: 1
.
Primul pas este să adăugați puțină transparență în partea dreaptă folosind opacity
:
Aceasta simulează efectul că o parte a cubului este umplută în timp ce cealaltă este goală. Apoi actualizăm culoarea părții stângi. Pentru a face asta, fie actualizăm cele trei culori din interiorul gradientului conic, fie o facem adăugând o culoare de fundal cu un background-blend-mode
:
.loader::before { background-color: #CC333F; /* control the color here */ background-blend-mode: multiply;
}
Acest truc ne permite să actualizăm culoarea o singură dată. Partea dreaptă a încărcătorului se îmbină cu cele trei nuanțe de alb din gradientul conic pentru a crea trei nuanțe noi ale culorii noastre, chiar dacă folosim o singură valoare a culorii. Înșelătorie de culoare!
Să animăm lățimea părții stângi a încărcătorului:
Hopa, animația este puțin ciudată la început! Observați cum începe în afara cubului? Acest lucru se datorează faptului că începem animația la 0%
lăţime. Dar din cauza clip-path
și marja negativă pe care o folosim, ceea ce trebuie să facem este să începem de la noi --_d
variabilă, pe care am folosit-o pentru a defini clip-path
puncte și marja negativă:
@keyframes load { 0%, 5% {width: var(--_d); } 95%, 100% {width: 100%; }
}
E puțin mai bine:
Dar putem face această animație și mai lină. Ai observat că ne lipsește ceva? Permiteți-mi să vă arăt o captură de ecran pentru a compara cum ar trebui să arate demonstrația finală cu ultima demonstrație:
Este partea de jos a cubului! Deoarece al doilea element este transparent, trebuie să vedem fața de jos a dreptunghiului, așa cum puteți vedea în exemplul din stânga. Este subtil, dar ar trebui să fie acolo!
Putem adăuga un gradient la elementul principal și îl putem tăia așa cum am făcut cu pseudo-urile:
background: linear-gradient(#fff1 0 0) bottom / 100% var(--_d) no-repeat;
Iată codul complet odată ce totul este strâns:
.loader { --s: 100px; /* control the size */ --_d: calc(0.353*var(--s)); /* 0.353 = sin(45deg) / 2 */ height: var(--s); aspect-ratio: 3; display: flex; background: linear-gradient(#fff1 0 0) bottom / 100% var(--_d) no-repeat; clip-path: polygon(var(--_d) 0, 100% 0, 100% calc(100% - var(--_d)), calc(100% - var(--_d)) 100%, 0 100%, 0 var(--_d));
}
.loader::before,
.loader::after { content: ""; clip-path: inherit; background: conic-gradient(from -90deg at calc(100% - var(--_d)) var(--_d), #fff 135deg, #666 0 270deg, #aaa 0);
}
.loader::before { background-color: #CC333F; /* control the color here */ background-blend-mode: multiply; margin-right: calc(var(--_d) / -2); animation: load 2.5s infinite linear;
}
.loader:after { flex: 1; margin-left: calc(var(--_d) / -2); opacity: 0.4;
} @keyframes load { 0%, 5% { width: var(--_d); } 95%, 100% { width: 100%; }
}
Asta este! Am folosit doar o tehnică inteligentă care folosește pseudo-elemente, gradienți conici, tăiere, amestecare de fundal și margini negative pentru a obține, nu unul, ci Două încărcătoare 3D cu aspect plăcut, cu nimic mai mult decât un singur element în marcaj.
Mai mult 3D
Putem merge mai departe și să simulăm un număr infinit de cuburi 3D folosind un singur element - da, este posibil! Iată o grilă de cuburi:
Această demonstrație și următoarele demonstrații nu sunt acceptate în Safari în momentul scrierii.
Nebun, nu? Acum creăm un model repetat de cuburi realizate folosind un singur element... și nici pseudos! Nu voi intra în detalii fine despre matematica pe care o folosim (există numere foarte specifice acolo), dar iată o cifră pentru a vizualiza cum am ajuns aici:
Mai întâi folosim a conic-gradient
pentru a crea modelul cub care se repetă. Repetarea modelului este controlată de trei variabile:
--size
: Adevărat numelui său, aceasta controlează dimensiunea fiecărui cub.--m
: Acesta reprezintă numărul de coloane.--n
: Acesta este numărul de rânduri.--gap
: acesta este decalajul sau distanța dintre cuburi
.cube { --size: 40px; --m: 4; --n: 5; --gap :10px; aspect-ratio: var(--m) / var(--n); width: calc(var(--m) * (1.353 * var(--size) + var(--gap))); background: conic-gradient(from -90deg at var(--size) calc(0.353 * var(--size)), #249FAB 135deg, #81C5A3 0 270deg, #26609D 0) /* update the colors here */ 0 0 / calc(100% / var(--m)) calc(100% / var(--n));
}
Apoi aplicăm un strat de mască folosind un alt model având aceeași dimensiune. Aceasta este partea cea mai dificilă a acestei idei. Folosind o combinație de a linear-gradient
și conic-gradient
vom tăia câteva părți din elementul nostru pentru a păstra vizibile doar formele cuburilor.
.cube { /* etc. */ mask: linear-gradient(to bottom right, #0000 calc(0.25 * var(--size)), #000 0 calc(100% - calc(0.25 * var(--size)) - 1.414 * var(--gap)), #0000 0), conic-gradient(from -90deg at right var(--gap) bottom var(--gap), #000 90deg, #0000 0); mask-size: calc(100% / var(--m)) calc(100% / var(--n)); mask-composite: intersect;
}
Codul poate părea puțin complex, dar datorită variabilelor CSS, tot ce trebuie să facem este să actualizăm câteva valori pentru a controla matricea noastră de cuburi. Ai nevoie de o grilă 10⨉10? Actualizați --m
și --n
variabile la 10
. Ai nevoie de un spațiu mai mare între cuburi? Actualizați --gap
valoare. Valorile culorilor sunt folosite o singură dată, așa că actualizați-le pentru o nouă paletă de culori!
Acum că avem o altă tehnică 3D, să o folosim pentru a construi variații ale încărctorului jucându-se cu diferite animații. De exemplu, ce zici de un model repetat de cuburi care alunecă infinit de la stânga la dreapta?
Acest încărcător definește patru cuburi într-un singur rând. Asta înseamnă a noastră --n
valoarea este 4
și --m
este egal cu 1
. Cu alte cuvinte, nu mai avem nevoie de acestea!
În schimb, putem lucra cu --size
și --gap
variabile într-un container grilă:
.loader { --size: 70px; --gap: 15px; width: calc(3 * (1.353 * var(--size) + var(--gap))); display: grid; aspect-ratio: 3;
}
Acesta este containerul nostru. Avem patru cuburi, dar vrem să arătăm doar trei în container la un moment dat, astfel încât să avem întotdeauna unul care alunecă înăuntru așa cum unul iese afară. De aceea, luăm în calcul lățimea 3
și au setat raportul de aspect la 3
de asemenea.
Să ne asigurăm că modelul nostru de cuburi este configurat pentru lățimea a patru cuburi. Vom face asta pe container ::before
pseudo-element:
.loader::before { content: ""; width: calc(4 * 100% / 3); /* Code to create four cubes */
}
Acum că avem patru cuburi într-un container cu trei cuburi, putem justifica modelul cubului până la capătul containerului grilă pentru a-l revărsa, arătând ultimele trei cuburi:
.loader { /* same as before */ justify-content: end;
}
Iată ce avem până acum, cu un contur roșu pentru a arăta limitele containerului grilă:
Acum tot ce trebuie să facem este să mutăm pseudo-elementul la dreapta adăugând animația noastră:
@keyframes load { to { transform: translate(calc(100% / 4)); }
}
Ai înțeles trucul animației? Să terminăm asta prin ascunderea modelului de cub debordant și adăugând o notă de mascare pentru a crea acel efect de estompare pe care la început și la sfârșit:
.loader { --size: 70px; --gap: 15px; width: calc(3*(1.353*var(--s) + var(--g))); display: grid; justify-items: end; aspect-ratio: 3; overflow: hidden; mask: linear-gradient(90deg, #0000, #000 30px calc(100% - 30px), #0000);
}
Putem face acest lucru mult mai flexibil prin introducerea unei variabile, --n
, pentru a seta câte cuburi sunt afișate simultan în container. Și deoarece numărul total de cuburi din model ar trebui să fie cu unul mai mult decât --n
, putem exprima asta ca calc(var(--n) + 1)
.
Iată chestia completă:
OK, încă un încărcător 3D care este similar, dar are cuburile care își schimbă culoarea succesiv în loc să alunece:
Ne vom baza pe un fundal animat cu background-blend-mode
pentru acesta:
.loader { /* ... */ background: linear-gradient(#ff1818 0 0) 0% / calc(100% / 3) 100% no-repeat, /* ... */; background-blend-mode: multiply; /* ... */ animation: load steps(3) 1.5s infinite;
}
@keyframes load { to { background-position: 150%; }
}
Am eliminat codul de prisos folosit pentru a crea același aspect ca ultimul exemplu, dar cu trei cuburi în loc de patru. Ceea ce adaug aici este un gradient definit cu o culoare specifică care se îmbină cu gradientul conic, așa cum am făcut mai devreme pentru încărcătorul 3D cu bara de progres.
De acolo, animează gradientul de fundal background-position
ca o animație în trei pași pentru a face cuburile să clipească pe rând pe rând.
Dacă nu sunteți familiarizat cu valorile pentru care le folosesc background-position
și sintaxa de fundal, recomand cu căldură unul dintre articolele mele anterioare și unul dintre răspunsurile mele Stack Overflow. Veți găsi acolo o explicație foarte detaliată.
Putem actualiza numărul de cuburi pentru a-l face variabile?
Da, am o solutie pentru asta, dar mi-aș dori să-l faci mai degrabă decât să-l încorporezi aici. Luați ceea ce am învățat din exemplul anterior și încercați să faceți același lucru cu acesta - apoi împărtășiți-vă munca în comentarii!
Variații din belșug!
La fel ca celelalte trei articole din această serie, aș dori să vă las puțină inspirație pentru a vă crea propriile încărcătoare. Iată o colecție care include încărcătoarele 3D pe care le-am făcut împreună, plus câteva altele pentru a-ți declanșa imaginația:
Asta-i o înfășurare
Sper că v-a plăcut să petreceți timp făcând încărcătoare cu un singur element cu mine în ultimele câteva săptămâni. Este o nebunie că am început cu un filator aparent simplu și apoi am adăugat treptat piese noi pentru a lucra singuri până la tehnici 3D care încă folosesc doar un singur element în marcaj. Exact așa arată CSS atunci când îi valorificăm puterile: scalabil, flexibil și reutilizabil.
Mulțumesc încă o dată pentru că ai citit această mică serie! Voi închide reamintindu-vă că am un colecție de peste 500 de încărcătoare dacă sunteți în căutarea mai multor idei și inspirație.
Seria de articole
- Încărcătoare cu un singur element: Spinner
- Încărcătoare cu un singur element: punctele
- Încărcătoare cu un singur element: Barele
- Încărcătoare cu un singur element: Trecerea în 3D — Eşti aici
Încărcătoare cu un singur element: Treci în 3D! publicat inițial pe CSS-trucuri. Tu ar trebui primiți buletinul informativ.
- "
- 10
- 3d
- 9
- 95%
- a
- Despre Noi
- adăugat
- TOATE
- permite
- mereu
- O alta
- Aplică
- în jurul
- articol
- bunuri
- fundal
- deoarece
- înainte
- în spatele
- Mai bine
- între
- Pic
- construi
- Poate obține
- cod
- colectare
- combinaţie
- complex
- Recipient
- conţinut
- Control
- controale
- crea
- Crearea
- detaliu
- detaliat
- FĂCUT
- diferit
- Afişa
- distanţă
- dropbox
- fiecare
- efect
- stabili
- etc
- tot
- exact
- exemplu
- explora
- Față
- fete
- familiar
- Figura
- capăt
- First
- flexibil
- următor
- din
- faţă
- Complet
- mai mult
- decalaj
- merge
- Grilă
- având în
- înălțime
- aici
- extrem de
- speranţă
- Cum
- HTTPS
- idee
- idei
- imaginaţie
- În altele
- include
- Inspiraţie
- introducerea
- IT
- A pastra
- strat
- învățat
- Părăsi
- mic
- încărca
- Uite
- cautati
- făcut
- face
- Efectuarea
- masca
- matematica
- Matrice
- mijloace
- mai mult
- muta
- negativ
- număr
- numere
- Altele
- propriu
- parte
- Model
- piese
- joc
- puncte
- posibil
- precedent
- publicat
- Citind
- recomanda
- rămas
- reprezintă
- REST
- Safari
- acelaşi
- scalabil
- serie
- set
- Modela
- forme
- Distribuie
- Arăta
- semna
- asemănător
- simplu
- întrucât
- singur
- Mărimea
- So
- unele
- ceva
- Spaţiu
- specific
- Cheltuire
- împărţi
- pătrat
- stivui
- Începe
- început
- începe
- Încă
- tehnici de
- lucru
- trei
- timp
- împreună
- atingeţi
- Transforma
- Transparență
- transparent
- Actualizează
- us
- utilizare
- valoare
- vizibil
- Ce
- în timp ce
- mai larg
- cuvinte
- Apartamente
- scris
- Ta