Imparate a creare grafica Web con canvas in un'ora!


Prima di cominciare una breve precisazione. Canvas e' un'aggiunta relativamente recente a Javascript che ormai e' supportata da tutte le ultime versioni dei principali browsers. Canvas indica sia un nuovo elemento HTML che un'API per il disegno 2d all'interno della finestra creata dall'elemento. Tempo fa avevo scritto una guida simile che usava SVG. I miglioramenti di canvas permettono adesso di avere un valido tool che si aggiunge e in alcuni casi puo' sostituire per la grafica via Web sia SVG che flash e gli applet Java. Inoltre il suo uso e' relativamente semplice. Ma tenete conto che si tratta di programmare in Javascript! Se non conoscete Javascript o addirittura la programmazione in un qualsiasi linguaggio, allora non basterebbe un anno per imparare. Se poi voi siete gia' programmatori esperti di altri linguaggi allora solo guardando le figure imparerete a programmare usando Canvas in un'ora. Per ogni immagine e' riportato il programma completo che potete salvare su disco, provarlo cosi com'e' e modificarlo a piacere. Per fare questo si consiglia di eseguire prima il programma e poi selezionare "File/Salva pagina con nome" scegliendo come formato "pagina web completa" : in questo modo saranno copiati automaticamente eventuali file aggiuntivi richiesti dal programma canvas.

Nei primi esempi per semplicita' uso solo Javascript. Ma ormai e' risaputo che il trattamento in maniera semplice ed efficace dell'interattivita' richiede l'uso di una particolare libreria (o API) jQuery. Questa viene introdotta poco a poco negli ultimi esempi.


Il nostro primo disegno : un rettangolo esegui il programma canvas

<html>
  <head>
    <title>Canvas tutorial</title>
    <script type="text/javascript">
      function disegna(){
        var canvas = document.getElementById('esempio');
        if (canvas.getContext){
          var cg = canvas.getContext('2d');
          cg.fillStyle='rgb(255,255,0)';
          cg.fillRect(25,25,100,100);
          cg.clearRect(45,45,60,60);
          cg.strokeStyle='red'; 
          cg.strokeRect(50,50,50,50);
             
        }
      }
    </script>
    <style type="text/css">
      canvas { border: 1px solid black; }
    </style>
  </head>
  <body onload="disegna();">
    <canvas id="esempio" width="150" height="150"></canvas>
  </body>
</html>
A differenza di SVG il rettangolo e' l'unica forma che puo' essere disegnata con un'apposita istruzione. Per ogni altra forma bisogna usare il cosiddetto path che permette di generare forme qualsiasi in maniera molto compatta.Un path (cammino in inglese) e' generato da una serie di punti collegati da segmenti di retta o anche da curve.
Il primo path: un cerchio esegui il programma canvas
  <head>
    <title>Canvas tutorial</title>
    <script type="text/javascript">
      function disegna(){
        var canvas = document.getElementById('esempio');
        if (canvas.getContext){
          var cg = canvas.getContext('2d');
          cg.beginPath();
          cg.arc(75,75,50,0,Math.PI*2,true);
          cg.moveTo(115,75); 
          cg.arc(75,75,40,0,Math.PI*2,false);
          cg.strokeStyle='red';
          cg.lineWidth=3;
          cg.stroke(); 
          cg.closePath();
          cg.beginPath();
          cg.arc(75,75,30,0,Math.PI*2,true);
          cg.fillStyle='rgb(255,255,0)';
          cg.fill();

        }
      }
    </script>
    <style type="text/css">
      canvas { border: 1px solid black; }
    </style>
  </head>
  <body onload="disegna();">
    <canvas id="esempio" width="150" height="150"></canvas>
  </body>
</html>

