存储与清除图像的变换状态

图像变换的效果会保留下来。我们绘制出一次镜像特征后,绘制其他特征时都会产生镜像效果,这可能并不方便。

对于需要临时转换坐标系统的函数来说,我们经常需要保存当前的信息,画一些图,变换图像然后重新加载之前的图像。首先,我们需要将当前函数调用的所有图形变换信息保存起来。接着,函数完成其工作,并添加更多的变换。最后我们恢复之前保存的变换状态。

2D 画布上下文的saverestore方法执行这个变换管理。这两个方法维护变换状态堆栈。save方法将当前状态压到堆栈中,restore方法将堆栈顶部的状态弹出,并将该状态作为当前context对象的状态。

下面示例中的branch函数首先修改变换状态,然后调用其他函数(本例中就是该函数自身)继续在特定变换状态中进行绘图。

这个方法通过画出一条线段,并把坐标系的中心移动到线段的端点,然后调用自身两次,先向左旋转,接着向右旋转,来画出一个类似树一样的图形。每次调用都会减少所画分支的长度,当长度小于 8 的时候递归结束。

  1. <canvas width="600" height="300"></canvas>
  2. <script>
  3. let cx = document.querySelector("canvas").getContext("2d");
  4. function branch(length, angle, scale) {
  5. cx.fillRect(0, 0, 1, length);
  6. if (length < 8) return;
  7. cx.save();
  8. cx.translate(0, length);
  9. cx.rotate(-angle);
  10. branch(length * scale, angle, scale);
  11. cx.rotate(2 * angle);
  12. branch(length * scale, angle, scale);
  13. cx.restore();
  14. }
  15. cx.translate(300, 0);
  16. branch(60, 0.5, 0.8);
  17. </script>

如果没有调用saverestore方法,第二次递归调用branch将会在第一次调用的位置结束。它不会与当前的分支相连接,而是更加靠近中心偏右第一次调用所画出的分支。结果图像会很有趣,但是它肯定不是一棵树。