Efeito de carrossel de fatias de imagem

Prefácio

Quando visitei um determinado site sem querer, fiquei profundamente atraído pelo efeito carrossel em sua página inicial. Por meio da depuração do navegador, finalmente entendi o princípio de implementação e finalmente escrevi uma cópia por mim mesmo Demo. O efeito final é o seguinte :( o código-fonte está no final)

Efeito plano:

Insira a descrição da imagem aqui

Efeito 3D:

Insira a descrição da imagem aqui

Este carrossel corta a imagem em várias partes, depois reproduz as partes cortadas com efeitos de animação por sua vez e, por fim, costura-as em uma nova imagem.

No processo de recuperação da pilha de tecnologia front-end, parece que não há tecnologia que possa cortar diretamente a imagem e dividi-la em várias partes. O efeito de corte de imagem que normalmente aplicamos é usado apenas canvaspara simular a geração.

Por meio de minha própria depuração, descobri que esta imagem do carrossel usa uma canvasmaneira mais simples de obter o mesmo efeito de corte.

Em seguida, prossiga do mais superficial para o mais profundo, passo a passo, para revelar o princípio de implementação.

Efeito plano

Vamos começar com o efeito plano, primeiro escreva um htmldiagrama geral de carrossel, a estrutura é a seguinte:

 <div class="main" id="el">
       <div class="item">
         <img src="./img/1.jpg" />
       </div>
       <div class="item">
         <img src="./img/2.jpg" />
       </div>
       <div class="item">
         <img src="./img/3.jpg" />
       </div>
 </div>

elÉ o contêiner externo, que contém três fotos do carrossel.

Se quisermos fazer um efeito de animação, temos que seguir um passo.

  • Gere ou faça com que os domelementos sejam animados
  • domAdicione efeitos de animação ao elemento

Agora diminua a animação do efeito plano e observe cuidadosamente suas características, conforme mostrado na figura a seguir:

Insira a descrição da imagem aqui

htmlEsta fatia da imagem não é encontrada no código original , o que significa que os elementos a serem animados precisam ser gerados por nós e adicionados ao documento da página para renderização.

Se a imagem de configuração será cortada em 5partes, então geramos uma estrutura de imagem de fatia é a seguinte:

   <div class="main" id="el">
         <div class="item">
           <img src="./img/1.jpg" />
         </div>
         <div class="item">
           <img src="./img/2.jpg" />
         </div>
         <div class="item">
           <img src="./img/3.jpg" />
         </div>
         <!--做动画的dom元素-->
         <div class="hook">
              <div><img src="./img/2.jpg" /></div>
              <div><img src="./img/2.jpg" /></div>
              <div><img src="./img/2.jpg" /></div>
              <div><img src="./img/2.jpg" /></div>
              <div><img src="./img/2.jpg" /></div>
         </div>
   </div>

Na página original, jsgerando uma classe chamada período hookde html片段, como um modo de posicionamento absolute.

hookHá cinco div, respectivamente, mostram 2.jpgo problema corte imagem correspondente enfrentando agora é como deixar este 5um divforam para escalar esta imagem uma parte dela?

Se a configuração hookdo recipiente exterior tem uma largura total de 1000pxsub-elemento de 5número divmédio de 200pxpode ser fornecida por uma segunda deixar divsó mostram imgos segundos recortes.

  <div style="position:absolute;width:200px;left:200px;overflow:hidden">
     <img src="./img/2.jpg" style="position:absolute;width:500%;left:-200px"/>
  </div>

Desde a largura total da camada externa 1000px, corte em 5partes cada uma divrepresentando 200px(na codificação real 200por meio de jscalculado) e, em seguida, movido para a direita 200pxocupando a segunda posição da fatia.

imgA atribuição da widthsoma lefté o ponto chave, e seu valor específico também é calculado pela largura total e pelo número de fatias.

widthDefina como 500%, o que significa que a largura da imagem é igual ao 1000pxcontêiner externo e, em seguida, mova para a esquerda 200px. Como o pai está divdefinido overflow:hidden, imagine o efeito e ele aparecerá.

Esses processos mencionados acima devem ser jsemendados e calculados em uma string html字符串, semelhante ao seguinte:

  for(i=0;i<n;i++){ //循环i次,n(总共将图片切成n份),unit_width对应每一个切块的宽度
           html += `
               <div 
               style="position:absolute;
               width:${unit_width}px;
               top:-100%;
               left:${ i * unit_width};
               overflow:hidden">
                   <img src="${src}" 
                       style="position:absolute;
                       width:${n*100}%;
                       left:${-i * unit_width}px"/>
              </div>
     `     
  }

5Após a conclusão da divcostura, coloque-o <div class="hook"></div>nele e adicione-o à renderização do documento da página.O domelemento final gerado é o elemento a ser animado a seguir.

Uma vez que 5um divconjunto de posicionamento e topvalor absolutos é definido -100%, eles, uma vez renderizados, estão na posição superior da página.

O próximo efeito de animação é muito fácil de conseguir, só precisamos divadicionar um a cada no loop acima transition:top linear 0.25s.