Ora coloriamo un quadrato con un gradiente e ridisegniamolo molte volte ruotato in modo da formare una spirale esegui il programma canvas
<html>
  <head>
    <title>Canvas tutorial</title>
    <script type="text/javascript">
      function disegna(){
        var canvas = document.getElementById('esempio');
        if (canvas.getContext){
          var cg = canvas.getContext('2d'); 
          var cw = 200;
          gradiente = cg.createLinearGradient(0,0,cw,cw);
          gradiente.addColorStop(0,'yellow');
          gradiente.addColorStop(1,'magenta');
          cg.fillStyle= gradiente;
          cg.fillRect(0,0,cw,cw);
          cg.strokeStyle = "black";
          cg.strokeRect(0,0,cw,cw);
          var sf=1;    
          for (var i=0;i<10;i++){
            cg.translate(cw/2,cw/2);
            cg.rotate(Math.PI/180*5*(i+1));
            sf = sf*0.95;
            cg.scale(sf,sf);
            cg.translate(-cw/2,-cw/2);
            cg.fillRect(0,0,cw,cw);
            cg.strokeRect(0,0,cw,cw);
          }


        }
      }
    </script>
    <style type="text/css">
      canvas { border: 1px solid black; }
    </style>
  </head>
  <body onload="disegna();">
    <canvas id="esempio" width="200" height="200"></canvas>
  </body>
</html>


Animazioni, testi, immagini fai partire il programma canvas
<html>
  <head>
    <title>Canvas tutorial</title>
    <script type="text/javascript">
      var cw;
      var cg;
      var i ;
      var im1;
      var vis; 
      var posy=50;
      function init(){
        im1 = new Image();
        im1.src="srunning.gif";
        var canvas = document.getElementById('esempio');
        if (canvas.getContext){
          cg = canvas.getContext('2d');
          cw = 400;
          vis = 0.5;
          cg.fillStyle= "rgba(0,100,100,"+vis+")";
          cg.fillRect(0,0,cw,cw);
          cg.font='40pt Arial Bold';
          cg.textAlign='left';
          cg.strokeText('Ciao a tutti',50,posy);
          cg.drawImage(im1,50,100,100,100); 
          cg.save(); 
          i=0;  
                     }
               }
  function ruota()
  {         
            cg.restore();
            cg.translate(100,150);
            cg.rotate(-Math.PI/180*5*(i));
            cg.translate(-100,-150);
            cg.clearRect(0,0,cw,cw);
            vis = vis+.01; if(vis>1.)vis=0.;
            cg.fillStyle= "rgba(0,100,100,"+vis+")";            
            cg.fillRect(0,0,cw,cw);
            posy=posy+2;if(posy>cw-50)posy=50;
            cg.strokeText('Ciao a tutti',50,posy);
            cg.translate(100,150);
            cg.rotate(Math.PI/180*5*(i+1));
            cg.translate(-100,-150);
            cg.drawImage(im1,50,100,100,100); 
            i++;
            T=setTimeout("ruota()", 50)
            
                         
    }
 function resetta()
  {
           cg.restore();
           cg.translate(100,150);
           cg.rotate(-Math.PI/180*5*(i));
           cg.translate(-100,-150);
           cg.clearRect(0,0,cw,cw);
           vis=0.5;
           i=0;
           posy = 50; 
           clearTimeout(T);
}
       </script>
    <style type="text/css">
      canvas { border: 1px solid black; }
    </style>
  </head>
  <body onload="init();">
  <input value="START" type="button" onClick="ruota()">
<input value="STOP" type="button" onClick="clearTimeout(T)">
<INPUT onClick="resetta()" type="button" value=RESET>

<canvas id="esempio" width="400" height="400"></canvas> </body> </html>


Generazione di un'immagine a caso esegui programma canvas

<html>
  <head>
    <title>Canvas tutorial</title>
    <script type="text/javascript">

      function disegna(){
        var canvas = document.getElementById('esempio');
        if (canvas.getContext){
          var max = 1000;
          var redVal=0;
          var greenVal=0;
          var blueVal=0;
          var prevx = 512.;
          var prevy = 512.;
          var x = 0.;
          var y = 0.;
          var dis = 10;
          var an = 0;
          var c1 = Math.random()*1000;
          var inter = 5;
          cg = canvas.getContext('2d');
          cw = 1024;
          cg.fillStyle= 'rgba(0,100,100,0.5)';
          cg.fillRect(0,0,cw,cw);
          cg.beginPath();
          cg.moveTo(512,512); 
          for (var i=0; i<=max; i++)
                 {
            x = prevx + dis * Math.sin(an);
            y = prevy + dis * Math.cos(an); 
            if(x > 1024) break;
            if(x < 1) break;
            if(y > 1024) break;
            if(y < 1) break;
            x1 = Math.round(x);
            y1 = Math.round(y);
            cg.lineTo(x1,y1);
            prevx = x;
            prevy = y;
            dis = dis + inter;
            an = an + c1;
                   }
          redVal = Math.round(Math.random()*255);
          greenVal = Math.round(Math.random()*255);
          blueVal = Math.round(Math.random()*255);
          cg.fillStyle ="rgb(" + redVal + "," + greenVal + "," + blueVal + ")";
          redVal = Math.round(Math.random()*255);
          greenVal = Math.round(Math.random()*255);
          blueVal = Math.round(Math.random()*255);
          cg.strokeStyle="rgb(" + redVal + "," + greenVal + "," + blueVal + ")";
          cg.fill();  
          cg.stroke();
             }
}
       </script>
    <style type="text/css">
      canvas { border: 1px solid black; }
    </style>
  </head>
  <body onload="disegna();">
<canvas id="esempio" width="1024" height="1024"></canvas>
  </body>
</html>



Il primo programma(del rettangolo) riscritto in modo da usare jQuery esegui il programma canvas

<html>
  <head>
    <title>Canvas tutorial</title>
      <script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>  
    <script type="text/javascript">
          $(document).ready(function(){
          var canvas = document.getElementById('esempio');
          var cg = canvas.getContext('2d');
          cg.fillStyle='rgb(255,255,0)';
          cg.fillRect(25,25,100,100);
          cg.clearRect(45,45,60,60);
          cg.strokeStyle='red'; 
          cg.strokeRect(50,50,50,50);
       })
    </script>
    <style type="text/css">
      canvas { border: 1px solid black; }
    </style>
  </head>
  <body>
    <canvas id="esempio" width="150" height="150"></canvas>
  </body>
</html>

Ora proviamo a riscrivere la pagina con l'animazione in jQuery esegui la pagina con canvas

<html>
  <head>
    <title>Canvas tutorial</title>
    <script src="jquery-1.js"></script>  
    <script type="text/javascript">
      var cw;
      var cg;
      var i ;
      var im1;
      var vis; 
      var posy=50;
      im1 = new Image();
      im1.src="srunning.gif";
      function init(){
          cg = $('#esempio')[0].getContext("2d");
          cw = 400; 
          vis = 0.5;
          cg.fillStyle= "rgba(0,100,100,"+vis+")";
          cg.fillRect(0,0,cw,cw);
          cg.font='40pt Arial Bold';
          cg.textAlign='left';
          cg.strokeText('Ciao a tutti',50,posy);
          cg.save(); 
          i=0;  
               }
          
  function ruota()
  {         
            cg.restore();
            cg.translate(100,150);
            cg.rotate(-Math.PI/180*5*(i));
            cg.translate(-100,-150);
            cg.clearRect(0,0,cw,cw);
            vis = vis+.01; if(vis>1.)vis=0.;
            cg.fillStyle= "rgba(0,100,100,"+vis+")";            
            cg.fillRect(0,0,cw,cw);
            posy=posy+2;if(posy>cw-50)posy=50;
            cg.strokeText('Ciao a tutti',50,posy);
            cg.translate(100,150);
            cg.rotate(Math.PI/180*5*(i+1));
            cg.translate(-100,-150);
            cg.drawImage(im1,50,100,100,100); 
            i++;
            T=setTimeout("ruota()", 50);
            
                         
    }
 function resetta()
  {
 cg.restore();
 cg.translate(100,150);
 cg.rotate(-Math.PI/180*5*(i));
 cg.translate(-100,-150);
 cg.clearRect(0,0,cw,cw);
  vis=0.5;
  i=0;
  posy = 50; 
  clearTimeout(T);
}
 $(document).ready(function(){
      $("#start").click(function(){
        ruota();
    });    
      $("#stop").click(function(){
        clearTimeout(T)
    }); 
     $("#reset").click(function(){
       resetta();
    });
    $(im1).load(function(){
    cg.drawImage(im1,50,100,100,100); 
    });
     init();
     })
       </script>
    <style type="text/css">
      canvas { border: 1px solid black; }
    </style>
  </head>
  <body>
 <input value="START" type="button" id="start">
 <input value="STOP" type="button" id="stop" >
 <input type="button" id="reset" value=RESET>

<canvas id="esempio" width="400" height="400"></canvas> </body> </html>


