mercoledì 25 marzo 2009

Super javascript

In questi giorni ho scoperto una evoluzione, per me nuova, di html e javascript che la dice lunga sulla direzione che sta prendendo questa tecnologia: da semplice sistema per la creazione di ipertesti si sta trasformando sempre più in una vera e propria "piattaforma" per la programmazione di applicazioni che non hanno nulla da invidiare a quelle "classiche" che abbiamo installato sul pc. In particolare ho scoperto che le ultime specifiche dell'HTML5 prevedono la gestione diretta della grafica mediante javascript: in parole semplici è possibile avere una "tela" su cui disegnare quello che si vuole. Il tutto dipende dall'introduzione del tag <canvas> (che significa appunto "tela") e di alcune funzioni javascript per disegnare linee, rettangoli, cerchi, ... ma anche immagini nei formati supportati dal browser. Il tag è supportato, per ora, solo dalle più recenti versioni di Firefox, Safari, Opera e, ovviamente, Chrome. Internet Explorer, anche nella versione 8 (che è uscita recentemente in beta) non lo supporta.

Il funzionamento è procedurale, non dichiarativo; in pratica il disegno viene costruito "dicendo" al browser come deve procedere per farlo: "sposta la matita qui", "traccia una linea da qui a là", "cambia il colore della matita", "fai un cerchio", "riempi il cerchio di colore", ... Non voglio entrare in discussioni (filosofiche) sul fatto se sia meglio un approccio dichiarativo o procedurale ma voglio fare subito alcuni semplici esempi per capire.

Per iniziare c'è bisogno di una semplicissima pagina html con un tag <canvas> al quale associamo un attributo "id" per poterlo identificare semplicemente. Inserirò poi nella pagina una funzione javascript disegna() che viene eseguita al caricamento della pagina stessa (onload) e "disegnerà" nel canvas. Questo è il codice di base della pagina:

<html> <head> <title>Test canvas tag</title> <style type="text/css"> #mycanvas {border-style:solid; border-width:1px; border-color:black;} </style> <script> function disegna() { //Qui inseriremo le istruzioni per fare il disegno } </script> </head> <body onload="disegna();"> <canvas id="mycanvas" width="200" height="200"> Tag &lt;canvas&gt; non supportato da questo browser </canvas> </body> </html>

Notare che qualsiasi contenuto del tag <canvas> non verrà visualizzato se il browser lo supporta: scrivere al suo interno è quindi un ottimo sistema per informare l'utente che sta usando un browser a cui manca questa funzionalità.

Faccio qualche prova di codice javascript nella funzione disegna().

Prima di tutto occorre ottenere l'oggetto che permette di disegnare e metterlo in una variabile:


var foglio = document.getElementById('mycanvas').getContext('2d')


Notare che il metodo getContext() per ora supporta solo il tipo '2d' (disegno bidimensionale) ma in futuro potrebbe anche supportare grafica in uno spazio tridimensionale (3d).

La tela è come un piano cartesiano con le coordinate che hanno origine nell'angolo in alto a sinistra, quindi il punto (0,0) sarà l'angolo in alto a sinistra, il punto (200,200), nel caso di esempio, sarà invece l'angolo in basso a destra.

la funzione moveTo permette di spostare la "matita" senza disegnare

foglio.moveTo(0,150)

La funzione lineTo disegna una linea retta fino al punto indicato

foglio.lineTo(200,150)

La funzione stroke() visualizza le linee fatte

foglio.stroke()

Cambio il colore della matita, ne prendo una rossa:

foglio.strokeStyle = 'red'

Inizio una linea (spezzata)

foglio.beginPath()

Mi sposto (senza disegnare)

foglio.moveTo(50,50)

Faccio due linee...

foglio.lineTo(150,50) foglio.lineTo(100,0)

E "chiudo" la linea spezzata sul punto di partenza:

foglio.closePath() foglio.stroke()

Riprendo la matita nera:

foglio.strokeStyle = 'black'

Disegno un rettangolo (i primi due parametri indicano il punto di partenza (angolo in alto a sinistra) e gli altri due indicano rispettivamente la larghezza e l'altezza del rettangolo

foglio.strokeRect(50,50,100,100)

Imposto il colore per lo riempimento delle figure:

foglio.fillStyle = 'brown'

Disegno un rettangolo colorato:

foglio.fillRect(100,120,20,30)

Il risultato, mettendo tutto insieme, è in questa pagina (visualizzate l'HTML per vedere com'è). Vi sembra banale? Allora guardate questo esempio fatto sfruttando (anche) l'elemento canvas: http://www.chromeexperiments.com/hosted/gravity/index.html

oppure quest'altro:

http://deanm.github.com/pre3d/monster.html