Assim que 5a divrenderização for concluída, podemos jsdefinir dinamicamente em cada um divdos topvalores de 0animação que é acionado, cada página divdeslizando lentamente para baixo a partir do topo.

Espere até que todo o processo de animação seja finalizado, teremos hookeste uso jsgerado domremovido, e que deve ser exibido item(contendo imagens estáticas do original dom) é definido para exibir oculto a partir deste ponto todo o processo de animação está concluído.

Efeito 3D

O efeito planar é relativamente simples de implementar, e o 3Defeito lançando requer uma compreensão cssdos 3datributos em primeiro lugar.

Revisão de propriedade 3d

rotateX: Em torno do Xeixo de rotação, a Lenovo 单杠运动.
rotateY: Em torno do Yeixo de rotação, a Lenovo 钢管舞.
rotateZ: Em torno do Zeixo de rotação, a Lenovo 老式钟表盘.

Os três atributos acima costumam ser muito contatados, então não vou repeti-los. A seguir, focaremos nos 3datributos.

    .container{
       perspective: 1200px;
       perspective-origin: right center;
      .wrapper {
        transform-style: preserve-3d;
        transform:translateZ(-100px);
      }
    }

O contêiner externo containercontém um filho wrapper. O filho é o 3delemento específico a ser animado, portanto, deve definir uma propriedade transform-style: preserve-3d.

Somente quando está definido o preserve-3delemento pode mostrar seu 3defeito.

translateZE translateX, translateYestes dois atributos não são os mesmos. translateXEstá prestes a mudança no plano, translateYé movido no plano vertical.

translateZÉ um 3datributo. Não faz deslocamentos para cima, para baixo, para a esquerda e para a direita no plano, mas faz deslocamentos para dentro ou para fora da direção perpendicular ao plano.

translateZ(-100px)Isso significa que o elemento foi movido para o interior da tela 100px. De acordo com a regra de perto, grande, longe, pequeno, o efeito visual final do elemento é 100pxreduzido como um todo. Se for positivo , ele se moverá para o fora da tela 100px, e o efeito visual do elemento é ampliado.

translateZpreserve-3dAplicar apenas no elemento com o atributo definido terá efeito, de modo que preserve-3dtodos os 3datributos podem ter efeito.

blockÉ 3do domelemento a ser transformado , portanto, precisa ser definido preserve-3de transformtransformado.O elemento pai é containerequivalente a um palco e blockpode ser considerado um ator de performance de palco.

perspectiveRepresenta a distância entre o público e o palco. É concebível perspectiveque quanto menor o valor, mais próximo o público está do palco, e a cena no palco será vista com mais clareza.

Correspondendo à cena real, perspectivecorrespondendo à domdistância entre os elementos aos olhos do usuário, quanto maior a distância, quanto mais distante, wrappermenor e menos claro o interior. Pelo contrário, quanto perspectivemaior quanto maior, wrappermaior será a aparência e mais claros os detalhes internos.

perspective-originPode-se entender se o usuário está sentado na posição esquerda, posição intermediária ou posição direita do auditório para assistir à apresentação no palco, e o efeito do campo visual é diferente.

Agora, de volta ao tópico, continue a estudar 3do diagrama de carrossel do efeito flip. Ao diminuir o tempo de animação, observe seus detalhes, conforme mostrado na figura a seguir:

Insira a descrição da imagem aqui

Ao observar a imagem acima, percebi rapidamente que os elementos a serem animados não estão disponíveis na página atual e precisam ser jsgerados dinamicamente por nós.

O elemento de animação é um cubo que contém dois efeitos de movimento. Um é mover para a esquerda e o outro é virar para a frente. Mover para a esquerda é fácil de fazer, defina-o para um leftvalor de mudança dinâmica de posicionamento absoluto . RotateX(-90deg)pode ser feito definindo Arrived (equivalente ao grau de Xinversão ao longo do eixo 90).

O efeito de animação do cubo não é difícil de conseguir, a dificuldade está em como gerar tal cubo.

Desenhar cubo

Na cena atual, o cubo só precisa desenhar quatro faces: superior, frontal, esquerda e direita. A parte superior é armazenada para a próxima imagem a ser carrossel, a frente é armazenada para a imagem exibida no momento, e a esquerda e a direita são preto. O fundo é preenchido para tornar a imagem mais tridimensional, a htmlestrutura é a seguinte:


   <div class="wrapper">
            <div class="left"></div>
            <div class="right"></div>
            <div class="front"><img src="1.jpg"></div>
            <div class="up"><img src="2.jpg"></div>
   </div>

A left, right, fronte upsão definidas para o posicionamento absoluto, largura e altura são preenchidos com o elemento pai, lefte topconfiguração 0.

frontÉ o rosto diretamente à frente, é originalmente exibido no plano e não há necessidade de nenhum processamento.

leftPara posicionar o ponto central no canto superior esquerdo, o grau de yrenderização ao longo do eixo 90formará o lado.

.left {
  transform-origin: 0% 0%;
  transform: rotateY(90deg);
  background-color: #333;
}

rightVocê precisa mover toda a largura para a direita e girar ao longo do eixo y 90para formar o lado direito.

