O que é canvas e de onde ele surgiu?

Canvas foi uma tecnolgia criada pela apple e incorporada primeiramente ao motor de renderização webkit (safari), mas tarde foi inserida no Gecko e no Opera e padronizada pelo WHATWG.

Introdução:

Antes de mais nada quero esclarecer que esse post é um tutorial, para pessoas que querem aprender o canvas rápidamente…. caso você queira entender a fundo como funciona de uma olhada nos seguintes links:

para começar, antes de tudo devemos iniciar a tag <canvas> exemplo:

<canvas id="c1" width="500" height="500">
Aqui dentro você pode colocar qualquer coisa que vai aparecer caso o navegador não tenha suporte ao elemento canvas.
</canvas>

O elemento canvas tem 2 atributos para definir o tamanho (width e height) e 1 atributo para identificação (id), somente.

Desenhando:

A primeira coisa a se fazer é obter a referência ao objeto, e tentar instânciar o objeto CanvasRenderingContext2D

<canvas id='ex' width='250' height='250'>
      inicia o html
</canvas>

<script language='javascript'>
 // Pega a referência ao elemento canvas do html
 var canvas = document.getElementById("ex");

 // Pega o objeto CanvasRenderingContext2D
 var ctx = canvas.getContext("2d");

 ctx.fillStyle = "rgb(200,0,0)"; // cor de preenchimento
 ctx.fillRect(10, 10, 55, 50); // desenha um retângulo

 ctx.fillStyle = "rgba(0, 0, 200, 0.5)"; // cor de preenchimento
 ctx.fillRect (30, 30, 55, 50); // desenha outro retângulo
</script>

demonstração deste exemplo

No nosso exemplo a cima a variável ctx contém uma referência para o objeto CanvasRenderingContext2D onde contém as propriedades e métodos responsáveis pela mágica. Na linha 12 inserimos uma cor de preenchimento, as cores utilizadas devem seguir o padrão CSS ou CanvasGradient e CanvasPattern.

Esse é o princípio básico de canvas:

  1. Declare as tags <canvas>, de preferência adicione o atributo ID
  2. Obtenha a referência ao canvas, nesse caso utilizamos o o ‘document.getElementById()
  3. Obter uma referência ao Context, no nosso caso o ‘2D Context‘, terceiros podem desenvolver outros Context, como o moz-3d e agora o WebGL, falaremos do WebGL mais tarde.

Retângulos

Atualmente temos 3 funções para desenha retângulos:

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

 ctx.fillStyle = "rgb(200,0,0)";
 ctx.fillRect(10, 10, 40, 40);

 ctx.strokeStyle = "rgb(0, 0,255)";
 ctx.strokeRect(60, 10, 40, 40);

 ctx.clearRect(30, 15, 50, 30);

demonstração deste exemplo.

Formas complexas

O Context2D só tem retângulos como formas primitivas, para criar diferentes formas devemos utilizar Paths (caminhos), as funções de Path são:

  • void beginPath() : Reseta o Path atual
  • void closePath() : Marca o atual Path como fechado.
  • void moveTo(in float x, in float y) : Cria um novo subPath do ponto fornecido
  • void lineTo(in float x, in float y) : Adiciona ao Path atual um novo ponto, conectando-o com o ponto anterior através de uma linha reta.
  • void quadraticCurveTo(in float cpx, in float cpy, in float x, in float y) : Adiciona um ponto ao atual Path, conectando-o com o ponto anterior através de uma curva quadratic Bézier com o ponto de controle passada.
  • void bezierCurveTo(in float cp1x, in float cp1y, in float cp2x, in float cp2y, in float x, in float y) : Adiciona um ponto ao atual Path, conectando-o com o ponto anterior através de um cubic Bézier com os pontos de controle fornecidos.
  • void arcTo(in float x1, in float y1, in float x2, in float y2, in float radius) : Adiciona um ponto ao atual Path, conectando-o com o ponto anterior através de uma linha reta, então adiciona um segundo ponto ao atual Path, conectando-o com o anterior por um arc cujo as propriedades são descritas pelos argumentos passados.Lança um exception INDEX_SIZE_ERR se o radiano é negativo
  • void arc(in float x, in float y, in float radius, in float startAngle, in float endAngle, in boolean anticlockwise) : Adiciona um ponto ao subPath de tal forma que o arc descreve uma circuferência de um circulo descrito pelos argumentos passados, o ponto se inicia com o start angle e finaliza ao end angle, vai na direção dada e é adicionado ao atual Path conectando-o com o ponto anterior em uma linha reta.Lança uma exception INDEX_SIZE_ERR se o radiano é negativo.
  • void rect(in float x, in float y, in float w, in float h) : Adiciona um novo subPath fechado ao atual Path, representando um retângulo.
  • void fill() : Preenche o subPath com o atual fill style.
  • void stroke() : Strokes o subPath com o atual stroke style. (não consegui traduzir a palavra stroke)
  • void clip() : Adiciona outras restrições a região de recorte para o caminho dado.
  • boolean isPointInPath(in float x, in float y) : Retorna true se o ponto dado está dentro do atual Path.

você não precisa gravar todas elas, ao menos por enquanto, vamos ao mais básico, desenhar uma reta:

	 ctx.beginPath();
	 ctx.moveTo(10, 10);
	 ctx.lineTo(240, 10);
	 ctx.closePath();

	 ctx.stroke();

