Curseur d'image à rotation infinie et circulaire CSS PlatoBlockchain Data Intelligence. Recherche verticale. Aï.

Curseur d'image à rotation infinie et circulaire CSS

Les curseurs d'image (également appelés carrousels) sont partout. Il y a beaucoup d'astuces CSS pour créer le curseur commun où les images glissent de gauche à droite (ou l'inverse). C'est la même affaire avec les nombreuses bibliothèques JavaScript disponibles qui créent des sliders fantaisistes avec des animations complexes. Nous n'allons rien faire de tout cela dans ce post.

À travers une petite série d'articles, nous allons explorer des curseurs CSS uniques et fantaisistes. Si vous êtes fatigué de voir les mêmes curseurs classiques, alors vous êtes au bon endroit !

Série de curseurs CSS

Pour ce premier article, nous allons commencer par quelque chose que j'appelle le "curseur d'image rotatif circulaire":

Cool non ? disséquons le code !

Le balisage HTML

Si vous avez suivi ma série de décorations d'images fantaisie or Grille CSS et formes personnalisées, alors vous savez que ma première règle est de travailler avec le plus petit code HTML possible. J'essaie toujours de trouver des solutions CSS avant d'encombrer mon code avec beaucoup

s et d'autres choses.

La même règle s'applique ici — notre code n'est rien d'autre qu'une liste d'images dans un conteneur.

Disons que nous travaillons avec quatre images :

C'est ça! Passons maintenant à la partie intéressante du code. Mais d'abord, nous allons plonger là-dedans pour comprendre la logique de fonctionnement de notre curseur.

Comment cela fonctionne ? 

Voici une vidéo où j'enlève overflow: hidden du CSS afin que nous puissions mieux comprendre comment les images se déplacent :

C'est comme si nos quatre images étaient placées sur un grand cercle qui tourne dans le sens inverse des aiguilles d'une montre.

Curseur d'image à rotation infinie et circulaire CSS

Toutes les images ont la même taille (indiquée par S dans la figure). Notez le cercle bleu qui est le cercle qui coupe le centre de toutes les images et a un rayon (R). Nous aurons besoin de cette valeur plus tard pour notre animation. R est égal à 0.707 * S. (Je vais sauter la géométrie qui nous donne cette équation.)

Écrivons du CSS !

Nous utiliserons Grille CSS pour placer toutes les images dans la même zone les unes au-dessus des autres :

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

Rien de trop complexe pour l'instant. La partie délicate est l'animation.

Nous avons parlé de faire tourner un grand cercle, mais en réalité, nous ferons tourner chaque image individuellement en créant l'illusion d'un grand cercle en rotation. Alors, définissons une animation, m, et appliquez-le aux éléments de l'image :

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

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

L'astuce principale repose sur cette ligne en surbrillance. Par défaut, le CSS transform-origin la propriété est égale à center (ou 50% 50%) qui fait tourner l'image autour de son centre, mais nous n'en avons pas besoin pour cela. Nous avons besoin que l'image tourne autour du centre de la grand cercle qui contient nos images d'où la nouvelle valeur de transform-origin.

Puisque R est égal à 0.707 * S, on peut dire ça R est égal à 70.7% de la taille de l'image. Voici une figure pour illustrer comment nous avons obtenu le 120.7% valeur:

Curseur d'image à rotation infinie et circulaire CSS PlatoBlockchain Data Intelligence. Recherche verticale. Aï.
Curseur d'image à rotation infinie et circulaire CSS

Exécutons l'animation et voyons ce qui se passe :

Je sais je sais. Le résultat est loin de ce que nous souhaitons, mais en réalité nous en sommes très proches. Il peut sembler qu'il n'y a qu'une seule image, mais n'oubliez pas que nous avons empilé toutes les images les unes sur les autres. Tous tournent en même temps et seule l'image du haut est visible. Ce dont nous avons besoin, c'est de retarder l'animation de chaque image pour éviter ce chevauchement.

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

Les choses vont déjà mieux !

Si nous cachons le débordement sur le conteneur, nous pouvons déjà voir un curseur, mais nous mettrons un peu à jour l'animation afin que chaque image reste visible pendant une courte période avant de se déplacer.

Nous allons mettre à jour nos images clés d'animation pour faire exactement cela :

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

Pour chaque 90deg (360deg/4, Où 4 est le nombre d'images) nous ajouterons une petite pause. Chaque image restera visible pendant 5% de la durée globale avant de passer à la suivante (27%-22%, 52%-47%, etc.). je vais mettre à jour le animation-timing-function à l'aide d'un cubic-bezier() fonction pour rendre l'animation un peu plus fantaisiste :

Maintenant, notre curseur est parfait ! Enfin presque parfait car il nous manque encore la touche finale : la bordure circulaire colorée qui tourne autour de nos images. On peut utiliser un pseudo-élément sur le .gallery emballage pour le faire:

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

J'ai créé un cercle avec un dégradé conique répétitif pour l'arrière-plan lors de l'utilisation d'un astuce de masquage qui ne montre que la zone rembourrée. Ensuite, je lui applique la même animation que nous avons définie pour les images.

Nous avons fini! Nous avons un curseur circulaire sympa :

Ajoutons plus d'images

Travailler avec quatre images est bien, mais ce serait mieux si nous pouvions l'adapter à n'importe quel nombre d'images. Après tout, c'est le but d'un curseur d'image. On devrait pouvoir considérer N images.

Pour cela, nous allons rendre le code plus générique en introduisant Sass. Tout d'abord, nous définissons une variable pour le nombre d'images ($n) et nous mettrons à jour chaque partie où nous avons codé en dur le nombre d'images (4).

Commençons par les retards :

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

La formule du retard est (1 - $i)*duration/$n, ce qui nous donne la boucle Sass suivante :

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

Nous pouvons également faire de la durée une variable si nous le voulons vraiment. Mais passons à l'animation :

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

Simplifions-le pour avoir une meilleure vue du modèle :

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

Le pas entre chaque état est égal à 25% - lequel est 100%/4 — et nous ajoutons un -90deg angle - qui est -360deg/4. Cela signifie que nous pouvons écrire notre boucle comme ceci à la place :

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

Étant donné que chaque image prend 5% de l'animation, nous changeons ceci :

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

…avec ça:

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

En tant que professionnels, 5% est une valeur arbitraire que je choisis pour cet exemple. Nous pouvons également en faire une variable pour contrôler combien de temps chaque image doit rester visible. Je vais sauter ça par souci de simplicité, mais pour les devoirs, vous pouvez essayer de le faire et partager votre mise en œuvre dans les commentaires !

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

Le dernier bit est de mettre à jour transform-origin. Nous aurons besoin de quelques astuces de géométrie. Quel que soit le nombre d'images, la configuration est toujours la même. Nous avons nos images (petits cercles) placées à l'intérieur d'un grand cercle et nous devons trouver la valeur du rayon, R.

Curseur d'image à rotation infinie et circulaire CSS PlatoBlockchain Data Intelligence. Recherche verticale. Aï.
Curseur d'image à rotation infinie et circulaire CSS

Vous ne voulez probablement pas une explication de géométrie ennuyeuse alors voici comment nous trouvons R:

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

Si nous exprimons cela en pourcentage, cela nous donne :

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

… ce qui signifie que transform-origin valeur est égale à :

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

Avaient fini! Nous avons un curseur qui fonctionne avec n'importe quel nombre d'images !

Jetons-y neuf images :

Ajoutez autant d'images que vous le souhaitez et mettez à jour le $n variable avec le nombre total d'images.

Emballage en place

Avec quelques astuces utilisant les transformations CSS et la géométrie standard, nous avons créé un joli curseur circulaire qui ne nécessite pas beaucoup de code. Ce qui est cool avec ce curseur, c'est que nous n'avons pas besoin de dupliquer les images pour conserver l'animation infinie puisque nous avons un cercle. Après une rotation complète, nous reviendrons à la première image !

Horodatage:

Plus de Astuces CSS