Conteúdo gratuito para entusiastas de código

Pra quem ainda não conhece, PostCSS é um processador de folhas de estilo (CSS), assim como Less e Sass. Um processador te dá “poderes adicionais” para criar folhas de estilo, por exemplo, criar variáveis.

Se você ainda não está familiarizado com esse conceito, recomedo os seguintes links antes de prosseguir sua leitura:

Bom, como você já deve saber, muitos consideram PostCSS um pós-processador de CSS, outros, têm a opinião oposta: “PostCSS é como um pré-processador, faz exatamente a mesma coisa”.

Pra tentar entender onde mora a diferença, comecei a tentar imaginar qual seria a origem da palavra pré-processador, e, por analogia, podemos comparar com o PHP (sigla para PHP: Hipertext Preprocessor):

O PHP foi uma linguagem criada para pré-formatar uma saída HTML que deveria ser dinâmica em momento de runtime, e é chamado assim, pois o processamento das informações era feito antes de ser recebido e interpretado pelo navegador, como no diagrama abaixo:

PHP Pré Processado

Podemos considerar que um pré-processador funciona da mesma maneira:

CSS Pré Processado

Partindo desse princípio, como funciona um pós processador?

CSS Pós Processado

Analisando dessa forma, um pós-processador processa os arquivos CSS finais, que já são “interpretáveis” pelo navegador, porém, que ainda podem ser otimizados, “cross-browserificados” (essa palavra existe?), concatenados, comprimidos, etc.

Para reforçar a ideia de que PostCSS é um pós-processador de arquivos, os exemplos de utilização da ferramenta utilizam a extensão .css nos arquivos de entrada e saída (source / destination), porém, não é só isso que devemos levar em consideração.

Para garantir que o PostCSS é um pós-processador, ele deve se enquadrar no mesmo modelo mostrado anteriormente:
PostCSS Pós Processado