Create un "biliardo" quadrato con una palla che rimbalza in continuazione esegui programma canvas
<html>
  <head>
    <title>Canvas tutorial</title>
      <script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>  
    <script type="text/javascript">
    var x = 150;
    var y = 150;
    var dx=2;
    var dy=4;
    var r = 10;
    var larghezza;
    var lunghezza;
    var cg;
    function init() {
     cg = $('#esempio')[0].getContext("2d");
     larghezza = $('#esempio').width();
     lunghezza = $('#esempio').height();
     return setInterval(disegna, 10);
     }
     function disegna() {
      cg.clearRect(0,0,larghezza,lunghezza);
      cg.beginPath();
      cg.arc(x, y, r, 0, Math.PI*2, true); 
      cg.closePath();
      cg.fill();
      if(x+dx > larghezza || x+dx < 0) dx = -dx;
      if(y+dy > lunghezza || y+dy < 0) dy = -dy;
      x += dx;
      y += dy;
     }
    $(document).ready(function(){
            init(); 
     })
    </script>
    <style type="text/css">
      canvas { border: 1px solid black; }
    </style>
  </head>
  <body>
    <canvas id="esempio" width="150" height="150"></canvas>
  </body>
</html>

Simulazione dell'esperimento di caduta simultaneo esegui programma canvas
<html>
  <head>
<title>Canvas tutorial</title>
<style type="text/css">
      canvas {  background: rgb(220,220,220) }
</style>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>  
<script type="text/javascript">
var dis
var i=0
var y= new Array()
var x= new Array()
var vx = 10

function pallino(x,y,color){
dis.strokeStyle = color
dis.fillStyle = color
dis.beginPath()
dis.arc(x, y, 10, 0, Math.PI*2,true)
dis.closePath()
dis.stroke()
dis.fill()
}

function barretta(x,y,color){
dis.strokeStyle = color
dis.beginPath()
dis.moveTo(x,y)
dis.lineTo(x+20,y)
dis.stroke()
}

function draw() 
{ 
 if(i==10) return

y[i]=30+(10*Math.pow(i,2))/2
x[i]=200+i*vx
 
dis.clearRect(21,0,758,444)
pallino(100,y[i],"red");
pallino(x[i], y[i],"green")

barretta(0,y[i],"red")
barretta(780,y[i],"green")

if(i>0){
dis.beginPath()
dis.strokeStyle = "red"
dis.moveTo(100,y[0])
for (tq = 1; tq < i+1; tq=tq+1) {
dis.lineTo(100,y[tq])
}
dis.stroke()

dis.beginPath()
dis.strokeStyle = "green"
dis.moveTo(200,y[0])
for (tq = 1; tq < i+1; tq=tq+1) {
dis.lineTo(x[tq],y[tq])
}
dis.stroke()
}
i++

T=setTimeout("draw()", 500)
}

function disegno()
{
dis = $('#prova')[0].getContext("2d");
dis.strokeStyle = "rgb(200,0,0)"

pallino(100,30,"red");
pallino(200,30,"green")

dis.strokeStyle = "rgb(0,0,200)"
dis.beginPath()
dis.moveTo(0,445)
dis.lineTo(800,445)
dis.closePath()
dis.stroke()
}

function resetta()
  {
 dis.clearRect(0,0,800,444)
  i=0
pallino(100,30,"red");
pallino(200,30,"green")

  clearTimeout(T)
}

 $(document).ready(function(){
      $("#start").click(function(){
        draw();
    });    
      $("#stop").click(function(){
        clearTimeout(T)
    }); 
     $("#reset").click(function(){
       resetta();
    }); 
            disegno(); 
     })

    </script>
    <style type="text/css">
      canvas { border: 1px solid black; }
    </style>
  </head>
  <body>
 <input value="START" type="button" id="start">
 <input value="STOP" type="button" id="stop" >
 <input type="button" id="reset" value=RESET>
<p>
<canvas id="prova" width="800" height="500">
  </body>
</html>

Bibliografia
  1. Canvas tutorial che usa "breakout" uno dei primi videogame
  2. mozilla (firefox) canvas tutorial
  3. HTML5 canvas cheat sheet (foglio riassuntivo)
  4. HTML5 tutorial (include anche Canvas)

INDIETRO a Materiale dei corsi HTML e Java
Maintained by : info@zitogiuseppe.com Last modified: