Categorie
Javascript Programmazione

{JS} API Image: Le immagini SVG, Canvas e la manipolazione

Cosa sono le immagini SVG?

Le immagini SVG (Scalar Vector Graphics) sono un particolare formato, basato sul linguaggio XML, che è in grado di visualizzare oggetti di grafica vettoriale e quindi di salvare immagini in modo che siano ingrandibili e rimpicciolibili a piacere senza perdere in risoluzione grafica.
Rappresentano un approccio alternativo che ci consente di colmare i limiti delle classiche immagini raster.
SVG è uno standard W3C che definisce un linguaggio di markup per la creazione di grafica bidimensionale.

<svg>
	<circle id="cerchio" cx="100" cy="100" r="50" style="stroke: #000000; fill: #00ff00;" />
</svg>

Creare ed aprire un file SVG

È possibile aprire un file SVG con qualsiasi sistema operativo. Proprio per la sua natura, essendo basato sul linguaggio XML, un file SVG può essere aperto con qualsiasi editor di testo o software di disegno. Per visualizzarlo semplicemente va benissimo anche il browser web a noi più congeniale.

Se si desidera creare un file SVG, uno dei metodi più efficienti è utilizzare Adobe Illustrator o programmi similari (es. GIMP)

 I file SVG sono ideali per immagini che devono essere scalate e devono mantenere sempre la stessa qualità es. logo aziendale, marchi e icone dell’interfaccia grafica delle nostre app/sito.

Struttura di immagine SVG

Seppur difficilmente ci occuperemo di scrivere a mano un immagine SVG, è importante conoscere come essi sono strutturati.

Le immagini SVG è un formato basato su XML e di fatto hanno un proprio DOM.
I nodi dell’albero descrivono oggetti geometrici o trasformazioni; possono essere renderizzati dai principali browsers, e adottano i principali standard del web (XML, CSS).
Un immagine SVG è costituita da più nodi, tags, attributi ed eventualmente contenuti; questo consente di manipolarli mediante il linguaggio di programmazione Javascript.
Si potrà quindi creare animazioni e disegni interattivi.

<?xml version="1.0" encoding="iso-8859-1" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//Dtd SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/Dtd/svg11.dtd">
<svg width="300" height="200"
     version="1.1" xmlns="http://www.w3.org/2000/svg">
	<text x="10" y="100"
	      style="fill:red;font-family:times;font-size:18">
	Primo esempio di SVG
	</text>
</svg>

Nella prima riga troviamo l’istruzione che dichiara che il file in questione è un file XML conforme alla versione 1.0.
Nella seconda riga troviamo la dichiarazione del tipo di documento con la quale informiamo il programma che si occuperà di visualizzare (es. browser) che la nostra immagine, che il file SVG, è stato scritto seguendo le regole W3C indicate nella versione 1.1 del linguaggio.
Nella terza riga troviamo la dichiarazione dell’elemento principale di un file SVG.
Similare al tag <html> di una pagina web, il tag <svg> (detto elemento root (radice) del documento), contiene tutti gli tutti gli elementi grafici della nosta immagine.

Gli attributi di <svg> width ed height indicano quella che sarà la dimensione dell’immagine, l’attributo version indica la versione di SVG che si sta utilizzando ed in fine l’attributo xmlns serve ad indicare il namespace a cui fanno riferimento i tag del file SVG. 

Nella quarta riga troviamo la dichiarazione dell’ elemento grafico <text> che contiene la nostra immagine.

Gli attributi di text x e y indicano dove l’elemento sarà posizionato lungo i rispettivi assi rispetto all’immagine <svg>; l’attributo stile contiene invece le regole css che determino l’aspetto dell’elemento.

Gli elementi compongono un immagine SVG assumono dei precisi nomi:

SVG Canvas (tela SVG)Indica tutto l’insieme degli elementi che compongono un immagine SVG
 SVG ViewportE’ l’area di disegno definita all’interno del tag <svg> mediante gli attributi height e width; unità di misura ammesse: em, ex, px, pt, pc, cm, mm e %
