Este é o terceiro artigo de uma série sobre a API de animação do GreenSock e o SVG. Essa série não se destina a iniciantes, mas sim a um mergulho profundo em alguns dos recursos mais interessantes e menos conhecidos com os quais se pode trabalhar depois de passar pela introdução inicial. O primeiro artigo foi sobre Movimento ao longo de um caminho. A segunda foi sobre Animação responsiva complexa. Hoje, exploraremos brevemente alguns novos recursos do GSAP e os usaremos para criar uma animação mais complexa.


Ciclo de escalonamento

O primeiro recurso que abordaremos é o ciclo de escalonamento. O recurso de escalonamento em muitas bibliotecas de animação JavaScript tende a ser uma ferramenta incrivelmente útil para a criação de animações elegantes e é, sem dúvida, uma vantagem em relação ao fluxo de trabalho do CSS para criar o mesmo efeito. Para criar um efeito de escalonamento no CSS, o senhor aumenta o atraso usando o elemento ou pseudoelemento com os mesmos keyframes:



@keyframes staggerFoo {
  to {
    background: orange;
    transform: rotate(90deg);
 }
}

.css .bar:nth-child(1) { animation: staggerFoo 1s 0.1s ease-out both; }
.css .bar:nth-child(2) { animation: staggerFoo 1s 0.2s ease-out both; }
.css .bar:nth-child(3) { animation: staggerFoo 1s 0.3s ease-out both; }
.css .bar:nth-child(4) { animation: staggerFoo 1s 0.4s ease-out both; }
.css .bar:nth-child(5) { animation: staggerFoo 1s 0.5s ease-out both; }
.css .bar:nth-child(6) { animation: staggerFoo 1s 0.5s ease-out both; }


E, no SASS, o senhor poderia SECAR um pouco:



@keyframes staggerFoo {
  to {
    background: orange;
    transform: rotate(90deg);
 }
}

@for $i from 1 through 6 {
  .sass .bar:nth-child(#{$i} ) {
      animation: staggerFoo 1s ($i * 0.1s) ease-out both;
   }
 }


No entanto, com o GSAP, o senhor pode criar esse efeito com uma única linha de código:



TweenMax.staggerTo(".gsap .bar", 1, { backgroundColor: "orange", rotation: 90, ease: Sine.easeOut}, 0.1);


Veja a caneta aqui por Sarah Drasner (@sdras) em CodePen.


A concisão é uma vantagem para o fluxo de trabalho, especialmente se for necessário fazer ajustes no futuro.


Com o ciclo de escalonamento, agora podemos passar vários valores para escalonar entre eles, algo que seria exponencialmente complexo em CSS. A sintaxe exige uma matriz de valores:



TweenMax.staggerTo(".foo", 1, {
 cycle: {
   y: [75, 0, -75]
 },
 ease: Power4.easeInOut
}, 0.05);


Que o senhor também pode randomizar, para obter efeitos ainda mais interessantes.



var coord = [40, 800, 70, -200];

TweenMax.staggerTo(".foo", 1, {
 cycle: {
   x: function(i) {
     return coord[Math.floor(Math.random() * coord.length)];
   }
 },
 ease: Power4.easeInOut
}, 0.1);


Na caneta a seguir, eu simplesmente escalonei entre três valores para cada elemento e apliquei isso somente a um elemento no SVG. Com muito pouco código (22 linhas de JS), o senhor pode fazer muito:



Veja a caneta SVG com escalonamento de ciclo por Sarah Drasner (@sdras) em CodePen.



Animação de cores HSL relativas

Este é relativamente simples. O senhor entendeu? Relativo? Caramba. A capacidade de interpor quantidades relativas de cores HSL é fantástica, pois se o senhor pretende criar efeitos de cores sofisticados facilmente na animação, é preciso fazer um pequeno ajuste:




