JavaScript Canvas 恢复教程
最后修改于 2025 年 4 月 3 日
在本文中,我们探讨了 JavaScript 中的 Canvas 保存和恢复方法。这些方法对于管理 HTML Canvas 的绘图状态堆栈至关重要。掌握状态管理对于复杂的绘图和动画至关重要。
基本定义
Canvas 的 save() 和 restore() 方法用于管理绘图状态堆栈。save()
方法将当前状态推送到堆栈。restore()
方法从堆栈中弹出顶部状态。
绘图状态包括样式、变换和剪切路径。这允许进行临时更改,而不会影响后续的绘图。正确进行状态管理是高效 Canvas 编程的关键。
基本保存和恢复
此示例演示了 save 和 restore 方法的基本用法。
<!DOCTYPE html> <html> <head> <title>Basic Save and Restore</title> </head> <body> <canvas id="myCanvas" width="300" height="200"></canvas> <script> const canvas = document.getElementById('myCanvas'); const ctx = canvas.getContext('2d'); // Original state ctx.fillStyle = 'blue'; ctx.fillRect(10, 10, 100, 100); // Save current state ctx.save(); // Change state ctx.fillStyle = 'red'; ctx.fillRect(150, 10, 100, 100); // Restore original state ctx.restore(); // Uses original blue color ctx.fillRect(10, 120, 100, 50); </script> </body> </html>
此示例展示了如何保存绘图状态。我们首先绘制一个蓝色矩形,然后在更改填充颜色为红色之前保存状态。
绘制红色矩形后,我们恢复到之前的状态。最后一个矩形使用了原始的蓝色,演示了状态恢复。
嵌套保存和恢复
此示例演示了嵌套的保存和恢复操作。
<!DOCTYPE html> <html> <head> <title>Nested Save and Restore</title> </head> <body> <canvas id="myCanvas" width="400" height="300"></canvas> <script> const canvas = document.getElementById('myCanvas'); const ctx = canvas.getContext('2d'); // Level 0 state ctx.fillStyle = 'black'; ctx.fillRect(10, 10, 100, 100); // Save Level 0 ctx.save(); // Level 1 state ctx.fillStyle = 'blue'; ctx.fillRect(150, 10, 100, 100); // Save Level 1 ctx.save(); // Level 2 state ctx.fillStyle = 'red'; ctx.fillRect(290, 10, 100, 100); // Restore to Level 1 ctx.restore(); ctx.fillRect(150, 120, 100, 100); // Restore to Level 0 ctx.restore(); ctx.fillRect(10, 120, 100, 100); </script> </body> </html>
此示例展示了嵌套状态管理。我们创建了三个具有不同填充颜色的状态,在更改为下一个状态之前保存了每个状态。
恢复时,我们按照相反的顺序回退到各个状态。这演示了堆栈如何与多个保存操作协同工作。
带有变换的保存和恢复
此示例展示了带有 Canvas 变换的保存/恢复。
<!DOCTYPE html> <html> <head> <title>Save/Restore with Transformations</title> </head> <body> <canvas id="myCanvas" width="400" height="300"></canvas> <script> const canvas = document.getElementById('myCanvas'); const ctx = canvas.getContext('2d'); // Original state ctx.fillStyle = 'blue'; ctx.fillRect(50, 50, 100, 50); // Save state ctx.save(); // Apply transformation ctx.translate(200, 100); ctx.rotate(Math.PI/4); ctx.fillStyle = 'red'; ctx.fillRect(0, 0, 100, 50); // Restore original state ctx.restore(); // Draw with original state ctx.fillRect(50, 150, 100, 50); </script> </body> </html>
此示例演示了保存和恢复变换状态。我们首先在原始坐标系中绘制一个蓝色矩形。
保存状态后,我们平移和旋转 Canvas,然后绘制一个红色矩形。恢复后,后续的绘图将使用原始的未变换坐标。
带有剪切的保存和恢复
此示例展示了带有剪切路径的保存/恢复。
<!DOCTYPE html> <html> <head> <title>Save/Restore with Clipping</title> </head> <body> <canvas id="myCanvas" width="400" height="300"></canvas> <script> const canvas = document.getElementById('myCanvas'); const ctx = canvas.getContext('2d'); // Original drawing ctx.fillStyle = 'blue'; ctx.fillRect(50, 50, 300, 200); // Save state ctx.save(); // Create clipping path ctx.beginPath(); ctx.arc(200, 150, 100, 0, Math.PI * 2); ctx.clip(); // Draw with clipping ctx.fillStyle = 'red'; ctx.fillRect(50, 50, 300, 200); // Restore state (removes clipping) ctx.restore(); // Draw without clipping ctx.fillStyle = 'green'; ctx.fillRect(100, 100, 200, 100); </script> </body> </html>
此示例演示了使用 save/restore 管理剪切路径。我们首先绘制一个覆盖整个绘图区域的蓝色矩形。
保存状态后,我们创建一个圆形剪切路径并绘制一个红色矩形(仅在圆内可见)。恢复后,剪切将被移除,我们可以正常进行绘图。
包含多个状态的复杂示例
此示例结合了多个状态更改和 save/restore。
<!DOCTYPE html> <html> <head> <title>Complex Save/Restore Example</title> </head> <body> <canvas id="myCanvas" width="500" height="400"></canvas> <script> const canvas = document.getElementById('myCanvas'); const ctx = canvas.getContext('2d'); // Initial state ctx.fillStyle = 'gray'; ctx.fillRect(0, 0, 500, 400); // Save state 1 ctx.save(); ctx.fillStyle = 'blue'; ctx.translate(100, 100); ctx.fillRect(0, 0, 100, 100); // Save state 2 ctx.save(); ctx.fillStyle = 'red'; ctx.rotate(Math.PI/4); ctx.fillRect(0, 0, 100, 100); // Save state 3 ctx.save(); ctx.fillStyle = 'green'; ctx.scale(1.5, 1.5); ctx.fillRect(50, 50, 100, 100); // Restore to state 2 ctx.restore(); ctx.fillRect(0, 0, 100, 100); // Restore to state 1 ctx.restore(); ctx.fillRect(150, 0, 100, 100); // Restore to initial state ctx.restore(); ctx.fillRect(300, 100, 100, 100); </script> </body> </html>
这个复杂的示例展示了多次状态更改以及变换。我们从灰色背景开始,然后创建三个嵌套状态。
每个状态都添加了新的变换和样式更改。恢复时,我们回退到每个状态,演示了堆栈的工作方式。最终的矩形使用的是原始的未变换状态。
来源
在本文中,我们探讨了 Canvas 中的 save 和 restore 方法。这些强大的工具通过保存状态来帮助管理复杂的绘图。正确使用这些方法可以带来更清晰、更易于维护的代码。
作者
列出 所有 JS Canvas 教程。