SVG viewBoxl’attributo viewBox applicabile a <svg> modifica il sistema di riferimento interno; <svg ... viewBox="0 0 1000 500">indica gli estremi superiori ed inferiori “left-bottom left-top right-top right-bottom”
Sistema di coordinatesono gli attributi x e y contenuti all’interno dei singoli elementi  ed indicano come devono essere posizionati all’interno dello spazio di disegno <svg>

Includere SVG in documento HTML

Un immagine SVG puo essere inclusa in diversi modi all’interno di un documento HTML:

<svg width="300" height="200"
     version="1.1" xmlns="http://www.w3.org/2000/svg">
	<text x="10" y="100"
	      style="fill:red;font-family:times;font-size:18">
	Primo esempio di SVG
	</text>
</svg>
  • incollando direttamente il codice contenuto nei tag <svg></svg>
<object width="300" height="200" data="immagine.svg" type="image/xml+svg">
   Scaricate il plugin SVG per visualizzare l'immagine
</object>
  • mediante i tags <object></object>; questo tipo di inclusione permette di aggiungere un file esterno e di restituire un messaggio di avviso, contenuto in esso, che informa che il browser non supporta SVG.
<embed src="immagine.svg"   type="image/xml+svg">
  • alcuni browser non interpretano in maniera corretta il tag <object> e preferiscono invece il tag <embed>.

Figure geometriche principali

Esistono delle figure geometriche principale che è possibile disegnare in un immagine SVG

Figuratag
testo<text></text>
rettangolo<rect></rect>
linea<line />
polilinea<polyline />
cerchio<circle />
poligono<polygon />
ellisse<ellipse />
figura irregolare<path />

Vediamo ora gli attribuiti che le singole figure devono avere:

tagattributi
<text></text>“<text x=”10″ y=”20″>Scritta</text>”;
Lo esamineremo sotto questa tabella
<rect></rect>“<rect x=”10″ y=”10″ rx=”2″ ry=”2″/>”;
Gli attributi x e y indicano le coordinate del vertice superiore sinistro del nostro rettangolo mentre tramite gli attributi width ed height è possibile specificare la larghezza e l’altezza del rettangolo.
<line />“<line x1=”10″ y1=”10″ x2=”100″ y2=”100″/>”;
Gli attributi x1 e y1 del tag <line> indicano le coordinate del punto iniziale della linea, mentre gli attributi x2 e y2 indicano il punto di arrivo della linea.
<polyline />“<polyline points=”10,10 50,50 90,10″/>” ;
L’attributo points indica le coppie di valori delle coordinate dei punti che costituiscono gli estremi della polyline.
<circle />“<circle cx=”100″ cy=”100″ r=”50″/>”;
Gli attributi cx e cy indicano le coordinate del centro della circonferenza mentre l’attributo r indica la dimensione del raggio della circonferenza stessa.
<polygon />“<polygon points=”250,250 297,284 279,340 220,340 202,284″/> “;
L’attributo points possiamo specificare le coordinate dei punti che costituiscono gli estremi del poligono.
<ellipse />“<ellipse cx=”100″ cy=”100″ rx=”70″ ry=”50″/>”;
Gli attributi cx e cy esprimono le coordinate del centro dell’ellisse mentre gli attributi rx e ry indicano rispettivamente la misura del raggio dell’ellisse lungo l’asse X e lungo l’asse Y.
<path />“<path d=”M100,150 L150,100 L200,150 Z”/>”;
Lo esamineremo sotto questa tabella

<text></text>

In SVG questo è possibile utilizzando l’elemento <tspan>, in abbinata all’elemento <text>.
Possiamo immaginare questo testo aggiuntivo come delle righe contenute nello stesso blocco/paragrafo di testo.

<text x="20" y="10">Prima riga
<tspan x="20" dy="20">Seconda riga</tspan>
<tspan dx="10" dy="20">Terza Riga</tspan>
</text>

Gli attributi x e y contenti in <text> indicano dove posizionare l’intero blocco nella SVG viewport; mentre gli attributi dx e dy indicano dove posizionare il testo contenuto nelle righe <tspan> rispetto alla posizione relativa di <text>.

<path/>

