Pong

Uma bola que sai do canto superior esquerdo com um determinado ângulo e velocidade e, ao batar numa tabela, reflete o movimento com o mesmo ângulo, no sentido oposto.

É um exemplo simples de uma animação criada com a função setInterval. Mais à frente usaremos outra forma de criar animações.

A direção inicial é dada pelos valores de incx e incy. O ecrã é atualizado a cada 40ms. Em cada atualização do ecrã, a posição da bola é atualizada com os incrementos incx e incy. Estes incrementos são atualizados sempre que a bola bate nas extremidades do canvas.

Note-se que o canvas tem que ser totalmente rescrito em cada frame.

Visualização:

<!DOCTYPE html>
<html>
<head>
<title>Gráfico</title>
<meta charset="iso-8859-1">
<script type="text/javascript">

var incx = 3 + 6 * Math.random();	// direção- coordenada x
var incy = 3 + 6 * Math.random();	// direção- coordenada y

// Garante velocidade mínima
var vMin = 8;
var vel = Math.sqrt(incx*incx+incy*incy);
if(vel<vMin) {
	incx *= vMin/vel;	
	incy *= vMin/vel;
}
// Nota: Para garantir velocidade mínima exata de vMin, era necessário corrigir as fórmulas anteriores com base na direção da velocidade.
// É preferível não tornar isto muito mais complexo, para não dificultar a compreensão.

incx = Math.floor(incx);
incy = Math.floor(incy);

var raio=5;	// raio do ponto cintilante
var x=raio, y=raio; 	// coordenadas do ponto cintilante

var ctx;

var larg, alt;

function init() {
	var c = document.getElementById("cvs");
	ctx = c.getContext("2d");
	larg = c.getAttribute("width");
	alt = c.getAttribute("height");
	var periodoRelogio = 40;
	setInterval("anima()", periodoRelogio);
}

function anima() {
	// Desenhar
	ctx.fillStyle = "black";
	ctx.beginPath();
	ctx.rect(0,0,larg,alt);
	ctx.fill();

	x += incx;
	y += incy;

	//window.alert(x+','+y);

	ctx.fillStyle = "#FFFF20";
	ctx.beginPath();
	ctx.arc(x,y,raio,0,2*Math.PI);
	ctx.fill();

	if(x+2*raio>larg) incx = -incx;
	if(x-raio<0) incx = -incx;
	if(y+2*raio>alt) incy = -incy;
	if(y-raio<0) incy = -incy;
}

</script>


</head>
<body onload="init();">
<canvas width="600" height="400" id="cvs"></canvas>
</body>
</html>

Programar no Canvas

O HTML5 introduziu um novo objeto – o canvas – onde é possível programar em javascript, como uma tela, da mesma forma que se programa sobre painéis em Java.

Há uma série de funções predefinidas para desenhar círculos, retângulos, linhas e escrever textos, com a cor, espessura e fonte que quisermos.

No exemplo abaixo, criamos um canvas com 600px de largura e 400px de altura, e desenhamos dois retângulos, uma circunferência e um círculo, assim como 6 linhas que unem estes 4 objetos.

Visualização:

Código HTML

<!DOCTYPE html>
<html>
<head>
<title>Canvas e Javascript</title>
<meta charset="iso-8859-1">
<script type="text/javascript" src="codigo.js"></script>
</head>
<body onload="inicia();">
<h3>Canvas e Javascript</h3>
<canvas width="640" height="480" id="tela"></canvas>
</body>
</html>

Código javascript


function inicia() {
	var canvas = document.getElementById("tela");
	var larg = canvas.getAttribute("width");
	var alt = canvas.getAttribute("height");

	// Aceder ao contexto gráfico do canvas
	var ctx = canvas.getContext("2d");

	// Retângulo do fundo
	ctx.fillStyle = "#60FFFF";
	ctx.beginPath();
	ctx.rect(0,0,larg,alt);
	ctx.fill();

	// Retângulo cima, esquerda
	ctx.fillStyle = "red";
	ctx.beginPath();
	ctx.rect(80,70,70,50);
	ctx.fill();

	// Retângulo cima, direita
	ctx.fillStyle = "blue";
	ctx.beginPath();
	ctx.rect(450,70,70,50);
	ctx.fill();

	// Círculo baixo esquerda (circunferência)
	ctx.lineWidth = 5;
	ctx.strokeStyle = "#008000";
	ctx.beginPath();
	ctx.arc(115,305,35,0,2*Math.PI);
	ctx.stroke();

	// Círculo baixo direita
	ctx.lineWidth = 5;
	ctx.fillStyle = "#FFFF20";
	ctx.beginPath();
	ctx.arc(485,305,35,0,2*Math.PI);
	ctx.fill();

	// Linha entre os retângulos
	poeLinha(ctx,115,95,485,95,"black");
	poeLinha(ctx,115,305,485,305,"white");
	poeLinha(ctx,115,95,115,305,"khaki");
	poeLinha(ctx,485,95,485,305,"purple");
	poeLinha(ctx,115,95,485,305,"magenta");
	poeLinha(ctx,115,305,485,95,"#123456");
}

function poeLinha(ctx,x1,y1,x2,y2,cor) {
	ctx.strokeStyle = cor;
	ctx.beginPath();
	ctx.moveTo(x1,y1);
	ctx.lineTo(x2,y2);
	ctx.stroke();
}

A função ctx.arc permite desenhar um arco com a amplitude (em radianos) pretendida. Para desenhar um círculo, precisamos de desenhar de 0 a 2*PI (dois últimos parâmetros). Os dois primeiros parâmetros são as coordenadas do centro, e o terceiro parâmetro é o raio.