Como o PostCSS é uma ferramenta que depende de plugins para funcionar, temos que analisar o comportamento desses plugins para identificar o modelo de processamento da ferramenta.
(uma lista com todos eles pode ser vista / incrementada aqui (http://postcss.parts/))

Alguns deles são feitos apenas para otimizar nosso arquivo CSS, como por exemplo, o autoprefixer. Esse plugin permite você escrever seu CSS sem utilizar os prefixos de vendor, adicionando-os automaticamente, por exemplo:

entrada (source):

1
2
3
:fullscreen a {
display: flex
}

saída (destination):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
:-webkit-full-screen a {
display: -webkit-box;
display: flex
}
:-moz-full-screen a {
display: flex
}
:-ms-fullscreen a {
display: -ms-flexbox;
display: flex
}
:fullscreen a {
display: -webkit-box;
display: -ms-flexbox;
display: flex
}

Analisando o exemplo, podemos notar que um navegador (mesmo que apenas um moderno), conseguirá interpretar o arquivo CSS de entrada, isso significa que nessa situação, o PostCSS + autoprefixer estão pós-processando nosso arquivo CSS.

Em contrapartida, analisando o plugin short, vemos que é um pouco diferente:
entrada (source):

1
2
3
.icon {
size: 48px;
}

saída (destination):

1
2
3
4
.icon {
width: 48px;
height: 48px;
}

No exemplo acima, o PostCSS + Short não se comportam como um pós-processador, e sim como um pré-processador por um simples fato: Apesar de o arquivo de entrada ter a extensão .css, nenhum navegador conseguiria interpretar a propriedade ‘short’, consequentemente, o arquivo de entrada é inválido.

Em resumo, não podemos dizer se PostCSS é uma ferramenta de pós ou pré processamento, mas podemos dizer se um conjunto de plugins é. Por exemplo, um projeto que utiliza PostCSS com os plugins autoprefixer, stylelint e cssnano está sendo usado como um pós-processador.

Já em um projeto que utiliza lost e postcss-safe-parser, o PostCSS atua como um pré-processador.

Tem alguma coisa pra acrescentar ou alguma dúvida? Comenta aí pra se juntar na discussão ou me envia um e-mail pra sou@lucaschain.com,br que podemos discutir esse ou qualquer outro assunto!

Leia Mais

Animações

Para iniciar a linha de raciocínio, devemos nos perguntar:
O que é uma animação?

Uma animação é exatamente uma sequência de imagens, que, quando exibidas sequencialmente, formam um determinado movimento.

Utilizando o javascript como recurso, podemos simular um processo de sequência e desenhar (renderizar) o que queremos animar, por exemplo:

//Declara a variável de contagem
var c = 0;

//função que executa o passo (step)
var step = function(){
  //Aumenta o contador de steps
  c += 1;

  //Desenha o frame
  renderizarFrame(c);
};

//Coloca a função step para ser executada a cada 40 milissegundos
setInterval(step, 40);

Sim, já vimos essa regra no último tutorial, mas um pouco mais de explicações sobre esse assunto não vai fazer mal à ninguém.
A nossa função de renderizar frame é onde vai ocorrer a mágica. Baseado no valor da variável c, colocaremos um quadrado em uma posição diferente, assim criando o efeito de movimentação:

// Define qual é a velocidade que o retângulo vai se movimentar
var renderizarFrame = function(c){
  // Limpa o canvas, para não desenhar um retângulo em cima do outro e causar o efeito de "borrão". Experimente comentar a linha abaixo caso esteja curioso
  ctx.clearRect(0,0,canvas.width,canvas.height);


  //desenha o retângulo, a variável c é usada 
  ctx.fillStyle = '#0000FF'; //a definição de fillStyle poderia ocorrer fora dessa função para melhorar a performance, mas e se tivéssemos dois quadrados, por exemplo?
  ctx.fillRect(c, 50, 100, 80);
};

var velocidade = 1.1;
//Vamos alterar a função step para utilizar a velocidade dinâmica:
var step = function(){
  //Aumenta o contador de steps
  c += velocidade;

  //Desenha o frame
  renderizarFrame(c);
};

(Não se esqueça de atualizar a sua função step como fiz acima)

Ok, mas tem algo estranho. Nosso movimento parece estar “travando” em alguns momentos.
Isso ocorre por que quando o navegador usa o método setInterval, ele não se importa se o canvas terminou seu processamento, ele SEMPRE fará de tudo para atualizar a cada 40 milisegundos, custe o que custar. Isso sobrecarrega nosso motor de renderização.

Para solucionar esse problema, os browsers têm métodos para nos dizer quando eles estão prontos para desenhar novamente:

  • requestAnimationFrame //Browsers em suas últimas versões
  • webkitRequestAnimationFrame //Google chrome em versões não tão recentes
  • mozRequestAnimationFrame //Firefox
  • funcão declarada com setTimeout dentro //IEs antigos

Para suprir a necessidade de todos os browsers, vamos encapsular todos esses métodos em um método centralizado (coloque antes da definição de step):

var requestAnimFrame = 
  window.requestAnimationFrame   ||
  window.webkitRequestAnimationFrame ||
  window.mozRequestAnimationFrame    ||
  function( callback ){
    //Tenta chamar o método callback 60 vezes por segundo
    window.setTimeout(callback, 1000/60); 
  };

var step = function(){
  //Quando o browser estiver pronto para desenhar, executa o método step (ele mesmo)
  requestAnimFrame(step);

  //Aumenta o contador de steps
  c += velocidade;

  //Desenha o frame
  renderizarFrame(c);
  };
}

Agora não precisamos mais do antigo setInterval, mas precisamos iniciar nosso motor chamando o método step pela primeira vez:

step();
//Não utilizamos mais setInterval devido a nossa lógica de requestAnimationFrame
//setInterval(step, 40);

Pronto. Agora temos um modelo funcional de animação suave.

Como transformar isso em um jogo?
O que difere uma animação de um jogo é a interatividade, então, vamos adicionar um pouco (só um pouco) de interatividade no nosso jogo. Colocaremos um acelerador de velocidade: as setas do teclado:

// Define a captura de eventos do teclado para alternar a velocidade de acordo com a seta pressionada
document.onkeydown = function(e){
  //Caso alguma seta seja pressionada, temos que responder ao movimento:

  switch (e.keyCode){
    case 39:
      //Aumenta a velocidade (anda pra direita)
      velocidade += 0.5;
    break;
    case 37:
      //Reduz a velocidade (anda pra esquerda)
      velocidade += 0.5;
    break;
    default:
      return;
  }
  return false;
}

Para facilitar seu teste, defina o valor inicial da variável velocidade para 0.
Agora que o retângulo não move, seria bom adicionar uma mensagem no método de desenho:

var renderizarFrame = function(c){
  // Limpa o canvas, para não desenhar um retângulo em cima do outro e causar o efeito de "borrão". Experimente comentar a linha abaixo caso esteja curioso
  ctx.clearRect(0,0,canvas.width,canvas.height);

  // define a posição x do retângulo baseando-se no contador e na velocidade:
  var x = c;

  //desenha o retângulo
  ctx.fillStyle = '#0000FF'; //a definição de fillStyle poderia ocorrer fora dessa função para melhorar a performance, mas e se tivéssemos dois quadrados, por exemplo?
  ctx.fillRect(x, 50, 100, 80);

  //desenha a frase de ajuda
  ctx.font="20px Verdana";
  ctx.fillStyle="green";
  ctx.fillText("Pressione barra de espaços para acelerar",10,30);

};

Na próxima parte, vamos melhorar (e muito) nosso sistema de controle (input) e também vamos usar alguns conceitos básicos de física pra dar mais realismo ao jogo. Também voltaremos a orientar nosso código a objetos e mostrar algumas estruturas básicas de uma Game Engine.

Fontes:
http://www.cambiaresearch.com/articles/15/javascript-char-codes-key-codes
http://www.paulirish.com/2011/requestanimationframe-for-smart-animating/
https://pt.wikipedia.org/wiki/Animação

Leia Mais

Olá, meu nome é Lucas Chain e sou desenvolvedor na Just Digital.

Os arquivos referentes a esse tutorial estão localizados no GitHub do projeto
https://github.com/justdigital/content-canvas

O elemento Canvas no HTML5 funciona exatamente como uma tela de pintura: Um quadro onde você pode desenhar para usuário utilizando uma API em javascript

Para começar, crie uma estrutura básica:

CSS
body{
  background-color: black;
}
#quadro{
  margin: 50px auto 0 auto;
  width: 640px;
  height: 480px;
}