demonstração deste exemplo

  1. a primeira coisa que fazemos é iniciar um novo Path com o método beginPath()
  2. movemos a ‘ponta da caneta’ para uma determinada coordenada dentro do canvas com o moveTo()
  3. utilizamos o método lineTo() que vai desenha uma linha reta do último ponto declarado, no nosso caso com moveTo() até o x e y nele passado como parâmetro
  4. em seguida fechamos o nosso Path atual com o closePath() (ou não, depende da sua finalidade, nesse caso não é necessário mas é uma boa prática fechar o Path)
  5. e por último precisamos dar cor a nossa reta, utilizamos o método stroke().

OBS: Os termos utilizados acima são representativos para melhor aprendizado, para saber mais sobre como o Path API funciona leia a especificação do W3C.

Exemplo de um triângulo:

	 ctx.strokeStyle = 'rgb(255, 0, 0)';
	 ctx.fillStyle = 'rgb(0, 200, 255)';

	 ctx.beginPath();
	 ctx.moveTo(10, 125);
	 ctx.lineTo(125, 20);
	 ctx.lineTo(240, 125);
	 ctx.closePath();

	 ctx.stroke();
	 ctx.fill();

demonstração deste exemplo

Linhas Curvas

  • void quadraticCurveTo(in float cpx, in float cpy, in float x, in float y);
  • void bezierCurveTo(in float cp1x, in float cp1y, in float cp2x, in float cp2y, in float x, in float y);

Temos essas duas funções no Context2D para fazer linhas curvas, a diferença entre elas é o ponto de curva, enquanto no quadraticCurveTo() temos somente 1 ponto base para a curva no bezierCurveTo() temos 2 pontos. O gráfico que melhor demonstra essas funções, segue abaixo, fonte mozilla developer (onde também tem um excelente tutorial, apenas em inglês).

  • quadraticCurveTo() : recebe duas coordenadas como parâmetros, a primeira coordenada (cpx, cpy) é demonstrado com o ponto vermelho na imagem ao lado, e a segunda coordenada (x, y) é o ponto final da reta, demonstrado como pontos azuis, onde um ponto azul é o começo do Path declarado com o moveTo() por exemplo, e o outro ponto azul é o final do Path passado pelos parâmetros x e y da função quadraticCurveTo().
  • bezierCurveTo() : recebe 3 coordenadas como parâmetro, as coordenadas cp1x, cp1y, cp2x e cp2y são as coordenadas dos dois pontos vermelhos demonstrados na imagem ao lado. A terceira coordenada (x, y) é o fim da reta demonstrado com qualquer um dos pontos azuis da imagem ao lado.

Essas duas funções requerem uma atenção na aprendizagem, porque você só vai aprender a manipular elas praticando, segue exemplo de utilização delas abaixo (com linhas guias em vermelho):

	 ctx.strokeStyle = 'rgb(0, 0, 0)';
	 ctx.fillStyle = 'rgb(225, 225, 255)';

	 ctx.beginPath();
	 ctx.moveTo(10, 145);
	 ctx.quadraticCurveTo(75, 10, 145, 145);
	 ctx.closePath();
	 ctx.stroke();
	 ctx.fill();

demonstração desse exemplo

	 // curve path 1
	 var cp1x = 20;
	 var cp1y = 50;

	 // curve path 2
	 var cp2x = 220;
	 var cp2y = 200;

	 // end path
	 var endx = 125;
	 var endy = 240;

	 ctx.beginPath();
	 ctx.moveTo(125, 10);
	 ctx.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, endx, endy);
	 ctx.stroke();

demonstração desse exemplo

Arcos e Circulos

para desenha arcos e circulos nós utilizamos o seguinte método:

  • arc(x, y, radius, startAngle, endAngle, anticlockwise)

Este método faz parte do conjunto de API Path, temos 6 parâmetros que por si só já são auto descritivos, segue um exemplo de utilização abaixo:

	for (var i = 1; i < 5; i++) {

		var x = i * 50;
		var y = 50;
		var radius = 20;
		var startAngle = 0;
		var endAngle = (Math.PI * i) / 2;
		var anticlockwise = false;

		context.beginPath();
		context.arc(x, y, radius, startAngle, endAngle, anticlockwise);
		context.stroke();
	}

demonstração desse exemplo

Referências / Observações:

além dos links colocados durante o post vou citar mais uma excelente referência que é o site da developper.apple.com onde você encontra em uma unica página todos as funções do context 2D, uma excelente referência de funções.

Se você quiser se aprofundar, mergulhe de cabeça porque isso é só o começo tem muita coisa além disso, além é claro do WebGL, um lugar onde eu recomendo a leitura sobre canvas, WebGL e outros é no mozilla developer.

WebGL é o context 3D baseado no OpenGL ES, e que, vale ressaltar que o Firefox 4 já vem com WebGL Experimental nativo, porém não ativo como default, é preciso ativa-lo (ao menos na versão beta do navegador):

  1. Digite ‘about:config‘ na URL do navegador
  2. procure por ‘webgl
  3. de dois cliques em “enabled_for_all_sites” para ativar.

O rascunho da especificação você encontra aqui e uma demonstração do webGL aqui.

exemplo w3c Context2D

Boa Sorte!

Posts Relacionados