ctx.arc(485,305,35,0,2*Math.PI);

Os parâmetros da função ctx.rect são mais intuitivos: abcissa e ordenada do canto superior esquerdo, largura e altura do retângulo.

ctx.rect(450,70,70,50);

As funções do tipo stroke desenham apenas a linha, enquanto que as funções do tipo fill preenchem a figura.

Resultado final:
canvas1

Captcha com Canvas e Javascript

Há uns anos atrás fiz um captcha em PHP com o jpgraph. Funcionava bem, mas dependia de uma ferramenta que foi deixando de ser de uso livre (o jpgraph) e, como estava a correr em Linux, o uso de tipos de letras diferentes estava muito limitado.

Ontem descobri que um dos captchas que estava a usar num jogo – Domaisnquest – não estava a funcionar. Decidi deitar fora, de vez, o jpgraph e criar um novo captcha feito com um Canvas de HTML5 e javascript.

Visualização:

Ficheiro: CapCanvas.js


/*************
 * Class CapCanvas
 * Parameters
 * - w: canvas width			[number]
 * - h: canvas height			[number]
 * - n: number of digits (default 5)	[number]
 * - s: font size (default 16px)	[number]
 * - f: font-family (default random)	[text]
 * 
 */

function CapCanvas(w,h,n,s,f) {
	var ctx;
	var key;
	var cvsName = 'capcvs';
	var fonts = new Array("Arial", "Courier", "Times New Roman");
	var colors = new Array("yellow", "blue", "black", "gray", "red", "green", "salmon", "purple", "coral", "darkkhaki", "darkolivegreen", "honeydew", "turquoise", "white");
	if(n==undefined) n=5;
	if(s==undefined) s=16;
	if(f==undefined) {
		f = fonts[rand(fonts.length)];
	}

	document.write("<canvas id='"+cvsName+"' width='"+w+"' height='"+h+"' title=\"Click to change if you can't read the letters\" style='cursor:pointer;' onclick='capCanvas.chgCap();'></canvas>");
	ctx = document.getElementById(cvsName).getContext("2d");
	chgCap();


	function putLine(x1,y1,x2,y2,c) {
		ctx.strokeStyle = c;
		ctx.beginPath();
		ctx.moveTo(x1,y1);
		ctx.lineTo(x2,y2);
		ctx.stroke();
	}

	this.chgCap = chgCap;
	function chgCap() {
		var c = colors[rand(colors.length)];
		var c2,c3;
		do{
			c2 = colors[rand(colors.length)];
		}while(c==c2);
		do{
			c3 = colors[rand(colors.length)];
		}while(c==c3 || c2==c3);
		key = newKey(n);
		f = fonts[rand(fonts.length)];

		ctx.fillStyle = c;
		ctx.beginPath();
		ctx.rect(0,0,w,h);
		ctx.fill();

		ctx.lineWidth = 2;

		//Draw lines
		var p = rand(5)+5;
		var inc = Math.floor(w/p);
		for(var i=0; i<p; i++) {
			putLine(i*inc,0,(i+1)*inc,h,c2);
		}
		var mp = Math.floor(p*inc/2);
		var h2 = Math.floor(h/2);
		putLine(mp,0,0,h2,c2);
		putLine(w,0,0,h,c2);
		putLine(w,h2,mp,h,c2);

		// Text
		ctx.fillStyle = c3;
		ctx.font = s + "px '"+f+"'";
		//ctx.font = "16px 'Arial'";
		ctx.textAlign = "center";
		ctx.textBaseline = "middle";
		var tx = Math.floor(w/2);
		var ty = Math.floor(h/2);
		ctx.fillText(key, tx, ty);

	}

	this.keyCheck = keyCheck;
	function keyCheck(k) {
		return k==key;
	}

	function newKey(t) {
		var kk = "";
		// Chars I want to use
		var crs = "A B C D E F G H J K L M N P Q R S T W X Y Z 2 3 4 5 6 7 8 9".split(" ");
		while(kk.length<t) {
			var r = rand(crs.length);
			if (crs[r]!=" ") {
				kk += crs[r];
			}
		}
		return kk;
	}


	function rand(n) {
		return Math.floor(n*Math.random());
	}
}

var capCanvas = new CapCanvas(105,30);

Ao lado deste canvas deve ser colocada uma caixa de texto. Mais tarde, para verificar se a caixa tem o mesmo texto que o captcha, basta chamar a função keyCheck().

Ficheiro: captcha.html

<!DOCTYPE html>
<html>
<head>
<title>Captcha</title>
<meta charset="iso-8859-1">
<script type="text/javascript">
function ver() {
	var cap = document.getElementById("tcap").value;
	if(!capCanvas.keyCheck(cap)) {
		window.alert(
			"You must enter the 5 letters/digits. " + 
			"If you can't read the letters, please click on the image to get another one."
		);
	} else {
		window.alert("OK");
	}
}
</script>

</head>
<body>
<h3>Captcha - exemplo de utilização</h3>
<form>
<script type="text/javascript" src="CapCanvas.js"></script>
<input type="text" size="8" id="tcap" />
<input type="button" value="Verificar" onclick="ver();" />
</form>
</body>
</html>

Objetivos deste sítio

Estruturas e procedimentos mais importantes do javascript. Exemplos de utilização.

Conceitos básicos de programação
Eventos de sistema e eventos de rato
Variáveis: tipos, declaração, locais e globais
Constantes: Numéricas, booleanas, de string
Expressões e operadores
Estruturas de controlo: decisão e iteração
Vetores
Funções
Cookies
Classes e objetos: propriedades e métodos
Ajax
jQuery