l path rappresenta una figura geometrica chiusa o aperta ed è costituito da una sequenza di segmenti che possono essere sia rettilinei che curvilinei.

<path d="M100,150 L150,100 L200,150 Z"/>

Non affronteremo l’argomento in maniera completa anche perchè non ci ritroveremo mai a disegnare “da codice” queste figure complesse; esistendo infatti, come accennato all’inzio di questo articolo, software come Adobe Illustrator che esegue una conversione da disegno vettoriale realizzato visualmente a SVG.
Basti sapere che le lettere M, L, L, Z e H sono istruzioni che indicano le cordinate x e y su: il punto di origine, una linea che parte dal punto di origine, una linea che parte dall’ultimo punto della linea precedente e la chiusura.

Risorse sul web
https://www.html.it/pag/31777/le-figure-geometriche-irregolari/

Aggiungere lo stile

E’ possibile aggiungere dello stile CSS alle figure di tipo testo di un immagine SVG mediante le classiche proprietà.

<text x="10" y="10" font-family="times" font-size="18">Scritta</text>
//oppure
<text x="10" y="10" style="font-family:times;font-size:18">Scritta</text>

Per tutti gli altri elementi esistono proprietà riservate:

fillpermette di indicare il colore di riempimento dell’elemento.
opacityindica il livello di opacità dell’elemento; valori: 1 e 0.
fill-ruledetermina il modo in cui verrà riempita l’area dell’elemento; molto utile nel caso di presenza di path complessi, stabilisce come verranno riempite le eventuali aree di intersezione.
strokepermette di specificare il colore della linea del bordo dell’elemento;
stroke-widthindica la misura dello spessore della linea;
stroke-dasharraypermette di specificare lo stile della linea es. normale o tratteggiata;
stroke-linecapdefinisce come saranno disegnati gli estremi della linea; valori: butt,round,square;
stroke-linejoindefinisce il modo in cui sarà disegnata l’intersezione tra due linee; valori: miterroundbevel;
displaypermette di controllare la visibilità di un elemento; valori: none l’elemento non verrà visualizzato; inline l’elemento sarà visualizzato.

Precompilare gli stili

In SVG possiamo definire lo stile di un elemento, seguendo la sintassi CSS, all’interno dell’elemento <style>

<svg height:"100px" width:"250px">

   <style type="text/css">
      text{font-family="times"; font-size="18";}
      rect {stroke:black; fill:red; stroke-width:5 }
      rect.coloreblu {stroke:black;fill:blue;stroke-width:5}
   </style>

   <text x="20" y="40">
   <rect x="10" y="10" />
   <rect class="coloreblue" x="110" y="10" />

</svg>

Nell’esempio qui sopra abbiamo incluso delle regole all’interno dei tag <style> posizionati all’interno del corpo della SVG canvas “<svg>”;
abbiamo definito una regola generale per i testi; una per i rettangoli ed attraverso una classe una regola particolare per i rettangoli di colore blu;
quest’ultima è stata richiamata all’interno del terzo elemento di tipo “rect” utilizzando l’attributo “class”.

Raggruppare gli elementi

E’ possibile raggruppare gli elementi attraverso l’elemento <g></g>.
Tramite questa operazione noi possiamo creare dei gruppi di elementi grafici e fare così in modo che gli elementi appartenenti allo stresso gruppo possano condividere determinati attributi e stili.

<g style="fill:green;stroke:black;stroke-width:3">
   <circle cx="100" cy="100" r="50"/>
   <rect x="200" y="50"/>
</g>

Trasformare gli elementi

Altra azione che potremo effettuare è l’operazione di trasformazione.
In SVG è possibile applicare alcune trasformazioni, proprietà già presenti nelle regole standard CSS, agli elementi grafici utilizzando l’attributo transform.

