CSS Infinito e Circular Rotativo Slider de Imagem PlatoBlockchain Data Intelligence. Pesquisa vertical. Ai.

Controle deslizante de imagem rotativa infinita e circular do CSS

Os controles deslizantes de imagem (também chamados de carrosséis) estão por toda parte. Há muitos truques de CSS para criar o controle deslizante comum onde as imagens deslizam da esquerda para a direita (ou o contrário). É o mesmo negócio com as muitas bibliotecas JavaScript por aí que criam controles deslizantes sofisticados com animações complexas. Não vamos fazer nada disso neste post.

Por meio de uma pequena série de artigos, vamos explorar alguns controles deslizantes sofisticados e incomuns somente para CSS. Se você está cansado de ver os mesmos sliders clássicos, então você está no lugar certo!

Série de controles deslizantes CSS

Para este primeiro artigo, começaremos com algo que chamo de “controle deslizante de imagem rotativa circular”:

Legal certo? vamos dissecar o código!

A marcação HTML

Se você acompanhou minha série de decorações de imagem extravagantes or Grade CSS e formas personalizadas, então você sabe que minha primeira regra é trabalhar com o menor HTML possível. Eu sempre tento encontrar soluções CSS antes de sobrecarregar meu código com muito

s e outras coisas.

A mesma regra se aplica aqui — nosso código nada mais é do que uma lista de imagens em um contêiner.

Digamos que estamos trabalhando com quatro imagens:

É isso! Agora vamos para a parte interessante do código. Mas primeiro, vamos nos aprofundar nisso para entender a lógica de como nosso controle deslizante funciona.

Como funciona o Tech & Data Studio:

Aqui está um vídeo onde eu removo overflow: hidden do CSS para que possamos entender melhor como as imagens estão se movendo:

É como se nossas quatro imagens fossem colocadas em um grande círculo que gira no sentido anti-horário.

Controle deslizante de imagem rotativa infinita e circular do CSS

Todas as imagens têm o mesmo tamanho (indicado por S na figura). Observe o círculo azul que é o círculo que cruza com o centro de todas as imagens e tem um raio (R). Vamos precisar desse valor mais tarde para nossa animação. R é igual a 0.707 * S. (Vou pular a geometria que nos dá essa equação.)

Vamos escrever um pouco de CSS!

Nós estaremos usando Grade CSS para colocar todas as imagens na mesma área umas sobre as outras:

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

Nada muito complexo até aqui. A parte complicada é a animação.

Falamos sobre girar um grande círculo, mas, na realidade, vamos girar cada imagem individualmente, criando a ilusão de um grande círculo girando. Então, vamos definir uma animação, m, e aplique-o aos elementos da imagem:

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

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

O truque principal depende dessa linha destacada. Por padrão, o CSS transform-origin propriedade é igual a center (ou 50% 50%) que faz a imagem girar em torno de seu centro, mas não precisamos dela para fazer isso. Precisamos que a imagem gire em torno do centro do grande circulo que contém nossas imagens, portanto, o novo valor para transform-origin.

Como R é igual a 0.707 * S, Nós podemos dizer que R é igual a 70.7% do tamanho da imagem. Aqui está uma figura para ilustrar como obtivemos o 120.7% valor:

CSS Infinito e Circular Rotativo Slider de Imagem PlatoBlockchain Data Intelligence. Pesquisa vertical. Ai.
Controle deslizante de imagem rotativa infinita e circular do CSS

Vamos rodar a animação e ver o que acontece:

Eu sei eu sei. O resultado está longe do que queremos, mas na realidade estamos muito próximos. Pode parecer que há apenas uma imagem ali, mas não se esqueça de que empilhamos todas as imagens umas sobre as outras. Todos eles estão girando ao mesmo tempo e apenas a imagem superior é visível. O que precisamos é atrasar a animação de cada imagem para evitar essa sobreposição.

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

As coisas já estão melhorando!

Se ocultarmos o estouro no contêiner já podemos ver um controle deslizante, mas atualizaremos um pouco a animação para que cada imagem permaneça visível por um curto período antes de seguir em frente.

Vamos atualizar nossos quadros-chave de animação para fazer exatamente isso:

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

Para cada 90deg (360deg/4, Onde 4 é o número de imagens) vamos adicionar uma pequena pausa. Cada imagem permanecerá visível por 5% da duração geral antes de passarmos para o próximo (27%-22%, 52%-47%, etc). vou atualizar o animation-timing-function utilizando um cubic-bezier() função para tornar a animação um pouco mais sofisticada:

Agora nosso slider está perfeito! Bem, quase perfeito porque ainda falta o toque final: a borda circular colorida que gira em torno de nossas imagens. Podemos usar um pseudo-elemento no .gallery invólucro para fazer isso:

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

Eu criei um círculo com um gradiente cônico repetitivo para o fundo ao usar um truque de mascaramento que mostra apenas a área acolchoada. Depois aplico a mesma animação que definimos para as imagens.

Acabamos! Temos um controle deslizante circular legal:

Vamos adicionar mais imagens

Trabalhar com quatro imagens é bom, mas seria melhor se pudéssemos dimensioná-lo para qualquer número de imagens. Afinal, esse é o objetivo de um controle deslizante de imagem. Devemos ser capazes de considerar N imagens.

Para isso, vamos deixar o código mais genérico introduzindo o Sass. Primeiro, definimos uma variável para o número de imagens ($n) e atualizaremos todas as partes em que codificamos o número de imagens (4).

Vamos começar com os atrasos:

.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 fórmula do atraso é (1 - $i)*duration/$n, que nos dá o seguinte loop Sass:

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

Podemos tornar a duração uma variável também, se realmente quisermos. Mas vamos à animação:

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

Vamos simplificar para ter uma visão melhor do padrão:

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

O passo entre cada estado é igual a 25% - qual é 100%/4 — e adicionamos um -90deg ângulo - que é -360deg/4. Isso significa que podemos escrever nosso loop assim:

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

Como cada imagem leva 5% da animação, mudamos isso:

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

…com isso:

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

Deve notar-se que 5% é um valor arbitrário que escolhi para este exemplo. Também podemos torná-la uma variável para controlar quanto tempo cada imagem deve permanecer visível. Vou pular isso para simplificar, mas como lição de casa, você pode tentar fazer e compartilhar sua implementação nos comentários!

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

A última parte é atualizar transform-origin. Vamos precisar de alguns truques de geometria. Seja qual for o número de imagens, a configuração é sempre a mesma. Colocamos nossas imagens (pequenos círculos) dentro de um grande círculo e precisamos encontrar o valor do raio, R.

CSS Infinito e Circular Rotativo Slider de Imagem PlatoBlockchain Data Intelligence. Pesquisa vertical. Ai.
Controle deslizante de imagem rotativa infinita e circular do CSS

Você provavelmente não quer uma explicação de geometria chata, então aqui está como encontramos R:

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

Se expressarmos isso como uma porcentagem, isso nos dá:

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

… o que significa o transform-origin valor é igual a:

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

Foram realizadas! Temos um controle deslizante que funciona com qualquer número de imagens!

Vamos lançar nove imagens lá:

Adicione quantas imagens quiser e atualize o $n variável com o número total de imagens.

Resumindo

Com alguns truques usando transformações CSS e geometria padrão, criamos um bom controle deslizante circular que não requer muito código. O legal desse controle deslizante é que não precisamos nos preocupar em duplicar as imagens para manter a animação infinita, pois temos um círculo. Após uma rotação completa, voltaremos à primeira imagem!

Carimbo de hora:

Mais de Truques CSS