⚡ Curso de HTML • Web-ZoneWare

HTML5 Canvas: Guia Prático de Gráficos 2D | Web Academy

Lição 34 de 50

HTML5 Canvas: Guia Prático de Gráficos 2D | Web Academy

O elemento <canvas> é uma das inovações mais revolucionárias introduzidas pelo HTML5. Ele funciona como uma tela de pintura digital em branco incorporada à página, permitindo a renderização programática de linhas, formas geométricas, textos, imagens rasterizadas e animações complexas em tempo real a 60 quadros por segundo (FPS) via JavaScript.

1. A Filosofia do Canvas: Modo Imediato vs Modo Retido

Para dominar o Canvas, é fundamental compreender como ele opera no motor de renderização do navegador:

  • Modo Imediato (Canvas): Ao desenhar um retângulo ou círculo no Canvas, o navegador calcula os pixels e os grava diretamente no buffer de vídeo. Uma vez desenhado, o navegador “esquece” o que aquela forma representa; ela se torna apenas um conjunto de pixels coloridos. Se você quiser mover o objeto, precisará limpar a tela e redesenhá-lo na nova coordenada.
  • Modo Retido (DOM e SVG): Elementos HTML comuns e nós SVG permanecem como objetos na árvore do DOM. Eles mantêm estado próprio, aceitam classes CSS e respondem a eventos de clique individuais.

💡 Analogia da Vida Real: O Pintor e a Tela

O elemento <canvas> é o tecido da tela esticado no cavalete. Ele não possui pincéis nem tintas próprias. A ferramenta que realiza a pintura é o Contexto 2D (CanvasRenderingContext2D), acessado e manipulado através do JavaScript.

2. Anatomia Básica e Sistema de Coordenadas

A declaração da tag no HTML exige atenção especial às dimensões da tela:

HTML5 4 linhas
<canvas id="meuCanvas" width="600" height="400" role="img" aria-label="Demonstração gráfica 2D">
    <!-- Texto de fallback para navegadores legados ou leitores de tela -->
    Seu navegador não possui suporte ao elemento HTML5 Canvas.
</canvas>

Aviso crucial sobre dimensões: Os atributos width e height declarados diretamente na tag definem a resolução interna de pixels (o buffer de desenho). Se você alterar a largura e a altura apenas por regras de CSS externo sem sincronizar esses atributos, o navegador esticará a imagem como se fosse um arquivo bitmap ampliado, provocando distorções e serrilhamento.

O Plano Cartesiano do Canvas

Diferente da geometria matemática tradicional onde a origem fica no centro ou no canto inferior esquerdo, no Canvas o ponto (x: 0, y: 0) está situado no canto superior esquerdo:

  • O eixo X cresce horizontalmente para a direita.
  • O eixo Y cresce verticalmente para baixo.

3. Formas Primitivas e Caminhos (Paths)

Para começar a desenhar, obtemos a referência do elemento no DOM e instanciamos o contexto de renderização bidimensional com getContext('2d'):

JavaScript 29 linhas
const canvas = document.getElementById('meuCanvas');
const ctx = canvas.getContext('2d');
 
// 1. Retângulos Primitivos
ctx.fillStyle = '#3b82f6'; // Cor de preenchimento (azul)
ctx.fillRect(50, 40, 150, 100); // x, y, largura, altura
 
ctx.strokeStyle = '#1e293b'; // Cor de contorno (grafite escuro)
ctx.lineWidth = 4; // Espessura da borda
ctx.strokeRect(50, 40, 150, 100);
 
// 2. Caminhos Personalizados (Linhas e Triângulos)
ctx.beginPath(); // Inicia um novo traçado
ctx.moveTo(280, 140); // Posiciona a caneta virtual
ctx.lineTo(360, 40);  // Traça linha até o topo
ctx.lineTo(440, 140); // Traça linha descendo
ctx.closePath();      // Conecta o final de volta ao ponto de início
 
ctx.fillStyle = '#10b981'; // Verde esmeralda
ctx.fill(); // Preenche a forma
ctx.stroke(); // Aplica a linha de contorno
 