translate(tx,ty)permette di traslare la posizione dell’elemento grafico di tx unità lungo l’asse X e di ty unità lungo l’asse Y;
scale(sx,sy)effettua un’operazione di scalatura; valori: sx, lungo l’asse X, sy, lungo l’asse Y;
rotate(ra,cx,cy)permette di ruotare l’elemento grafico. Gli attributi cx e cy (che sono opzionali) indicano le coordinate del punto attorno al quale effettuare la rotazione;
skewX(sa)applica una trasformazione che inclina l’asse X di un angolo pari al valore indicato
skeyY(sa)applica una trasformazione che inclina l’asse Y di un angolo pari al valore indicato
matrix(a,b,c,d,e,f)applica all’elemento grafico la matrice di trasformazione
 <rect x="200" y="50" transform="scale(2,1);"/>

Aggiungere collegamenti

Analizziamo come sia possibile inserire all’interno della nostra immagine SVG dei link ad elementi esterni o interni all’immagine stessa attraverso il sistema anchor-link.

<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
  <!-- Un link attorno ad una forma -->
  <a href="/svg">
    <circle cx="50" cy="40" r="35"/>
  </a>

  <!-- Link attorno ad un testo -->
  <a href="/svg">
    <text x="50" y="90" text-anchor="middle">
      circle
    </text>
  </a>
</svg>

Potrebbe essere necessario per la compatibilità con le versioni precedenti per i browser meno recenti l’utilizzo dell’ attributo “xlink:href”

<a xlink:href="/svg">
    <text x="50" y="90" text-anchor="middle">
      circle
    </text>

Altre operazioni possibili

Le immagini svg permettono l’integrazione di altri elementi grafici:

  • Template
  • Inclusione di immagini PNG e JPG
  • Gradient e Patterns
  • Filtri ed effetti grafici

Adesso conosciamo gli elementi fondamentali che consentono di gestire un immagine SVG e la loro manipolazione.

Manipolazione di immagini SVG

Abbiamo effettuato un ampia introduzione sulle immagini SVG, ora possiamo gestire gli elementi SVG come facciamo con gli elementi standard del DOM di una pagina HTML.

Disegno cerchio SVG
<svg>
	<circle id="cerchio"
            cx="100" cy="100" r="50"
		    style="stroke: #000000; fill: blue;" />
</svg>

Il risultato è quello che segue:

var cerchio = document.getElementById("cerchio");
cerchio.style.fill = "red";

Utilizzando javascript possiamo modificare i valori degli attributi di un SVG

Animare un SVG

Possiamo quindi anche animare il nostro cerchio facendolo muovere all’interno della nostra pagina HTML

var cerchio = document.getElementById("cerchio");

function animazione() {
    var posizioneAsseX = cerchio.getAttribute("cx");
	var nuovaPosizioneX = parseInt(posizioneAsseX) + 2;
	
    if(nuovaPosizioneX > window.innerWidth) {
	   nuovaPosizioneX = 20;
	}
 
	cerchio.setAttribute("cx", nuovaPosizioneX);
}

var statoAnimazione;

function iniziaAnimazione() {
	if(statoAnimazione == null) {
		statoAnimazione = window.setInterval(animazione, 20);
	}
}


function fermaAnimazione() {
	if(statoAnimazione != null){
		window.clearInterval(statoAnimazione);
            statoAnimazione = null;
	}
}

Il precedente script prevede tre funzioni: una funzione per l’animazione una per farla iniziare ed una per fermarla.
Inoltre abbiamo previsto una variabile solo inizializzata per memorizzare lo stato della animazione e poterla controllare “var statoAnimazione”.

animazione()

La funzione dell’animazione recupera l’attributo “cx” dell’elemento con “getAttribute”, lo converte in numero “parseInt” e lo incrementa di 2; è previsto un controllo “if” che qualora il suo valore sia superiore alla larghezza della viewport riporta il valore a “20” (dall’altra parte dello schermo); infine applica il valore incrementato dalla funzione all’elemento con “setAttribute”.

iniziaAnimazione()

La funzione che si occupa di far partire l’animazione effettua il controllo del valore della variabile “stato Animazione”; se il valore è nullo, valore inziale dell’animazione ferma, imposta con “window.setInterval” che la funzione animazione() sia ripetura con intervalli di 20millisecondi.

Note: window.setInterval() è memorizzata all'interno di una variabile in modo tale da poter essere identificata successivamente nella controparte window.clearInterval().

