Neste artigo veremos um recurso muito interessante e útil do HTML5, o Canvas. Este veio para substituir tecnologias ultrapassadas de desenho em “2d” e “3d”. Quando usado de forma correta ele tornar-se uma poderosa ferramenta de modelagem geométrica no plano. Existem diversos exemplos na Web que ilustram projetos gráficos incríveis realizados com o componente Canvas, incluindo até jogos.

Tais projeções geométricas exigem um bom embasamento matemático e físico, e quanto melhor suas habilidades matemáticas e físicas, com certeza melhor serão seus projetos. Você verá com muita frequência cálculos como: distância entre pontos, verificar se o ponto está dentro do polígono (convexo e não convexo), eixos cartesianos no plano 2D e 3D, intercessão entre pontos de duas figuras geométricas e assim por diante. Óbvio que o foco deste artigo não é ensinar matemática e nem física, pois estamos partindo do princípio que você já tem conhecimentos suficientes sobre essas áreas, já que são pré-requisitos.

O Canvas em HTML na verdade é apenas um container sem muitos atributos ou especificidades. Toda lógica é programada através de um linguagem de script, que geralmente é o JavaScript. Veremos nos próximos tópicos exemplos práticos e conceitos de como tornar o nosso canvas um objeto geométrico complexo e com muitas utilidades.

Usando Canvas com JavaScript

Como dissemos, o Canvas precisa de uma linguagem de script para ser implementado, e por opção escolhemos o JavaScript, que é a mais comumente usada no mercado. Mas antes de tudo vamos começar criando nossa página HTML com o container canvas. Veja a Listagem 1.

Listagem 1. Página HTML com Canvas


  <html>
    <head>
   
      <script type="text/javascript" src="mycanvas.js"></script>
   
    </head>
    <body>
   
     <canvas id="canvasQuadrado">
     
     </canvas>
   
    </body>
  </html>

A nossa página é bem simples, possui toda a estrutura comum do HTML (head, body), mais uma tag script inserindo nosso “mycanvas.js” (que terá todo código do nosso canvas), e por fim a tag “canvas” que irá armazenar nosso objeto desenhado.

Vamos agora ver o nosso arquivo mycanvas.js e verificar como fazemos para capturar esse container e utilizar no JavaScript. Todo código esta comentado para facilitar o entendimento do mesmo, conforme a Listagem 2.

Listagem 2. Usando o 'canvasQuadrado' no mycanvas.js


   
  /*
   * A cada refresh (F5) da página, o método "montarFigura()"
   * é executado.
   * */
  window.onload=function(){ 
         montarFigura();
  };
   
  function montarFigura() {
   
             /*
              * Capturamos o objeto/container canvas através do seu ID.
              * Você também pode optar por utilizar jQuery, a lógica é a mesma, só
              * muda a sintaxe.
              * */
               canvas = document.getElementById("canvasQuadrado");
               
               /*
                * Aqui é onde toda a 'mágica', começa a ocorrer. Iremos usar o método
                * "getContext('2d')" que irá "converter" nosso simples 
                 * container em um objeto 2D onde
                * poderemos trabalhar com diversos métodos que veremos mais adiante.
                * */
               ctx = canvas.getContext('2d');
               console.log("Capturando canvasQuadrado em formato 2D");
         
  }

Até agora não temos nada sendo mostrado na tela, pois ainda não começamos a projetar nossa figura geométrica, apenas preparamos o ambiente com o contexto 2D do canvas. Vamos começar desenhando um simples retângulo com a cor de fundo preta, conforme a Listagem 3.

Listagem 3. Desenhando retângulo com fundo preto


   
  window.onload=function(){ 
         montarFigura();
  };
   
  function montarFigura() {
   
             
               canvas = document.getElementById("canvasQuadrado");
               
               console.log("Capturando canvasQuadrado em formato 2D");
               ctx = canvas.getContext('2d');
               
               console.log("Colorindo canvas no plano x,y");
               
               //setamos a cor como preta para depois criar o retangulo
               ctx.fillStyle="black";
               
               //criamos o retangulo no plano passando os 4 vertices que o mesmo possui
               ctx.fillRect(0,0,150,75);
               
         
  }

Vamos melhorar nossa lógica, fazendo o mesmo retângulo, porém quando o usuário clicar dentro da área do retângulo nós iremos colorir o mesmo com outra cor e mostrar qual a coordenada do ponteiro do mouse através do console. Analise o código da Listagem 4.