// 3. Círculos e Arcos
ctx.beginPath();
// arc(x, y, raio, anguloInicial, anguloFinalEmRadianos, sentidoAntiHorario)
ctx.arc(520, 90, 45, 0, Math.PI * 2);
ctx.fillStyle = '#f59e0b'; // Âmbar
ctx.fill();
ctx.stroke();

4. Exemplo Completo: Animação Fluida a 60 FPS com requestAnimationFrame

Para criar animações profissionais no Canvas, nunca utilize laços while ou setInterval. A prática padrão da indústria é recorrer à função requestAnimationFrame(), que sincroniza a taxa de redesenho com a taxa de atualização do monitor do usuário economizando bateria e processamento:

HTML5 55 linhas
<div class="wzw-canvas-container">
    <canvas id="canvasAnimado" width="600" height="350"></canvas>
</div>
 
<script>
const c = document.getElementById('canvasAnimado');
const ctx = c.getContext('2d');
 
// Estado da partícula animada
let x = 100;
let y = 100;
let velX = 4;
let velY = 3;
const raio = 25;
 
function animar() {
    // 1. Limpa a tela inteira antes de renderizar o novo quadro
    ctx.clearRect(0, 0, c.width, c.height);
 
    // 2. Fundo decorativo sutil
    ctx.fillStyle = '#0f172a';
    ctx.fillRect(0, 0, c.width, c.height);
 
    // 3. Desenha a partícula com gradiente radial dinâmico
    const gradiente = ctx.createRadialGradient(x - 5, y - 5, 2, x, y, raio);
    gradiente.addColorStop(0, '#60a5fa');
    gradiente.addColorStop(1, '#1d4ed8');
 
    ctx.beginPath();
    ctx.arc(x, y, raio, 0, Math.PI * 2);
    ctx.fillStyle = gradiente;
    ctx.fill();
    ctx.lineWidth = 3;
    ctx.strokeStyle = '#93c5fd';
    ctx.stroke();
 
    // 4. Detecção de colisão com as bordas da tela
    if (x + raio >= c.width || x - raio <= 0) {
        velX = -velX; // Inverte o vetor horizontal
    }
    if (y + raio >= c.height || y - raio <= 0) {
        velY = -velY; // Inverte o vetor vertical
    }
 
    // 5. Atualiza coordenadas para o próximo quadro
    x += velX;
    y += velY;
 
    // 6. Agenda o próximo ciclo de animação do navegador
    requestAnimationFrame(animar);
}
 
// Inicializa a animação
requestAnimationFrame(animar);
</script>
🧪 Quer ver esta animação e renderização 2D funcionando agora?
⚡ Abrir no Playground IDE →

5. Nitidez em Telas Retina e Telas de Alta Resolução (High-DPI)

Em telas modernas de smartphones ou monitores 4K/Retina, a proporção de pixels físicos por pixel CSS (window.devicePixelRatio) costuma ser 2x ou 3x. Se você não compensar essa escala, o Canvas parecerá borrado. A solução definitiva de mercado consiste em multiplicar a resolução do buffer e reescalar o contexto:

JavaScript 20 linhas
function ajustarCanvasRetina(canvasElement, larguraCss, alturaCss) {
    const dpr = window.devicePixelRatio || 1;
    
    // 1. Amplia a contagem de pixels do buffer interno
    canvasElement.width = larguraCss * dpr;
    canvasElement.height = alturaCss * dpr;
 
    // 2. Mantém o tamanho geométrico na tela via CSS
    canvasElement.style.width = larguraCss + 'px';
    canvasElement.style.height = alturaCss + 'px';
 
    // 3. Normaliza o sistema de coordenadas do contexto
    const contexto = canvasElement.getContext('2d');
    contexto.scale(dpr, dpr);
 
    return contexto;
}
 
// Uso: Cria um canvas de 500x300 ultra-nítido em qualquer monitor
const ctxHiDPI = ajustarCanvasRetina(document.querySelector('#meuCanvas'), 500, 300);

6. Ferramentas Relacionadas & Próximos Passos

Continue seu aprendizado explorando as soluções de mídia e código do nosso ecossistema:

7. Referências Técnicas & Especificações Oficiais


Rolar para cima