fermaAnimazione()

La funzione per lo stop dell’animazione controlla sempre il valore di “statoAnimazione” che se l’animazione è già partita non avrà più valore nullo; a questo punto “pulisce” con “window.clearInterval()” la ripetizione dell’animazione precedentemente assegnata e attribuisce nuovamente il valore “nullo” alla variabile “statoAnimazione”.

Procediamo con l’attuazione del codice precedente includendo due bottoni per far iniziare e fermare l’animazione.

Le immagini Canvas

L’elemento Canvas è stato introdotto dalla Apple e infine standardizzato.
Canvas consente di disegnare forme bidimensionali (grafica vettoriale) e di gestire immagini bitmap (grafica raster).

Tramite le API di Canvas possiamo disegnare e colorare forme geometriche, creare gradienti, copiare immagini, convertirle e più in generale manipolare pixel.

La differenza sostanziale tra le grafiche vettoriale SVG sta nel fatto che CANVAS consente anche la gestione di grafica bitmap.

Creare un canvas

 Canvas è una tela su cui possiamo disegnare e colorare ed è individubile su un documento HTML dall’elemento <canvas>

<canvas id="miaCanvas" height:"250px" width:"450px"></canvas>

Se non indichiamo delle dimensioni specifiche tramite gli attributi width e height, le dimensioni predefinite sono fissate in 300 pixel per l’ampiezza e 150 per l’altezza, indipendentemente dal browser.

Acquisire il contesto

La prima operazione da fare è quella di acquisire il contento; l’acquisizione di un contesto oltre a determinare quale tipo di immagine trattare consente di acquisire metodi dedicati a determinati tipi di contesti-canvas.

var miaCanvas = document.getElementById('miaCanvas');
var contestoMiaCanvas = miaCanvas.getContext('2d');

Esistono vari tipi di contesti applicabili/acquisibili come : “2d” e “bitmaprenderer”; il secondo fornisce funzionalità per sostituire il contenuto della tela di immagini bitmap ed è specifico per determinate lavorazioni quindi ci concentreremo come accadeva per le immagini SVG sulla manipolazione di oggetti 2d vettoriali.

Proprietà e metodi

Acquisendo il “contesto” ereditiamo un ampio numero di metodi e proprietà per creare i nostri elementi grafici 2d.

context.beginPath()metodo che consente di avviare il disegno di un nuovo elemento
context.closePath()opzionale; può essere utilizzato ogni volta che si finisce di disegnare un nuovo tracciato; separa quindi una forma dall’altra
context.arc()metodo che consente di disegnare un arco, fornendo come parametri le coordinate del centro, la dimensione del raggio, l’angolo iniziale e l’angolo finale dell’arco
context.fillStyleproprietà che specifica il colore, la sfumatura o il motivo da utilizzare all’interno delle forme; valore di default #000 (nero).
context.fill()metodo che riempie il percorso corrente o forma con la proprietà .fillstyle
context.strokeStyleproprietà che specifica il colore, la sfumatura o il motivo del bordo delle forme; valore di default #000 (nero).
context.stroke()metodo che imposta il colore al percorso corrente o forma con la proprietà .strokeSyle

Per creare una forma questa dovremo sempre iniziare con context.beginPath() che potremmo tradurre come “nel contesto disegna nuova forma”;

//disegniamo un rettangolo
contestoMiaCanvas.beginPath();
contestoMiaCanvas.rect(20, 20, 150, 100);
contestoMiaCanvas.fillStyle = "red";
contestoMiaCanvas.fill();
contestoMiaCanvas.strokeStyle = "white";
contestoMiaCanvas.stroke();
contestoMiaCanvas.closePath()
//fine rettangolo

//disegniamo un arco
contestoMiaCanvas.beginPath();
contestoMiaCanvas.arc(100, 100, 50, 0, 2 * Math.PI);
contestoMiaCanvas.fillStyle = "#00ff00";
contestoMiaCanvas.fill();
contestoMiaCanvas.strokeStyle = "#000000";
contestoMiaCanvas.stroke();
contestoMiaCanvas.closePath()
//fine arco