Listagem 4. Colorindo retângulo onclick


  window.onload = function() {
         montarFigura();
  };
   
  function montarFigura() {
   
         canvas = document.getElementById("canvasQuadrado");
         
         /*
          * Adicionamos um listener ao canvas, assim toda vez que
          * ao clicar no canvas este método será chamado.
          * */
         canvas.addEventListener('click', function(e) {
               
               var rect = this.getBoundingClientRect();
               
               //Criamos uma estrutura contendo as coordenadas atuais do mouse
               var coords = {
                      x : e.clientX - rect.left,
                      y : e.clientY - rect.top
               };
               console.log("Coordenada Atual: " + coords.x + ", " + coords.y);
               
               //Capturamos o contexto 2d do canvas
               ctx = this.getContext('2d');
               
               //Preenchemos a cor em hexadecimal
               ctx.fillStyle = "#FFDEAD";
               
               //Criamos o retangulo na tela
               ctx.fillRect(0, 0, 150, 75);
         }, false);
   
         console.log("Capturando canvasQuadrado em formato 2D");
         ctx = canvas.getContext('2d');
   
         console.log("Colorindo canvas no plano x,y");
   
         // setamos a cor como preta para depois criar o retangulo
         ctx.fillStyle = "black";
   
         // criamos o retangulo no plano passando os 4 vertices que o mesmo possui
         ctx.fillRect(0, 0, 150, 75);
   
  }

O exemplo acima funciona perfeitamente, mas tem um bug que deixamos passar despercebido. O canvas é delimitado pela área da tag canvas no HTML e não no JavaScript. Isso significa que mesmo que você clique fora do retângulo desenhado na tela (em suas proximidades) o evento onclick ainda será chamado, pois você de fato está clicando no canvas. Sendo assim, você além de adicionar esse evento de onclick do mouse no canvas, você também deverá verificar se o ponto x,y do mouse está dentro do retângulo, assim você garantirá que se o usuário clicar fora do retângulo, mesmo que dentro do canvas, nenhuma ação será feita.

Em outras palavras, o seu canvas pode ter dimensão 500x500, mas o seu retângulo tem apenas 50x50. Nesse caso, se o usuário clicar em qualquer ponto dentro da dimensão 500x500 a ação será disparada, mas não é isso que queremos. O importante é definir se o ponto está dentro da dimensão 50x50, ou seja, no retângulo. Vejamos a Listagem 5.

Listagem 5. Checando se ponto está dentro do retângulo


  window.onload = function() {
         montarFigura();
  };
   
  function montarFigura() {
   
         canvas = document.getElementById("canvasQuadrado");
   
         canvas
           .addEventListener(
            'click',
           function(e) {
           var rect = this.getBoundingClientRect();
                                    
           var coords = {
            x : e.clientX - rect.left,
            y : e.clientY - rect.top
           };
           console.log("Coordenada Atual: " + coords.x + ", "
            + coords.y);
                      
           /*
            * Essa função nos garante que apenas se o usuário clicar dentro do
            * retângulo, a cor será alterada
            * */
            if (isPontoInRec(coords.x, coords.y)) {
               console.log("Você clicou dentro do retângulo. Iniciando mudança de cores...");
                // Capturamos o contexto 2d do canvas
               ctx = this.getContext('2d');
               // Preenchemos a cor em hexadecimal
               ctx.fillStyle = "#FFDEAD";
               // Criamos o retangulo na tela
               ctx.fillRect(0, 0, 150, 75);
   
           }
          }, false);
   
         console.log("Capturando canvasQuadrado em formato 2D");
         ctx = canvas.getContext('2d');
   
         console.log("Colorindo canvas no plano x,y");
   
         ctx.fillStyle = "black";
   
         ctx.fillRect(0, 0, 150, 75);
   
  }
   
  /*
   * Está função verifica se o ponto x,y está dentro do retângulo
   * */
  function isPontoInRec(x, y) {
      var rectDimensions = [0,0,150,75];
         var click_x = x;
         var click_y = y;
   
         if (click_x >= rectDimensions[0] && click_x 
          <= rectDimensions[0] + rectDimensions[2]
           && click_y >= rectDimensions[1] && click_y 
           <= rectDimensions[1] + rectDimensions[3]) {
               return true;
         }
   
         return false;
  }

O ponto chave no exemplo acima é a função “isPontoInRec()” que irá checar se o ponto x,y está dentro do retângulo. Aqui aplica-se trigonometria básica para calcular um ponto dentro de um retângulo, retornando true caso o ponto esteja contido ou false caso não esteja contido.

Então agora temos um exemplo completo de um retângulo que mudará de cor quando o usuário clicar neste. Perceba que em todo nosso artigo o “canvas” serviu apenas de container: todo trabalho foi feito em cima de objetos 2D que são desenhados em nosso canvas. Além de retângulos você pode desenhar círculos, retas, quadrados ou objetos mais complexos como polígonos. A lógica para uso de outros objetos é quase a mesma, mudando apenas a quantidade de pontos para criação do mesmo. Por exemplo, o polígono pode ter infinitos pontos, enquanto que o quadrado só pode ter quatro, o triângulo três, e assim por diante.

Trabalhar com polígonos complexos, calculando pontos, área e distâncias não é uma tarefa nada trivial, mas muito interessante e útil. O maior problema com certeza não é a sintaxe da linguagem ou como aplicar determinadas funções, mas sim a física e a matemática envolvida em todo processo, que podem envolver desde funções simples e complexas que envolvem gravidade, elasticidade de materiais e entre outros assuntos pertinentes.

Todos os exemplos deste artigo foram construídos utilizando a IDE Eclipse para facilitar a indentação e legibilidade do código.