CSS Oneindige en cirkelvormige roterende afbeeldingsschuifregelaar

Bronknooppunt: 1765846

Afbeeldingsschuifregelaars (ook wel carrousels genoemd) zijn overal. Er zijn veel CSS-trucs om de gemeenschappelijke schuifregelaar te maken waar de afbeeldingen van links naar rechts schuiven (of andersom). Het is dezelfde deal met de vele JavaScript-bibliotheken die er zijn die mooie schuifregelaars maken met complexe animaties. Dat gaan we in dit bericht niet doen.

Door middel van een kleine reeks artikelen gaan we een aantal mooie en ongebruikelijke schuifregelaars voor alleen CSS verkennen. Als je moe bent van het zien van dezelfde oude klassieke sliders, dan ben je op de juiste plek!

CSS Sliders-serie

Voor dit eerste artikel beginnen we met iets dat ik de "circulaire roterende afbeeldingsschuifregelaar" noem:

Cool toch? laten we de code ontleden!

De HTML-opmaak

Als je mijn serie van mooie afbeelding decoraties or CSS-raster en aangepaste vormen, dan weet je dat mijn eerste regel is om met de kleinst mogelijke HTML te werken. Ik doe altijd mijn best om CSS-oplossingen te vinden voordat ik mijn code volproppen

s en andere dingen.

Dezelfde regel is hier van toepassing: onze code is niets anders dan een lijst met afbeeldingen in een container.

Laten we zeggen dat we met vier afbeeldingen werken:

Dat is het! Laten we nu naar het interessante deel van de code gaan. Maar eerst gaan we hier dieper op in om de logica te begrijpen van hoe onze schuifregelaar werkt.

Hoe werkt het?

Hier is een video waarin ik verwijder overflow: hidden van de CSS zodat we beter kunnen begrijpen hoe de afbeeldingen bewegen:

Het is alsof onze vier afbeeldingen op een grote cirkel zijn geplaatst die tegen de klok in draait.

Alle afbeeldingen hebben dezelfde grootte (aangeduid met S in de figuur). Let op de blauwe cirkel, de cirkel die het midden van alle afbeeldingen snijdt en een straal heeft (R). We hebben deze waarde later nodig voor onze animatie. R is gelijk aan 0.707 * S. (Ik ga de geometrie overslaan die ons die vergelijking geeft.)

Laten we wat CSS schrijven!

We zullen gebruiken CSS-raster om alle afbeeldingen in hetzelfde gebied boven elkaar te plaatsen:

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

Niets te ingewikkeld tot nu toe. Het lastige is de animatie.

We hadden het over het roteren van een grote cirkel, maar in werkelijkheid zullen we elke afbeelding afzonderlijk roteren om de illusie van een grote roterende cirkel te creรซren. Laten we dus een animatie definiรซren, men pas het toe op de afbeeldingselementen:

.gallery > img {
  /* same as before */
  animation: m 8s infinite linear;
  transform-origin: 50% 120.7%;
}

@keyframes m {
  100% { transform: rotate(-360deg); }
}

De belangrijkste truc is gebaseerd op die gemarkeerde regel. Standaard is de CSS transform-origin eigenschap is gelijk aan center (of 50% 50%) waardoor de afbeelding om het midden draait, maar dat hebben we niet nodig. We hebben de afbeelding nodig om rond het midden van de afbeelding te roteren grote cirkel dat bevat onze afbeeldingen vandaar de nieuwe waarde voor transform-origin.

Aangezien R gelijk is aan 0.707 * S, we kunnen stellen dat R is gelijk aan 70.7% van de afbeeldingsgrootte. Hier is een figuur om te illustreren hoe we de 120.7% waarde:

Laten we de animatie uitvoeren en kijken wat er gebeurt:

Ik weet het. Het resultaat is verre van wat we willen, maar in werkelijkheid zijn we heel dichtbij. Het lijkt misschien alsof er maar รฉรฉn afbeelding is, maar vergeet niet dat we alle afbeeldingen op elkaar hebben gestapeld. Ze draaien allemaal tegelijkertijd en alleen de bovenste afbeelding is zichtbaar. Wat we nodig hebben, is de animatie van elke afbeelding vertragen om deze overlap te voorkomen.

.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 */

Het gaat al beter!

Als we de overloop op de container verbergen, zien we al een schuifregelaar, maar we zullen de animatie een beetje bijwerken, zodat elke afbeelding een korte periode zichtbaar blijft voordat deze verder beweegt.

We gaan onze animatiesleutelframes updaten om precies dat te doen:

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