Il livello lungo l’asse z (z-index) è determinato dall’ordine del codice scritto; l’ultimo elemento “disegnato” avrà valore maggiore e quindi si posizionerà al disopra del precedente.

Applicare animazione

Non potendolo manipolare gli elementi come avveniva in quelli SVG in stile DOM, la creazione di un elemento deve essere contenuta all’interno di una funzione i cui parametri, che rappresenteranno la posizione, devono essere variabili.

var myCanvas = document.getElementById("myCanvas");
var myCanvasContext = myCanvas.getContext("2d");

var x = 100;
var y = 100;

function disegnaCerchio(x, y) {
	myCanvasContext.beginPath();
	myCanvasContext.arc(x, y, 50, 0, 2 * Math.PI);
	myCanvasContext.fillStyle = "#00ff00";
	myCanvasContext.fill();
	myCanvasContext.strokeStyle = "#000000";
	myCanvasContext.stroke();
}
disegnaCerchio(x,y);

Per questo scopo ometteremo il comando finale di esecuzione della funzione “disegnaCerchio(x,y);” che di fatto disegna l’elemento.

function animation() {
	x = x + 2;
	if (x > myCanvas.width){ 
        x = 20;
}
	myCanvasContext.clearRect(0, 0, myCanvas.width, myCanvas.height);
	disegnaCerchio(x, y);
}

function startAnimation() {
window.setInterval(animation, 20);
	}

startAnimation();

Per eseguire l’animazione creiamo due funzioni: una che rappresenta l’animazione stessa ed una che la inizializza e fa in modo che si ripeta.

animation()

La funzione animation() si occupa di incrementare di 2 il valore della x; controllare che questo valore non sia maggiore della larghezza del contesto e nel caso contrario eventualmente riportarlo a valore 20, che rappresenta la posizione inziale; il metodo .clearRect() applicato al contesto si occupa di ripulire/cancellare  i pixel specificati all’interno di un determinato rettangolo.
Accetta quattro paramenti:
la coordinata x dell’angolo superiore sinistro,
la coordinata y dell’angolo superiore sinistro,
la larghezza del rettangolo da pulire espressa in pixel e l’altezza del rettangolo da pulire sempre espresso in pixel.
Infine all’interno della funzione animation() viene avviata la funzione di disegno disegnaCerchio(x, y).

startAnimation()

La funzione startAnimation() si occuperà di impostare un intervallo di ri-esecuizione ciclica dell’animazione presente nella funzione animation() attraverso il metodo window.setInterval().

Altri metodi

Abbiamo utilizzato proprietà e metodi fondamentali per spiegare il funzionamento e la manipolazione di forme dell’API Image Canvas; chiaramente l’API mette a disposizione numerosi metodi; elenchiamone qualcun altro:

context.moveTo(x,y)posiziona la punta della matita nel punto da cui iniziare il disegno
context.lineTo(x,y)disegna la linea fino al punto specificato
context.arc(x,y,r,start,stop)disegna un arco; accetta il punto centrale(x,y) il raggio(r), un angolo di partenza(start) ed uno di arrivo(stop) in radianti
context.rect(x,y,width,height)disegna un rettangolo o un quadrato; x e y sono la posizione d’inzio; width e height sono le dimensioni
context.fillRect(x, y, width, height)disegna un rettangolo già riempito del colore definito con fillStyle

Risorsa sul web
https://www.web-link.it/forme-canvas.html

Conclusione

E’ chiaro che l’approccio CANVAS è completamente differente da SVG;
SVG utilizza markup XML ed è manipolabile mediante javascript, canvas invece crea tutto, inculuse le forme, mediante JS.
SVG risulta ampiamente utilizzato grazie anche alla possibilità di utilizzare per il markup-xml editor grafici visuali ma non consente la manipolazione di immagini raster/bitmap; la scelta è quindi determinata dagli ambiti applicativi di sviluppo e principalmente da cosa ci apprestiamo a sviluppare.
La manipolazione dei pixel è utile per molte applicazione; si pensi alle ricerche di immagini simili su google, all’app che riconosce le costellazioni,
i filtri di instagram ecc.

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *