Blog Fellyph Cintra

Blog sobre WordPress, IA, PWA e JavaScript

Introdução a Canvas HTML5

Thumbnail do post Introdução a Canvas HTML5 com formas desenhadas no canvas e código getContext 2d

Comecei a experimentar Canvas HTML5 em 2010, quando voltei a trabalhar com JavaScript, com a ajuda do meu colega Leo (@leonardomarciel). A pergunta continua prática: como desenhar na página usando JavaScript?

Neste tutorial, você vai criar um quadrado, desenhar formas e texto, e animar um elemento com requestAnimationFrame(). O ponto de partida é a Canvas API 2D.

Canvas API

A Canvas API fornece maneiras de desenhar gráficos via JavaScript usando o elemento <canvas> do HTML. Com essa API podemos criar animações, gráficos para jogos, visualização de dados, manipulação de fotos e processamento de vídeo em tempo real.

A Canvas API foca em gráficos 2D. Para gráficos 3D acelerados por hardware existe a WebGL API e, mais recentemente, a WebGPU API, que também usam o elemento <canvas>. A documentação de referência completa está disponível na MDN Web Docs.

Sobre compatibilidade, hoje o assunto é tranquilo: o Canvas HTML5 faz parte do Baseline da plataforma web e funciona em todos os navegadores modernos (Chrome, Firefox, Safari e Edge), com suporte acima de 99% segundo o Can I use.

Suporte dos navegadores ao Canvas HTML5 no Can I use
Suporte dos navegadores ao Canvas HTML5 no Can I use

Como trabalhar com Canvas HTML5

Tudo começa com a tag <canvas> no HTML. Definimos um id para referenciar o elemento no JavaScript e as propriedades width e height. Se largura e altura não forem definidas, o canvas assume os valores padrão de 300px por 150px. Também é possível redimensionar por CSS, mas, nesse caso, corremos o risco de distorcer a imagem, porque o CSS escala o desenho em vez de aumentar a área de pixels.

<canvas id="meu-canvas" width="320" height="200">
  Seu navegador não tem suporte ao elemento canvas.
</canvas>Code language: HTML, XML (xml)

O conteúdo dentro da tag é o fallback: texto, imagem ou qualquer elemento HTML exibido apenas se o navegador não suportar canvas. Hoje isso é raríssimo, mas o fallback continua importante por outro motivo: acessibilidade. Leitores de tela não enxergam o que é desenhado no canvas, então descreva ali o que o desenho representa.

Acessando o contexto de renderização

Para desenhar, precisamos do contexto de renderização, obtido com o método getContext(). Para gráficos 2D passamos o parâmetro "2d". Outros contextos disponíveis são "webgl", "webgl2" e "webgpu", usados para gráficos 3D. Neste tutorial vamos trabalhar com o 2D.

const canvas = document.getElementById("meu-canvas");
const ctx = canvas.getContext("2d");Code language: JavaScript (javascript)

Desenhando o primeiro quadrado

Com o contexto em mãos, vamos desenhar uma forma primitiva. O exemplo completo fica assim:

<canvas id="meu-canvas" width="320" height="200">
  Seu navegador não tem suporte ao elemento canvas.
</canvas>

<script>
  const canvas = document.getElementById("meu-canvas");
  const ctx = canvas.getContext("2d");

  // definindo a cor de preenchimento
  ctx.fillStyle = "rgb(0, 200, 0)";

  // desenhando um quadrado: (x, y, largura, altura)
  ctx.fillRect(40, 40, 80, 80);
</script>Code language: HTML, XML (xml)

A propriedade fillStyle define a cor de preenchimento e aceita qualquer valor de cor do CSS. Podemos usar rgba(200, 0, 0, 0.5) para incluir opacidade (o quarto valor é o alpha) ou um código hexadecimal como ctx.fillStyle = "#00cc00". Um detalhe importante: fillStyle é uma propriedade, não uma função, então o valor é atribuído com o sinal de igual.

Contorno e limpeza: strokeRect e clearRect

Além do fillRect(), existem mais dois métodos para trabalhar com retângulos. O strokeRect() desenha apenas o contorno, usando a cor definida em strokeStyle e a espessura definida em lineWidth. Já o clearRect() apaga uma área retangular do canvas, deixando os pixels transparentes.

// retângulo preenchido
ctx.fillStyle = "#007bff";
ctx.fillRect(20, 20, 120, 120);

// retângulo apenas com contorno
ctx.strokeStyle = "#ff3b30";
ctx.lineWidth = 4;
ctx.strokeRect(160, 20, 120, 120);

// apagando uma área no meio do primeiro retângulo
ctx.clearRect(50, 50, 60, 60);Code language: JavaScript (javascript)

Desenhando caminhos: triângulos, círculos e linhas

Retângulos são a única forma pronta da API 2D. Qualquer outra forma é construída com paths (caminhos). O fluxo é sempre o mesmo: beginPath() inicia um novo caminho, métodos como moveTo(), lineTo() e arc() definem a geometria, e fill() ou stroke() desenham o resultado na tela.

// triângulo preenchido
ctx.fillStyle = "#8a2be2";
ctx.beginPath();
ctx.moveTo(50, 150);  // ponto inicial
ctx.lineTo(150, 150); // linha até a base direita
ctx.lineTo(100, 50);  // linha até o topo
ctx.closePath();      // fecha o caminho de volta ao início
ctx.fill();

// círculo com contorno
ctx.strokeStyle = "#00d4ff";
ctx.lineWidth = 3;
ctx.beginPath();
ctx.arc(220, 100, 50, 0, Math.PI * 2); // (x, y, raio, ângulo inicial, ângulo final)
ctx.stroke();Code language: JavaScript (javascript)

No método arc(), os ângulos são medidos em radianos. Para um círculo completo, o ângulo final é Math.PI * 2, o equivalente a 360 graus.

Escrevendo texto no canvas

A API também desenha texto com o método fillText(). A fonte é definida na propriedade font, com a mesma sintaxe do CSS:

ctx.font = "bold 32px sans-serif";
ctx.fillStyle = "#1a1a1b";
ctx.fillText("Canvas HTML5", 20, 60); // (texto, x, y)Code language: JavaScript (javascript)

Vale reforçar: texto desenhado no canvas vira pixel, não pode ser selecionado nem lido por leitores de tela. Para conteúdo textual de verdade, prefira HTML. Use fillText() para rótulos de gráficos, placares de jogos e elementos visuais.

Animações com requestAnimationFrame

O canvas não tem cenas nem camadas: para animar, redesenhamos o quadro inteiro várias vezes por segundo. O navegador oferece a função requestAnimationFrame(), que executa o nosso desenho em sincronia com a taxa de atualização da tela. O padrão é limpar o canvas com clearRect(), desenhar o novo quadro e agendar o próximo:

const canvas = document.getElementById("meu-canvas");
const ctx = canvas.getContext("2d");
const velocidade = 120; // pixels por segundo
let inicio;

function desenhar(timestamp) {
  if (inicio === undefined) {
    inicio = timestamp;
  }

  const segundos = (timestamp - inicio) / 1000;
  const posicaoX = (velocidade * segundos) % canvas.width;

  ctx.clearRect(0, 0, canvas.width, canvas.height);
  ctx.fillStyle = "rgb(0, 200, 0)";
  ctx.fillRect(posicaoX, 60, 50, 50);

  requestAnimationFrame(desenhar);
}

requestAnimationFrame(desenhar);Code language: JavaScript (javascript)

A velocidade usa pixels por segundo e o timestamp recebido pelo callback. Assim, o movimento mantém a mesma velocidade em telas de 60 Hz ou 120 Hz. Somar pixels a cada frame faria a animação acelerar em telas com maior taxa de atualização. Veja a documentação de requestAnimationFrame().

Dicas de especialista

  • Telas de alta densidade: em displays retina o canvas pode ficar borrado. A solução é multiplicar width e height por window.devicePixelRatio e ajustar o tamanho visual via CSS.
  • Performance: para desenhos pesados fora da thread principal, vale conhecer o OffscreenCanvas, que permite renderizar em um Web Worker.
  • Bibliotecas: em 2010 eu procurava um framework para facilitar o trabalho com canvas. Hoje o ecossistema é maduro: p5.js para creative coding, Konva para interfaces interativas e Chart.js para gráficos são ótimos pontos de partida.

Conclusão

O Canvas HTML5 saiu de novidade temida em 2010 para peça fundamental da plataforma web. Com fillRect(), paths, texto e requestAnimationFrame() você já consegue construir de gráficos simples a joguinhos 2D. O próximo passo natural é explorar WebGL e WebGPU para o mundo 3D.

Para mais conteúdo relacionado a desenvolvimento front-end confira os posts relacionados:


LEITURAS_RELACIONADAS

> ler ./comentarios.log


> adicionar comentário

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *