I was going to write save() and restore() myself, but I found a blog post that had a very clear understanding of save() and restore() and translated it. The original link: html5.litten.com/understandi…
— — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — O studying studying) O the following is a text O studying studying) O — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — –
First, THERE was a time when I couldn’t understand what save() and restore() really meant. In fact, it’s very simple, and here are a few chestnuts to help you understand these two methods better.
Let’s take a look at the official documentation for the definitions of save and restore:
Each Canvas context contains a stack that holds the state of the painting. The following contents belong to the state of painting:
- Current Transformation matrix
- Current clipping region
- StrokeStyle, fillStyle, globalAlpha, lineWidth, lineCap, lineJoin, miterLimit, shadowOffsetX, shadowOffsetY, shadowBlur, shadowCol Or, globalCompositeOperation, FONT, textAlign, textBaseline, the current values of these attributes
The current path and current bitmap are not drawn. The current path is permanent and always exists. To clear or reset, you can only use beginPath. The current bitmap is a property of the Canvas, not the context.
Context.save () pushes the current state onto the stack.
Context.restore () fetches the topmost state from the stack and restores the context to its extracted state.
Because a canvas can have only one 2D context, save and restore are widely used in a variety of situations. The most common of these is used for transformation.
A chestnut tells you how save() and restore() play a role in transformations.
When we use transformation, the coordinate system of the entire context is transformed. Usually after the transformation, the next thing we might want to do is restore the coordinate system to the normal state before the transformation. Are we going to reverse transformation again to restore the coordinate system? That’s obviously not a quick and reliable way to do it. At this point, we can save the normal coordinate system by state and push it onto the stack before transformation by using Save. After matrix transformation, we can remove the state we saved from the stack by using restore. It should be clearer when we look at the chestnuts.
At first we save the current state of the painting by using canvasContext.save () and push a copy of the current state into the painting state stack. As you can see below is a normal coordinate system, we save the current state. And then we do the matrix transformation, and we see that the coordinate system has changed. Then we draw the shape we want and fill in some colors. Now we want to draw more shapes on the canvas, but we don’t want to use the current matrix transformation, so we use restore() to remove the most recent state from the painting state stack, that is, the state we saved with the normal coordinate system. The current state becomes the state before we save. You can see that the grid in the background is restored to its normal coordinate system, but the shape we drew remains the same because the state we saved was only the Transformation state, and we didn’t set any other states we wanted to save.
Let’s do a more intuitive chestnut
Complete code and comments
Now let’s take a more intuitive look at how the painting state stack works with save() and restore().
<! doctype html> <html> <head> <meta charset="UTF-8" /> <title>Canvas Test</title> </head> <body> <header> </header> <nav> </nav> <section> <div> <canvas id="canvas" width="320" height="200"> This text is displayed if your browser does not support HTML5 Canvas. </canvas> </div> <script type="text/javascript"> var canvas; var ctx; function init() { canvas = document.getElementById("canvas"); ctx = canvas.getContext("2d"); draw(); } function draw() {// draw an orange rectangle and set the shadow ctx.fillstyle = '#FA6900'; ctx.shadowOffsetX = 5; ctx.shadowOffsetY = 5; ctx.shadowBlur = 4; Ctx. shadowColor = 'rgba(204, 204, 204, 0.5)'; ,0,15,150 CTX. FillRect (0); Ctx.save (); // Push the current state, which we call state 1 (orange, shadow-related attributes) into the stack; // Draw a yellowish rectangle and set the shadow ctx.fillStyle = '#E0E4CD'; ctx.shadowOffsetX = 10; ctx.shadowOffsetY = 10; ctx.shadowBlur = 4; Ctx. shadowColor = 'rgba(204, 204, 204, 0.5)'; CTX. FillRect (30,0,30,150); Ctx.save (); // Push the current state, which we call state 2 (earthen, shadow-related attributes) into the stack; // Draw an emerald rectangle and set the shadow ctx.fillStyle = '#A7DBD7'; ctx.shadowOffsetX = 15; ctx.shadowOffsetY = 15; ctx.shadowBlur = 4; Ctx. shadowColor = 'rgba(204, 204, 204, 0.5)'; CTX. FillRect,0,45,150 (90); Ctx.save (); // Push the current state, which we call state 3 (emerald green, shadow-related attributes) to the stack; Ctx.restore (); ctx.restore(); ctx.restore(); Ctx.beginpath (); ctx.beginPath(); ctx.beginPath(); ctx.beginPath(); ctx.arc(185, 75, 22, 0, Math.PI*2, true); ctx.closePath(); ctx.fill(); // Select the top state from the stack, now it is state 2, that is, the beige and shadow related property ctx.restore(); // The current state is in state 2, draw a circle and fill it, then it is a yellowy and shadow-related property ctx.beginPath(); ctx.arc(260, 75, 15, 0, Math.PI*2, true); ctx.closePath(); ctx.fill(); // Remove the top state from the stack, now state 1, namely the orange and shadow related property ctx.restore(); // The current state is state 1, draw a circle and fill it, then it is orange and shadow-related property ctx.beginPath(); ctx.arc(305, 75, 8, 0, Math.PI*2, true); ctx.closePath(); ctx.fill(); } init(); </script> </section> <aside> </aside> <footer> </footer> </body> </html>Copy the code
Section code, renderings, notes and specific instructions
Next, let’s segment the code and combine it with the illustration to make it clearer.
/* We drew an orange rectangle and set the shadow */ ctx.fillstyle = '#FA6900'; ctx.shadowOffsetX = 5; ctx.shadowOffsetY = 5; ctx.shadowBlur = 4; Ctx. shadowColor = 'rgba(204, 204, 204, 0.5)'; ,0,15,150 CTX. FillRect (0); /* Push the current state (fillStyle orange, shaded attribute) into the state stack, say state 1 */ ctx.save();Copy the code
You can see in the picture below that there is an extra state in the stack, and the color is close to the rectangle to make it easier to understand.
/* Then we draw an earthen rectangle and set the shadow */ ctx.fillstyle = '#E0E4CD'; ctx.shadowOffsetX = 10; ctx.shadowOffsetY = 10; ctx.shadowBlur = 4; Ctx. shadowColor = 'rgba(204, 204, 204, 0.5)'; CTX. FillRect (30,0,30,150); /* Push the current state (fillStyle yellowish, shaded) into the state stack, say state 2 */ ctx.save();Copy the code
We see that there are two states in the stack: State 1 (orange) and State 2 (khaki)
/* Then we drew an emerald rectangle and set the shadow */ ctx.fillstyle = '#A7DBD7'; ctx.shadowOffsetX = 15; ctx.shadowOffsetY = 15; ctx.shadowBlur = 4; Ctx. shadowColor = 'rgba(204, 204, 204, 0.5)'; CTX. FillRect,0,45,150 (90); /* Push the current state (fillStyle emerald green, shaded attribute) into the state stack, say state 3 */ ctx.save();Copy the code
We see three states in the stack: State 1 (orange), State 2 (khaki), and State 3 (emerald green)
*/ ctx.restore(); */ ctx.restore(); */ ctx.restore(); /* Draw an emerald circle */ ctx.beginPath(); ctx.arc(185, 75, 22, 0, Math.PI*2, true); ctx.closePath(); ctx.fill();Copy the code
*/ ctx.restore(); */ ctx.restore(); /* Draw a yellowish circle */ ctx.beginPath(); ctx.arc(260, 75, 15, 0, Math.PI*2, true); ctx.closePath(); ctx.fill();Copy the code
/* If we retrieve state 3 from the top of the stack, the current drawing state becomes state 1 (orange) */ ctx.restore(); /* Draw an orange circle */ ctx.beginPath(); ctx.arc(305, 75, 8, 0, Math.PI*2, true); ctx.closePath(); ctx.fill();Copy the code
— — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — O studying studying) end O O text studying studying) O — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — —
Is it easy to get down? ! I hope I translated that well. Corrections are welcome.
I am “Nanqiu ah Nanqiu”, I hope you can study hard in ordinary days, love life, every day is a good day!