terça-feira, 11 de dezembro de 2012

HTML5: Criando Elementos Clicáveis no Canvas

Uma das grandes problemas de quem está começando a fazer jogos no HTML5. Para fins de navegador, Canvas é como uma imagem qualquer, e qualquer coisa que é desenhada nessa imagem, vira parte da mesma. Agora, a grande pergunta: como é que vou clicar naquele botão que coloquei no Canvas, se ele é apenas um monte de pixels?

Aí entra a importância de criarmos objetos para descrever o que queremos. Vamos supor que queremos um botão retangular. Para isso, vamos criar uma classe para descrever esse botão:

function Botao(x,y,w,h){
   this.x = x;
   this.y = y;
   this.w = w;
   this.h = h;
}


O botão vai estar localizado em uma posição (x,y) do Canvas e possui w de largura e h de altura. Note que só com essas informações, posso utilizar o comando para preencher um retângulo com o fillRect. Pois bem, vamos fazer isso, vamos instanciar um objeto botão e pintá-lo, supondo que já pegamos a referência para Canvas e o contexto da Canvas:

var bt = new Botao(20,20,50,50);
ctx.fillRect(bt.x,bt.y,bt.w,bt.h);

Aqui ele pintou o "botão" no Canvas, mas e agora, como vou fazer esse botão ser clicável? Para isso, vamos configurar um evento, neste caso, vou usar o evento "onClick" que vamos configurar na Canvas.

canvas.onclick = function (evt){

}

Qualquer comando que colocarmos aqui vai ser executado quando dermos um click em cima da Canvas. Ou seja, toda a canvas é clicável. Mas temos que filtrar para que ele execute somente quando clicamos no botão, ou melhor, na sua área. Para isso, pegaremos a posição do Mouse e analisaremos se ele está ou não na mesma região do botão. Lembrando que a posição do mouse que o evento retorna, é a posição em relação a área do navegador, enquanto o do botão é a posição em relação ao Canvas, por isso temos que calcular a posição do Mouse na canvas antes:

canvas.onclick = function(evt){
    var rectNav = canvas.getBoundingClientRect();
    var pos = {
        x: evt.clientX - rectNav.left,
        y: evt.clientY - rectNav.top
     };
    if(pos.x>bt.x && pos.x<(bt.x+bt.w) && pos.y>bt.y && pos.y<(bt.y+bt.h){
        alert("Clicado");
    }
}

Para verificar a posição, é apenas verificar se a posição do mouse está entre a posição inicial do botão e a posição final, tanto no eixo x quanto no eixo y. E agora, o botão está operacional. Existem outros eventos que podem melhorar o botão, por exemplo, onMouseOver, que permite verificar se o botão está sobre a canvas (e consequentemente, sobre o botão), entre outros, nas quais falarei em algum outro post.

4 comentários:

  1. Rapaz, se eu te falar que este é o décimo site que eu tô lendo sem encontrar a resposta! Valeu pela dica!

    ResponderExcluir
  2. Como posso aplicar nesse projeto, desenhei dois botões em formas primitivas?
    gostaria de colocar neles um evento listener para click e executar uma animação.

    http://pt.stackoverflow.com/questions/35527/como-colocar-um-evento-de-click-em-uma-forma-primitiva-desenhada

    ResponderExcluir
  3. Eu gostaria de saber como desenhar uma forma complexa e torna-la clicável. Alguém pode me ajudar?

    ResponderExcluir
  4. Este comentário foi removido pelo autor.

    ResponderExcluir