Voor elk 90deg (360deg/4, Waar 4 is het aantal afbeeldingen) voegen we een kleine pauze toe. Elke afbeelding blijft zichtbaar voor 5% van de totale duur voordat we naar de volgende gaan (27%-22%, 52%-47%, enz.). Ik ga de update uitvoeren animation-timing-function gebruik maken van een cubic-bezier() functie om de animatie wat chiquer te maken:

Nu is onze slider perfect! Nou ja, bijna perfect, want we missen nog steeds de finishing touch: de kleurrijke cirkelvormige rand die rond onze afbeeldingen draait. We kunnen een pseudo-element gebruiken op de .gallery wikkel om het te maken:

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

Ik heb een cirkel gemaakt met een herhalende conische gradiรซnt voor de achtergrond tijdens het gebruik van een maskerende truc dat toont alleen het opgevulde gebied. Vervolgens pas ik dezelfde animatie toe die we voor de afbeeldingen hebben gedefinieerd.

We zijn klaar! We hebben een coole ronde schuifregelaar:

Laten we meer afbeeldingen toevoegen

Werken met vier afbeeldingen is goed, maar het zou beter zijn als we het kunnen schalen naar een willekeurig aantal afbeeldingen. Dit is tenslotte het doel van een afbeeldingsschuifregelaar. We zouden moeten kunnen overwegen N afbeeldingen.

Hiervoor gaan we de code generieker maken door Sass te introduceren. Eerst definiรซren we een variabele voor het aantal afbeeldingen ($n) en we zullen elk onderdeel bijwerken waar we het aantal afbeeldingen hard hebben gecodeerd (4).

Laten we beginnen met de vertragingen:

.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 */

De formule voor de vertraging is (1 - $i)*duration/$n, wat ons de volgende Sass-lus geeft:

@for $i from 2 to ($n + 1) {
  .gallery > img:nth-child(#{$i}) {
    animation-delay: calc(#{(1 - $i) / $n} * 8s);
  }
}

We kunnen de duur ook variabel maken als we dat echt willen. Maar laten we verder gaan met de animatie:

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

Laten we het vereenvoudigen om een โ€‹โ€‹beter beeld van het patroon te krijgen:

@keyframes m {
  0% { transform: rotate(0); }
  25% { transform: rotate(-90deg); }
  50% { transform: rotate(-180deg); }
  75% { transform: rotate(-270deg); }
  100% { transform: rotate(-360deg); }
}

De stap tussen elke toestand is gelijk aan 25% - dat is 100%/4 - en we voegen een -90deg hoek - dat is -360deg/4. Dat betekent dat we onze lus in plaats daarvan als volgt kunnen schrijven:

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

Omdat elke afbeelding duurt 5% van de animatie veranderen we dit:

#{($i / $n) * 100}%

โ€ฆhiermee:

#{($i / $n) * 100 - 2}%, #{($i / $n) * 100 + 3}%

Opgemerkt dat 5% is een willekeurige waarde die ik voor dit voorbeeld kies. We kunnen er ook een variabele van maken om te bepalen hoe lang elke afbeelding zichtbaar moet blijven. Ik ga dat voor de eenvoud overslaan, maar voor huiswerk kun je proberen het te doen en je implementatie delen in de reacties!

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

Het laatste stukje is om te updaten transform-origin. We hebben wat geometrietrucs nodig. Ongeacht het aantal afbeeldingen, de configuratie is altijd hetzelfde. We hebben onze afbeeldingen (kleine cirkels) in een grote cirkel geplaatst en we moeten de waarde van de straal vinden, R.

U wilt waarschijnlijk geen saaie uitleg over geometrie, dus hier is hoe we vinden R:

R = S / (2 * sin(180deg / N))

Als we dat uitdrukken als een percentage, geeft dat ons:

R = 100% / (2 * sin(180deg / N)) = 50% / sin(180deg / N)

โ€ฆwat betekent de transform-origin waarde is gelijk aan:

transform-origin: 50% (50% / math.sin(180deg / $n) + 50%);

Werden gedaan! We hebben een schuifregelaar die werkt met elk aantal afbeeldingen!

Laten we er negen afbeeldingen in gooien:

Voeg zoveel afbeeldingen toe als je wilt en update de $n variabele met het totale aantal afbeeldingen.

Afsluiten

Met een paar trucs met behulp van CSS-transformaties en standaardgeometrie, hebben we een mooie ronde schuifregelaar gemaakt waarvoor niet veel code nodig is. Het leuke aan deze schuifregelaar is dat we niet de moeite hoeven te nemen om de afbeeldingen te dupliceren om de oneindige animatie te behouden, aangezien we een cirkel hebben. Na een volledige rotatie komen we terug bij de eerste afbeelding!

Tijdstempel:

Meer van CSS-trucs