html += `
    ... //js中dom字符串拼接
   <div class="right" style="transform: translateX(${unit_width}px) rotateY(90deg);">
      ...
   </div>
   ...
`

upA superfície primeiro define o ponto central no canto esquerdo inferior, gira em torno do Xeixo 90e depois sobe toda a altura para formar o topo.

.up{
    transform-origin: 0% 100%;
}
html += `
    ... //js中dom字符串拼接
   <div class="up" style="transform: rotateX(90deg) translateZ(${container_height}px);">
     ...
   </div>
   ...
`

A domestrutura dessas quatro faces jsé dividida internamente e colocada no wrapperpai correspondente.Como divmencionado acima , os atributos wrapperprecisam ser configurados internamente preserve-3de os wrapperelementos são os elementos realmente animados dom.

wrapperDepois do elemento é encapsulado, isto é lançada para dentro do elemento fase container, e os atributos e containersão ajustados .3dperspectiveperspective-origin

Um containercorresponde a uma fatia do cubo, e o htmlfio formado por todos os cubos recortados é colocado no documento da página e renderizado, desta forma os domelementos animados são gerados.

Adicionar animação flip

Os domelementos que executam a animação foram gerados e renderizados na página. De acordo com a análise anterior, adicionar um atributo a cada cubo ( wrappercorrespondente div) rotateX(-90deg)pode fazer o cubo girar. Os resultados são os seguintes:

Insira a descrição da imagem aqui
wrapperAlém disso, o rotateX(-90deg)atributo é realmente invertido para a frente, mas a posição final não está perto do solo.

A causa do acidente foi porque se wrappertratava de um cubo, não um simples plano, mas também continha quatro planos.Agora, quando o cubo é girado, a posição do seu centro é muito importante.

wrapperA altura de está 100%cheia de todo o pai. Através de testes, descobriu-se que a transformação do atributo do cubo é na verdade baseada na frente ( frontface). O ponto central do cubo está localizado no frontmeio da frontaltura da face .Se a altura da face for 600px, então Ao 300pxdesenhar um Xeixo, gire todo o cubo ao longo deste eixo.Se a frontaltura da superfície for 800px, então o cubo irá 400pxgirar ao longo do eixo.

Agora volte ao caso acima, fronta altura da face é configurada para 100%preencher o elemento pai, então o cubo vai desenhar um eixo no meio e virar para frente 90, então haverá um vazio abaixo. Não podemos deixar o cubo Vire e pare no ar, Para encontrar uma maneira de colocá-lo de volta no chão.

De acordo com o que eu disse antes, o cubo usa a frontsuperfície como superfície de referência. Depois de inverter o 90grau, a frontsuperfície vai para o fundo. Então você quer que o cubo se mova para baixo, porque ele está frontvoltado para o fundo neste momento , e você só precisa configurá-lo translateZ(contrainer_height/2)para mover o cubo para baixo. Metade da altura é fixada na parte inferior.

Embora essa configuração possa garantir que o cubo virado seja preso na parte inferior, a imagem dentro dele é deformada.

Porque quando o cubo é configurado rotateX(-90deg)para virar para a frente, ele é realmente movido para frente. De acordo com as regras de quase grande e muito pequeno, o efeito visual da imagem é ampliado. Para resolver este problema, primeiro use o cubo translateZ(-contrainer_height/2)para empurrar metade da altura para dentro e depois deixar o cubo virar para frente, para que o problema de alongamento da imagem seja resolvido, o código é o seguinte:


while ((el = eles.shift())) {
    //el对应着每个立方体的dom
    //立方体先沿Z轴往后推一半高度,再朝前做翻转,翻转完后向下移动一半高度贴底 
    el.style.transform = `translateZ(${  
      -this.container_height / 2
    }px) rotateX(-90deg) translateZ(${this.container_height / 2}px)`;
    ...
  }

Depois que o efeito flip for concluído, descobriremos que o cubo está voltado para nós e girando, não podemos ver o lado direito do cubo com um fundo preto right, então ele parecerá muito adimensional.

Eu apresentei um atributo antes perspective-origin:right center. É como o público sentado do lado direito do auditório, e o palco é tão largo quanto o auditório, e há uma gaiola de ferro no palco voltada para a frente do público. Neste momento, o campo de visão do público só pode ver Na frente da gaiola de ferro, se a gaiola for empurrada para o lado esquerdo do palco, o cliente sentado do lado direito do público não pode ver apenas a frente da gaiola de ferro , mas ele também pode ver o lado direito da gaiola de ferro.

Da mesma forma, para que o cubo pareça mais tridimensional ao ser virado, o fundo preto à direita pode ser exibido durante a animação. Para isso, é necessário mover o cubo para a esquerda , além perspective-origindo suporte de atributos, o cubo O efeito tridimensional invertido aparece.

Se você deseja que o cubo se mova para a esquerda, você só precisa obter os domelementos do cubo e leftatribuí- los dinamicamente.

Código fonte

Código completo

Acho que você gosta

Origin blog.csdn.net/brokenkay/article/details/115034048
Recomendado
Clasificación