State Stack

 

Funzionamento di save() e restore():

  1. save():

    • Salva lo stato corrente del contesto, inclusi tutti gli attributi di disegno (come colori, linee, ecc.) e le trasformazioni (come scala, rotazione, traslazione).
  2. Disegno di oggetti:

    • Gli oggetti disegnati dopo una trasformazione (come scale) saranno influenzati da quella trasformazione.
  3. restore():

    • Ripristina lo stato del contesto al punto in cui è stato chiamato save(), annullando tutte le trasformazioni e le modifiche agli attributi che sono state fatte dopo il save().
    • Tuttavia, gli oggetti che sono stati disegnati prima del restore() rimarranno sulla tela con le trasformazioni applicate.

Per chiarire ulteriormente, ecco un esempio che mostra chiaramente la sequenza di salvataggio, trasformazione, disegno e ripristino:

 

stateStack.html: esegui

 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <meta name="viewport" content="width=device-width, initial-scale=1.0">
 6     <title>Ovale con Canvas</title>
 7 </head>
 8 <body>
 9     <canvas id="myCanvas" width="300" height="150" style="border:1px solid #000;"></canvas>
10 
11     <script>
12         var canvas = document.getElementById('myCanvas');
13         var ctx = canvas.getContext('2d');
14 
15         // Salva lo stato del contesto
16         ctx.save();
17 
18         // Scala il contesto orizzontalmente (allunga il cerchio)
19         ctx.scale(2, 1);
20 
21         // Disegna un cerchio (che apparirà come un ovale a causa della scala)
22         ctx.beginPath();
23         ctx.arc(50, 50, 40, 0, 2 * Math.PI);
24         ctx.closePath();
25         ctx.fillStyle = 'blue';
26         ctx.fill();
27 
28         // Ripristina lo stato del contesto (annulla la scala)
29         ctx.restore();
30 
31         // Disegna un altro cerchio senza trasformazione (apparirà come un cerchio)
32         ctx.beginPath();
33         ctx.arc(150, 50, 40, 0, 2 * Math.PI);
34         ctx.closePath();
35         ctx.fillStyle = 'red';
36         ctx.fill();
37     </script>
38 </body>
39 </html>

 

In questo esempio:

  • Il primo cerchio viene disegnato con la trasformazione di scala applicata, quindi appare come un ovale.
  • Dopo il restore(), il contesto torna allo stato originale (senza scala).
  • Il secondo cerchio viene disegnato senza alcuna trasformazione, quindi appare come un cerchio.

Questo dimostra chiaramente che restore() ripristina lo stato del contesto ma non cancella gli oggetti che sono già stati disegnati.

Si possono eseguire più save() ma il restore ripristina solo l'ultimo save(). Ladomanda è avendo eseguitopiù diun save() posso ripristinare un save precedente che non sia l'ultimo, od uno a piacere tra quellieseguiti?

In HTML5 Canvas, il metodo restore() ripristina lo stato del contesto al punto dell'ultimo save() chiamato. Non esiste un modo diretto per ripristinare lo stato del contesto a un punto intermedio di una sequenza di save() chiamati. Ogni chiamata a restore() ripristina lo stato salvato più recentemente. Tuttavia, è possibile gestire manualmente stati multipli di salvataggio con un po' di logica aggiuntiva nel tuo codice.

Se vuoi un controllo più preciso sugli stati salvati, potresti considerare di creare un sistema di gestione degli stati utilizzando stack (pila) per salvare manualmente gli stati che ti interessano e ripristinarli quando necessario. Ecco un esempio di come puoi implementarlo:

 

stateStackMulti.html: esegui

 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <meta name="viewport" content="width=device-width, initial-scale=1.0">
 6     <title>Gestione avanzata degli stati del contesto</title>
 7 </head>
 8 <body>
 9     <canvas id="myCanvas" width="400" height="200" style="border:1px solid #000;"></canvas>
10 
11     <script>
12         var canvas = document.getElementById('myCanvas');
13         var ctx = canvas.getContext('2d');
14 
15         // Stack per gestire stati multipli
16         var stateStack = [];
17 
18         // Funzione per salvare lo stato
19         function saveState() {
20             stateStack.push(ctx.save());
21         }
22 
23         // Funzione per ripristinare uno stato specifico
24         function restoreState(index) {
25             while (stateStack.length > index) {
26                 ctx.restore();
27                 stateStack.pop();
28             }
29         }
30 
31         // Salva lo stato iniziale
32         saveState(); // Stato 0
33 
34         // Modifica gli attributi del contesto e salva lo stato
35         ctx.scale(2, 1);
36         ctx.fillStyle = 'blue';
37         saveState(); // Stato 1
38 
39         // Disegna un ovale
40         ctx.beginPath();
41         ctx.arc(50, 50, 40, 0, 2 * Math.PI);
42         ctx.closePath();
43         ctx.fill();
44 
45         // Modifica ulteriormente gli attributi del contesto e salva lo stato
46         ctx.rotate(Math.PI / 4);
47         ctx.fillStyle = 'red';
48         saveState(); // Stato 2
49 
50         // Disegna un altro ovale ruotato
51         ctx.beginPath();
52         ctx.arc(150, 50, 40, 0, 2 * Math.PI);
53         ctx.closePath();
54         ctx.fill();
55 
56         // Ripristina lo stato intermedio (Stato 1)
57         restoreState(1);
58 
59         // Disegna un cerchio con gli attributi dello Stato 1
60         ctx.beginPath();
61         ctx.arc(250, 50, 40, 0, 2 * Math.PI);
62         ctx.closePath();
63         ctx.fill();
64     </script>
65 </body>
66 </html>

 

In questo esempio, utilizziamo uno stack (stateStack) per tenere traccia degli stati salvati. La funzione saveState() salva lo stato del contesto e aggiunge un riferimento allo stack. La funzione restoreState(index) ripristina gli stati fino a raggiungere l'indice specificato nello stack.

Con questo metodo, puoi gestire e ripristinare stati specifici del contesto in modo più flessibile rispetto all'uso diretto di save() e restore().