HTML5: desenhando gráficos no browser com Canvas
Aprenda como desenhar formas geométricas e gráficos no navegador usando JavaScript e Canvas do HTML5
Com a popularização da web e a rápida evolução dos navegadores hoje em dia é possível ter gráficos, animações e até jogos completos rodando diretamente no seu navegador sem ajuda de tecnologias como Flash ou Java Applet. O que estou querendo dizer é que não precisamos mais instalar um plugin ou software no computador do usuário para rodar jogos ou animações 2D complexas. Isso só se tornou possível graças a chegada e adoção do HTML5 e sua nova tag canvas.
Para quem ainda não conhece, o canvas é um elemento HTML usado para desenhar gráficos, textos e animações diretamente no browser do usuário. Podemos definir o canvas como um elemento que aceita desenhos dentro dele, igual a um quadro branco de pintura. Para desenhar qualquer coisa no canvas nós utilizamos a linguagem de programação JavaScript. Se você já programou com outra tecnologia para renderização de gráficos então você se dará bem com a API JavaScript do Canvas, pois ela possui várias funções nativas que ajudam o desenvolvedor a fazer estes desenhos na tela, como funções para desenhar quadrados, círculos, textos e imagens.
Criando seu canvas
Agora que já sabemos o que é um canvas, vamos começar a usar um numa página HTML. Para isso, abra um bloco de notas ou qualquer editor de texto que preferir, crie um arquivo texto e adicione este conteúdo:
<html>
<body>
<canvas id="meuCanvas">
Seu navegador não suporta Canvas do HTML5.
</canvas>
</body>
</html>
Salve o arquivo, abra em algum navegador que suporte HTML5 e veja um elemento canvas em sua tela...
o meu já deu errado, não tem nada na tela...
Não se preocupe! Não há nada de errado, o seu canvas está na tela e você está vendo ele, porém ele é um quadro transparente em um fundo branco, não possui nenhum desenho ainda. No caso do seu navegador não suportar canvas, você visualizará a mensagem de fallback que colocamos dentro da tag canvas: "Seu navegador não suporta Canvas do HTML5.".
Se você mantém seu navegador atualizado então as chances são de que ele rodará o canvas sem problemas, pois os navegadores mais modernos já suportam o Canvas do HTML5 faz um bom tempo, como você pode ver na imagem abaixo:
Com o canvas na página, já podemos iniciar o desenho e ai sim veremos algo na tela...
O primeiro desenho: linhas
Como já falamos, embora o canvas seja uma tag HTML, nós desenharemos dentro dele de forma programática usando JavaScript. Sendo, no arquivo HTML criado no passo anterior adicione a tag <script />
logo abaixo da tag <canvas />
, pois a partir de agora todo código JavaScript ficará dentro desta tag:
<canvas id="meuCanvas"></canvas>
<script>
// seu código javascript vai aqui
</script>
Após criar a tag, a primeira coisa que devemos fazer dentro dela é obter a representação do elemento canvas
no JavaScript, para isso utilizaremos o método getElementById
do objeto document
:
<script>
var canvas = document.getElementById('meuCanvas');
</script>
A varíavel canvas
funciona como um quadro na qual podemos desenhar o que quisermos. Mas para desenhar precisamos antes de um pincel, portanto, para obter a representação deste pincel no JavaScript basta invocar o método getContext
do canvas
que acabamos de criar, como abaixo:
var pincel = canvas.getContext('2d');
Ao informar o valor "2d" no método getContext
estamos informando ao canvas que iremos trabalhar em 2 dimensões, ou seja, com os eixos X e Y. Com o pincel em mãos já podemos movê-lo para o ponto (x=0, y=0) e partir daí projetar uma linha até o ponto (x=200, y=200), como a seguir:
pincel.moveTo(0, 0);
pincel.lineTo(200, 200);
Por fim, para que a linha seja de fato renderizada (pintada) no canvas nós precisamos invocar o método stroke
na qual fará o contorno da linha:
pincel.stroke();
No fim das contas nosso código ficará como abaixo:
<script>
var canvas = document.getElementById('meuCanvas');
var pincel = canvas.getContext('2d');
pincel.moveTo(0, 0);
pincel.lineTo(200, 200);
pincel.stroke();
</script>
Agora, atualize a página que você criou no primeiro passo e veja o desenho que você fez em seu canvas:
Simples, não é?
Podemos fazer mais do que um risco diagonal na tela. Podemos desenhar diversas formas geométricas dentro canvas...
Desenhando retângulos
Tomando como base o exemplo anterior, seria preciso projetar 4 linhas a fim de desenhar o retângulo. Não é algo muito produtivo, certo? Para facilitar a vida do desenvoveldor, o objeto context
(que é nosso pincel) já possui um método nativo para desenhar retângulos. Este método é o rect
.
O método rect
recebe 4 parâmetros, sendo eles x
, y
, largura
e altura
. Os pontos X e Y são os respectivos valores da posição do retângulo dentro do canvas, enquanto a largura e altura são as medidas da figura:
pincel.rect(x, y, largura, altura);
Portanto, para desenhar um retângulo no canvas bastaria um código semelhante a este:
<script>
var canvas = document.getElementById('meuCanvas');
var pincel = canvas.getContext('2d');
pincel.rect(20, 0, 150, 120);
pincel.stroke();
</script>
Perfeito! Ao atualizar seu navegador você deve ver o seguinte desenho:
Repare que tivemos que definir o retângulo no método rect
e logo após invocar o método stroke
para fazer o contorno da figura. Não é algo trabalhoso, mas para agilizar ainda mais o desenho de retângulos nós podemos usar o método strokeRect
:
pincel.strokeRect(20, 0, 150, 120);
Até este momento só fizemos o contorno do retângulo, porém podemos pintar o corpo da figura. Para preencher o interior da figura com alguma cor basta invocarmos o método fill
do context
:
// preenche com a cor preta (cor padrão do pincel)
pincel.fill();
// preenche com outra cor
pincel.fillStyle = "orange";
pincel.fill();
Similar ao método strokeRect
que agiliza o desenho do retângulo, nós podemos usar o método fillRect
para fazer as duas coisas ao mesmo tempo, neste caso desenhar e preencher o retângulo com uma cor:
pincel.fillStyle = "orange";
pincel.fillRect(20, 0, 150, 120);
A propriedade fillStyle
nos permite definir o estilo de como nossa figura será preenchida, como cor, gradiente e imagem. Caso a propriedade não seja definida a cor padrão utilizada será preta.
Desenhando círculos
Além de retângulos também podemos desenhar círculos de maneira muito semelhante. O método do context
para desenhar círculos é o arc
, na qual recebe 5 parâmetros: os 2 primeiros é o local no canvas em que o círculo será desenhado; os outros 3 são respectivamente o raio do círculo, o ângulo inicial em radianos e o ângulo final em radianos do desenho:
pincel.arc(x, y, raio, anguloInicial, anguloFinal);
Dessa forma, para desenhar um círculo no canvas só precisamos de algo como:
<script>
var canvas = document.getElementById('meuCanvas');
var pincel = canvas.getContext('2d');
pincel.arc(100, 80, 50, 0, Math.PI * 2);
pincel.stroke();
</script>
Ao rodar este código no navegador ele irá renderizar um círculo dentro do canvas:
Basicamente só precisamos conhecer os parâmetros do método arc
! Também podemos colorir o corpo do círculo como fizemos com o retângulo. Agora, vamos partir para figuras mais complexas e ver como o canvas trabalha...
Trabalhando com múltiplas figuras
É muito comum termos diversos gráficos e figuras no mesmo canvas em posições, tamanhos e cores diferentes. Dessa forma, vamos desenhar 2 círculos de tamanhos diferentes e preencher somente o segundo com a cor preta:
<script>
var canvas = document.getElementById('meuCanvas');
var pincel = canvas.getContext('2d');
// circulo 1
pincel.arc(100, 80, 50, 0, Math.PI * 2 );
pincel.stroke();
// circulo 2
pincel.arc(30, 30, 25, 0, Math.PI * 2);
pincel.fill();
</script>
Ao atualizar o navegador você deve ver os seguintes desenhos:
Repare que ambos os círculos foram preenchidos e não somente o segundo como esperávamos. Isto acontece pois o canvas entende que estamos trabalhando em cima do mesmo e único desenho. Para resolver isso precisamos tratar os círculos como 2 desenhos distintos. Para isso, cada desenho deve ser iniciado e finalizado usando os métodos beginPath
e closePath
do context
, como a seguir:
pincel.beginPath(); // inicia figura 1
pincel.arc(100, 80, 50, 0, Math.PI * 2 );
pincel.stroke();
pincel.closePath(); // finaliza figura 1
pincel.beginPath(); // inicia figura 2
pincel.arc(30, 30, 25, 0, Math.PI * 2);
pincel.fill();
pincel.closePath(); // finaliza figura 2
Pronto! Após alterar o código o resultado no navegador muda para a figura abaixo:
Como você pode ver, o método beginPath
serve para iniciar um novo desenho ou redefinir um desenho já existente. É como se estivéssemos dizendo para o browser para ele iniciar um novo desenho e preencher os "caminhos" (paths) de forma independente.
Além de figuras geométricas também podemos renderizar imagens comuns dentro do canvas...
Renderizando imagens
Também é possível renderizar imagens dentro do canvas, como um jpeg ou png. Para isso, basta chamar o método drawImage
do context
. Este método possui várias combinações de parâmetros, porém podemos usar a combinação mais simples:
pincel.drawImage(imagem, x, y);
Para entender melhor, veja o exemplo abaixo:
<script>
var canvas = document.getElementById('meuCanvas');
var pincel = canvas.getContext('2d');
// cria a imagem e faz o download do servidor
var logo = new Image();
logo.src = 'logo-triadworks.png';
// renderiza a imagem quando a página terminar de carregar
logo.onload = function() {
pincel.drawImage(logo, 0, 20);
};
</script>
Agora basta atualizar o navegador para ver o resultado:
Um detalhe importante no código acima é que o método drawImage
somente será invocado quando a imagem estiver completamente carregada pelo browser, caso contrário, a imagem não será exibida no canvas.
Mas nem só de gráficos geométricos e imagens vive um desenho, não é? Com canvas também podemos adicionar textos ao nosso desenho...
Desenhando textos no canvas
Podemos renderizar textos com diversas cores, tamanhos e fontes. Mais uma vez o canvas nos fornece alguns métodos nativos. Por exemplo, usando os métodos fillText
e strokeText
podemos escrever um texto com interior preenchido ou somente bordas. A assinatura dos métodos é bem simples:
pincel.fillText(texto, x, y);
pincel.strokeText(texto, x, y);
Para renderizar 2 textos no canvas basta um código parecido com este:
<script>
var canvas = document.getElementById('meuCanvas');
var pincel = canvas.getContext('2d');
pincel.font = "30px Verdana";
pincel.fillStyle = "orange";
pincel.fillText("Iniciando com o <canvas>", 40, 40);
pincel.strokeText("Iniciando com o <canvas>", 80, 80);
</script>
O resultado será como a seguir:
Repare que neste exemplo usamos a fonte Verdana com tamanho de 30px, mas é possível carregar qualquer outra fonte contanto que ela seja devidamente referenciada em um arquivo CSS da sua página.
Desenhando a logo da empresa com canvas
O uso de Canvas é viciante! Para você ter idéia, enquanto discutia o post com o Handerson Frota e Rafael Ponte eu acabei desenhando a logo da TriadWorks utilizando apenas a API JavaScript do Canvas que vimos nesse post e mais algumas poucas funções. O resultado final da logo você pode ver abaixo:
Ficou muito massa, não foi? Se quiser ver o código completo dá uma olhada nesse gist! Para testar baixe o código em um .html e abra no seu navegador!
Canvas é só o começo...
Canvas é muito mais poderoso do que esse artigo poderia descrever. Ele é a base para o implementação de gráficos e animações complexas; o alicerce para escrita de jogos completos que rodam no navegador. A cada dia ele se populariza mais e vai ganhando espaço na área comercial de sistemas corporativos e games.
Falando em games, não é por acaso que existem inúmeras engines e frameworks criados em cima do Canvas e JavaScript para o desenvolvimento de jogos, como por exemplo o Canvas Engine. Com essas engines o desenvolvedor se preocupa apenas com a lógica do jogo e não com detalhes mais técnicos como API de Audio, efeitos e animações, uso do teclado e mouse, física e colisão entre objetos etc.
Este artigo foi somente uma introdução a canvas, o uso básico da tag e sua API JavaScript. Para aprender mais sobre Canvas e principalmente JavaScript você pode conhecer nosso curso de Lógica de Programação.
E você, já usou Canvas para criar gráficos, animações ou algum jogo?
You might also be interested in these articles...
Desenvolvedor de software na XLung