HTML
<canvas width="640" height="480" id="quadro"></canvas>

Até agora só temos um quadro branco em um fundo preto. O próximo passo é extrair o contexto do nosso quadro para começar a desenhar.

O contexto gerencia tudo o que é colocado no quadro, portanto, sempre que formos desenhar 2d, precisaremos de um contexto 2d.

Para obter o contexto de um canvas, utilize a função createContext(‘2d’):

var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');

Antes de desenhar com o contexto, é preciso definir um estilo para ser utilizado, depois, utilizar o método de desenho, por exemplo:

1) Criar retângulo azul com o contexto:

//Define o estilo do contexto (cor azul)
ctx.fillStye = '#0000FF';

/*
  Desenha um retângulo no canvas com as seguintes propriedades:
  posição x (lateral): 30
  posição y (vertical de cima para baixo): 50
  largura: 100
  altura: 80
*/
ctx.fillRect(30, 50, 100, 80);

2) Criar um círculo com cor gradiente linear

/*
  Define um gradiente linear com as seguintes propriedades:
  x inicial: 50
  y inicial: 50
  x final: 100
  y final: 100
*/
var grd = ctx.createLinearGradient(50,50,100,100);

//Define as cores do gradiente (do vermelho em 0% ao verde em 45% para o azul em 100%)
grd.addColorStop(0, "red");
grd.addColorStop(0.45, "green");
grd.addColorStop(1, "blue");

//Definindo o estilo do contexto com o gradiente que acabamos e criar
ctx.fillStyle = grd;

//Para criar o círculo, devemos fazer um PATH (caminho), o caminho vai fazer um arco de 360 graus para que seja preenchido depois.

//Inicia o caminho com o contexto:
ctx.beginPath();

/*
  O caminho percorre um arco de 0 até 360 graus. O centro do arco fica na posição 75,75(x,y)
*/
ctx.arc(75,75,50,0,2*Math.PI);

// Preenchemos o circulo (com o estilo de gradiente préviamente definido)
ctx.fill();

O conceito é o mesmo para animações, a diferença é que a animação será feita dentro de um laço que será repetido várias vezes num curto intervalo de tempo, como no exemplo:

3) Escrever no canvas:

//Definindo a fonte do contexto
ctx.font="20px Georgia";

//Definindo a cor do estilo
ctx.fillStyle="red";

//Desenhando o texto
ctx.fillText("Olá blog!",10,50);

4) Criar um círculo animado:

//Criamos esse objeto que representa um círculo que será animado
var circulo = {
  x: 0,
  y: 40,
  desenhar: function(ctx, canvas){
    //Limpa o canvas das posições 0 até o seu limite (largura e altura)
    ctx.clearRect(0,0,canvas.width,canvas.height);
    ctx.fillStyle = "green";
    ctx.beginPath();
    ctx.arc(this.x, this.y, 30, 0, 2 * Math.PI);
    ctx.fill();
  },
  mover: function(){
    this.x += 3;
  }
};

//Executa o método mover e depois desenhar em um intervalo de 20 em 20 milissegundos. Caso já exista um circulo em movimento, o circulo antigo é cancelado
if (window.circuloInterval) clearInterval(window.circuloInterval);
window.circuloInterval = setInterval(function(){
  circulo.mover();
  circulo.desenhar(ctx, canvas);
}, 20);

Para concluir, quero dizer que essa é apenas uma pequena introdução ao universo canvas, com eles, podemos fazer coisas inacreditáveis como jogos, apps mobile, UX inovadores e muito mais!

Para mais referências sobre a documentação do canvas, recomendo os seguintes links:

No proximo post vamos falar mais sobre performance de canvas em diferentes browsers e como receber input (mouse e teclado) do usuário para adicionar interatividade.

Até mais!

Leia Mais
⬆︎TOPO