A képcsúszkák (más néven körhinta) mindenhol megtalálhatók. Vannak sok CSS-trükk a közös csúszka létrehozásához ahol a képek balról jobbra (vagy ellenkezőleg) csúsznak. Ugyanaz az üzlet a sok JavaScript-könyvtár amelyek elegáns csúszkákat hoznak létre összetett animációkkal. Ebben a bejegyzésben ezt nem fogjuk megtenni.
Egy kis cikksorozaton keresztül megvizsgálunk néhány divatos és szokatlan, csak CSS-t használó csúszkát. Ha fáradt ugyanazokat a régi klasszikus csúszkákat, akkor jó helyen jár!
CSS Sliders sorozat
Ebben az első cikkben kezdjük azzal, amit „kör alakú forgó képcsúszkának” nevezek:
Menő ugye? boncolgassuk a kódot!
A HTML jelölés
Ha követted a sorozatomat díszes képdíszek or CSS-rács és egyéni alakzatok, akkor tudja, hogy az első szabályom az, hogy a lehető legkisebb HTML-lel dolgozzak. Mindig keményen igyekszem CSS-megoldásokat találni, mielőtt sokat zsúfolnék a kódomat
s és egyéb dolgok.
Ugyanez a szabály érvényes itt is – a kódunk nem más, mint egy tárolóban lévő képek listája.
Tegyük fel, hogy négy képpel dolgozunk:
Ez az! Most térjünk át a kód érdekes részére. Először azonban ebbe bele fogunk merülni, hogy megértsük a csúszka működésének logikáját.
Hogyan működik?
Itt van egy videó, ahonnan eltávolítom overflow: hidden
a CSS-ből, hogy jobban megérthessük, hogyan mozognak a képek:
Olyan, mintha a négy képünket egy nagy körre helyeznénk, amely az óramutató járásával ellentétes irányba forog.
Az összes kép azonos méretű (a jelöléssel S
ábrán). Jegyezze meg a kék kört, amely az a kör, amely az összes kép középpontjával metszi, és sugara (R
). Később szükségünk lesz erre az értékre az animációnkhoz. R
egyenlő 0.707 * S
. (Kihagyom azt a geometriát, amely ezt az egyenletet adja.)
Írjunk egy kis CSS-t!
Mi fogjuk használni CSS Rács hogy az összes képet ugyanazon a területen egymás fölé helyezze:
.gallery {
--s: 280px; /* control the size */
display: grid;
width: var(--s);
aspect-ratio: 1;
padding: calc(var(--s) / 20); /* we will see the utility of this later */
border-radius: 50%;
}
.gallery > img {
grid-area: 1 / 1;
width: 100%;
height: 100%;
object-fit: cover;
border-radius: inherit;
}
Eddig semmi túl bonyolult. A trükkös rész az animáció.
Egy nagy kör elforgatásáról beszéltünk, de a valóságban minden képet külön-külön fogunk elforgatni, egy nagy forgó kör illúzióját keltve. Tehát definiáljunk egy animációt, m
, és alkalmazza a képelemekre:
.gallery > img {
/* same as before */
animation: m 8s infinite linear;
transform-origin: 50% 120.7%;
}
@keyframes m {
100% { transform: rotate(-360deg); }
}
A fő trükk ezen a kiemelt vonalon alapul. Alapértelmezés szerint a CSS transform-origin
tulajdonság egyenlő center
(Vagy 50% 50%
), amely a képet a közepe körül elforgatja, de ehhez nincs szükségünk rá. A képnek el kell forgatnia a középpontja körül nagy kör amely a képeinket tartalmazza, ezért az új érték transform-origin
.
Mivel R egyenlő 0.707 * S
, ezt mondhatjuk R
egyenlő 70.7%
a kép méretétől. Íme egy ábra, amely szemlélteti, hogyan jutottunk el a 120.7%
érték:
Futtassuk az animációt, és nézzük meg, mi történik:
Tudom, tudom. Az eredmény messze van attól, amit szeretnénk, de a valóságban nagyon közel vagyunk. Úgy tűnhet, hogy csak egy kép van ott, de ne felejtse el, hogy az összes képet egymásra helyeztük. Mindegyik egyszerre forog, és csak a felső kép látható. Az átfedés elkerülése érdekében minden egyes kép animációját késleltetni kell.
.gallery > img:nth-child(2) { animation-delay: -2s; } /* -1 * 8s / 4 */
.gallery > img:nth-child(3) { animation-delay: -4s; } /* -2 * 8s / 4 */
.gallery > img:nth-child(4) { animation-delay: -6s; } /* -3 * 8s / 4 */
A dolgok már javulnak!
Ha a konténeren elrejtjük a túlcsordulást, már láthatunk egy csúszkát, de az animációt egy kicsit frissítjük, így minden kép rövid ideig látható marad, mielőtt továbbhaladna.
Frissíteni fogjuk animációs kulcskockáinkat, hogy ezt tegyük:
@keyframes m {
0%, 3% { transform: rotate(0); }
22%, 27% { transform: rotate(-90deg); }
47%, 52% { transform: rotate(-180deg); }
72%, 77% { transform: rotate(-270deg); }
98%, 100% { transform: rotate(-360deg); }
}
Minden egyes 90deg
(360deg/4
, Ahol 4
a képek száma) egy kis szünetet adunk hozzá. Minden kép látható marad 5%
a teljes időtartamról, mielőtt a következőre csúsztanánk (27%-22%
, 52%-47%
stb.). Frissíteni fogom a animation-timing-function
segítségével cubic-bezier()
funkció, hogy az animációt egy kicsit szebbé tegye:
Most a csúszkánk tökéletes! Nos, majdnem tökéletes, mert még hiányzik az utolsó simítás: a színes körkörös szegély, amely a képeink körül forog. Használhatunk pszeudoelemet a .gallery
csomagolás az elkészítéshez:
.gallery {
padding: calc(var(--s) / 20); /* the padding is needed here */
position: relative;
}
.gallery::after {
content: "";
position: absolute;
inset: 0;
padding: inherit; /* Inherits the same padding */
border-radius: 50%;
background: repeating-conic-gradient(#789048 0 30deg, #DFBA69 0 60deg);
mask:
linear-gradient(#fff 0 0) content-box,
linear-gradient(#fff 0 0);
mask-composite: exclude;
}
.gallery::after,
.gallery >img {
animation: m 8s infinite cubic-bezier(.5, -0.2, .5, 1.2);
}
Létrehoztam egy kört a ismétlődő kúpos gradiens a háttérhez a használata közben maszkolási trükk amely csak a párnázott területet mutatja. Ezután ugyanazt az animációt alkalmazom rá, amit a képekhez definiáltunk.
Végeztünk! Van egy klassz kör alakú csúszkánk:
Adjunk hozzá további képeket
Jó négy képpel dolgozni, de jobb lenne, ha tetszőleges számú képre méreteznénk. Hiszen ez a képcsúszka célja. Tudnunk kell mérlegelni N
képeket.
Ehhez a Sass bevezetésével általánosabbá tesszük a kódot. Először definiálunk egy változót a képek számához ($n
), és frissíteni fogunk minden olyan részt, ahol keményen kódoltuk a képek számát (4
).
Kezdjük a késésekkel:
.gallery > img:nth-child(2) { animation-delay: -2s; } /* -1 * 8s / 4 */
.gallery > img:nth-child(3) { animation-delay: -4s; } /* -2 * 8s / 4 */
.gallery > img:nth-child(4) { animation-delay: -6s; } /* -3 * 8s / 4 */
A késleltetés képlete a következő (1 - $i)*duration/$n
, ami a következő Sass hurkot adja:
@for $i from 2 to ($n + 1) {
.gallery > img:nth-child(#{$i}) {
animation-delay: calc(#{(1 - $i) / $n} * 8s);
}
}
Az időtartamot is változóvá tehetjük, ha nagyon akarjuk. De térjünk át az animációra:
@keyframes m {
0%, 3% { transform: rotate(0); }
22%, 27% { transform: rotate(-90deg); }
47%, 52% { transform: rotate(-180deg); }
72%, 77% { transform: rotate(-270deg); }
98%, 100% {transform: rotate(-360deg); }
}
Egyszerűsítsük le, hogy jobban lássuk a mintát:
@keyframes m {
0% { transform: rotate(0); }
25% { transform: rotate(-90deg); }
50% { transform: rotate(-180deg); }
75% { transform: rotate(-270deg); }
100% { transform: rotate(-360deg); }
}
Az egyes állapotok közötti lépés egyenlő 25%
- ami 100%/4
— és hozzáadjuk a -90deg
szög — ami az -360deg/4
. Ez azt jelenti, hogy a ciklusunkat a következőképpen írhatjuk fel:
@keyframes m {
0% { transform: rotate(0); }
@for $i from 1 to $n {
#{($i / $n) * 100}% { transform: rotate(#{($i / $n) * -360}deg); }
}
100% { transform: rotate(-360deg); }
}
Mivel minden kép vesz 5%
az animációnál ezt változtatjuk:
#{($i / $n) * 100}%
…ezzel:
#{($i / $n) * 100 - 2}%, #{($i / $n) * 100 + 3}%
Meg kell jegyezni, hogy a 5%
egy tetszőleges érték, amelyet ehhez a példához választottam. Azt is beállíthatjuk, hogy az egyes képek mennyi ideig maradjanak láthatóak. Ezt az egyszerűség kedvéért kihagyom, de házi feladat kedvéért megpróbálhatod megcsinálni, és kommentben megoszthatod a megvalósítást!
@keyframes m {
0%,3% { transform: rotate(0); }
@for $i from 1 to $n {
#{($i / $n) * 100 - 2}%, #{($i / $n) * 100 + 3}% { transform: rotate(#{($i / $n) * -360}deg); }
}
98%,100% { transform: rotate(-360deg); }
}
Az utolsó lépés a frissítés transform-origin
. Szükségünk lesz néhány geometriai trükkre. Bármi legyen is a képek száma, a konfiguráció mindig ugyanaz. A képeinket (kis köröket) egy nagy körbe helyezzük, és meg kell találnunk a sugár értékét, R
.
Valószínűleg nem akar unalmas geometriai magyarázatot, ezért így találjuk meg R
:
R = S / (2 * sin(180deg / N))
Ha ezt százalékban fejezzük ki, akkor a következőt kapjuk:
R = 100% / (2 * sin(180deg / N)) = 50% / sin(180deg / N)
…ami azt jelenti, transform-origin
érték egyenlő:
transform-origin: 50% (50% / math.sin(180deg / $n) + 50%);
Végeztünk! Van egy csúszkánk, amely bármilyen számú képpel működik!
Dobjunk oda kilenc képet:
Adjon hozzá annyi képet, amennyit csak szeretne, és frissítse a $n
változó a képek teljes számával.
Csomagolta
Néhány CSS-transzformációt és szabványos geometriát használó trükkel egy szép kör alakú csúszkát hoztunk létre, amely nem igényel sok kódot. Ebben a csúszkában az a jó, hogy nem kell vesződnünk a képek sokszorosításával, hogy megőrizzük a végtelen animációt, mivel van egy körünk. A teljes forgatás után visszatérünk az első képhez!