produz efeitos visuais muito poderosos. Digamos que o senhor queira transformar uma cena inteira, cada elemento com uma cor ligeiramente diferente, do dia para a noite, lentamente. Anteriormente, a maneira mais fácil de fazer isso era alterar lentamente o valor da cor de cada um desses elementos individualmente. O senhor poderia colocar uma sobreposição em todo o contêiner, mas isso carece de sofisticação e realismo. Ou, talvez, usar um filtro de matriz de fe SVG, que é muito pouco semântico e não é muito intuitivo de animar. Ou até mesmo um filtro CSS, que, até o momento, não tem muito suporte. Agora, em um pequeno trecho de código, o senhor pode, de maneira uniforme e com grande compatibilidade com versões anteriores, pegar centenas de elementos e torná-los um pouco mais escuros, diminuir a saturação relativa e ajustar lentamente o matiz para transformá-los em uma tonalidade ligeiramente diferente. O Tweening HSL também tem a vantagem de poder ser usado tanto para background (para divs) ou fill (para SVG) porque não é opinativo em relação a um determinado tipo de propriedade. 13;


Aqui está uma pequena demonstração para mostrar como ele funciona:


Veja a caneta Tartarugas que mostram o Relative HSL tweening por Sarah Drasner (@sdras) em CodePen.


Tantas opções! Qual é um bom caso de uso? Vamos deixar isso para o seu visualizador. Podemos juntar o ciclo de escalonamento e a interpolação de cores HSL com alguma interação. Mas, em vez de uma cena noturna, vamos deixá-la um pouco mais selvagem.


Como estamos interpolando valores relativos, podemos combinar efeitos nos botões e obter vários resultados. Criaremos dois botões diferentes com efeitos relativos ligeiramente diferentes. Também vale a pena mencionar que finalmente temos o operação de classe em SVG na versão 3.0.0 do jquery e podemos controlar facilmente nossos tweens na interação:



//button hue
function hued() {

//keeps the fill and background consistent relative hue changes
  var ch1 = "hsl(+=110%, +=0%, +=0%)", 
  tl = new TimelineMax({
    paused: true
  });

  tl.add("hu");

  tl.to(mult, 1.25, {
      fill: ch1
    }, "hu");

//tweens for background because of divs and css
  tl.to(body, 1.25, {
      backgroundColor: ch1
    }, "hu");

//the gauge responds to the action in the scene as if it's showing pressure

  tl.from(gauge, 2, {
      rotation: "-=70",
      transformOrigin: "50% 50%",
      ease: Bounce.easeOut
    }, "hu");

  return tl;
}

var hue = hued();

//same thing for the tweens for button saturation (has some relative hue as well)
function saturation() {
  var ch2 = "hsl(+=5%, +=2%, -=10%)",
  tl = new TimelineMax({
    paused: true
  });

  tl.add("sated");

  tl.to(body, 1, {
      backgroundColor:ch2
    }, "sated");

  tl.to(mult, 2, {
      fill:ch2
    }, "sated");

  tl.from(gauge, 2, {
      rotation: "-=100",
      transformOrigin: "50% 50%",
      ease: Bounce.easeOut
    }, "sated");

  return tl;
}

var sat = saturation();

// ...

//detect class and either start or reverse the timeline depending
$(but1).on('click', function(e) {
    e.preventDefault();

    $(this).toggleClass('a-s');
    if ($(this).hasClass('a-s')) {
      sat.restart();
    } else {
      sat.reverse();
    }
  });


  $(but2).on('click', function(e) {

    e.preventDefault();
    $(this).toggleClass('a-h');
    if ($(this).hasClass('a-h')) {
      hue.restart();
    } else {
      hue.reverse();
    }
  });


Também faremos com que a cena seja escalonada com um pouco mais de nuance com o novo ciclo de escalonamento. Mas como queremos que todos os elementos entrem e tenham a mesma aparência, faz mais sentido usar um staggerFrom do que um staggerTo:



tl.staggerFrom(city, 0.75, {
     y: -50,
     scale: 0,
     cycle:{
       x:[300, 100, 200],
       opacity:[0.5, 0.3, 0.2, 0.8],
       rotation:[50, 100, 150],
     }, 
     transformOrigin: "50% 50%",
     ease: Back.easeOut
   }, 0.02, "in");


E isso se torna nosso conjunto de construtores de cidades:


Veja a caneta Local de construção da cidade por Sarah Drasner (@sdras) em CodePen.


Há mais um recurso importante nesta versão: interpolação e transformação de valores complexos baseados em strings. No entanto, esse é um recurso tão incrível que dedicaremos um artigo futuro a ele.


Esta é a terceira parte de uma série de várias partes. À medida que avançarmos no aprendizado de cada uma dessas técnicas, uniremos diferentes maneiras de trabalhar para criar trabalhos cada vez mais complexos e envolventes. Fique ligado!