日期:2014-05-17  浏览次数:20781 次

HTML5 canvas变换

?

?

2.2.3 变换

现在我们探讨一下在canvas上绘制图像的另一种方式--使用变换(transformation)。接下来的代码清单显示结果跟上

面是一样的,只是绘制对角线的代码不一样。这个简单示例可能会让你误认为使用变换增加了不必要的复杂性。事实并非

如此,其实变换是实现复杂canvas操作的最好方式。在后面的示例中将会看到,我们使用了大量的变换,而这对熟悉

HTML5 Canvas API的复杂功能是至关重要的。

?

也许了解变换最简单的方法(至少这种方法不涉及大量的数学公式,也不需手足并用地去解释)就是把它当成是介于

开发人员发出的指令和canvas显示结果之间的一个修正层(modification layer)。不管在开发中是否使用变换,

修正层始终都是存在的。

?

修正--在绘制系统中的说法是变换--在应用的时候可以被顺序应用、组合或者随意修改。每个绘制操作的结果显示

在canvas上之前都要经过修正层去做修正。虽然这么做增加了额外的复杂性,但却为绘制系统添加了更为强大的

功能,可以像目前主流图像编辑工具那样支持实时图像处理,所以API中这部分内容的复杂性是必要的。

?

不在代码中调用变换函数并不意味着可以提升canvas的性能。canvas在执行的时候,变换会被呈现引擎

隐式调用,这与开发人员是否直接调用无关。在接触最基本的绘制操作之前,提前了解系统背后的原理至关

重要。

?

关于可重用代码有一条重要的建议:一般绘制都应从原点(坐标系中的0,0点)开始,

应用变换(缩放、平移、旋转等),然后不断修改代码直至达到希望的效果。如图2-4所示。

?

代码清单2-7展示了如何使用最简单变换方法--translate函数。

?
(点击查看大图)图2-4 基于原点绘制和变换的示意图
代码清单2-7 用变换的方式在canvas上绘制对角线
  1. <script>?
  2. ??function?drawDiagonal()?{ ?
  3. ????var?canvas?=?document.getElementById('diagonal'); ?
  4. ????var?context?=?canvas.getContext('2d'); ?
  5. ?
  6. ????//?保存当前绘图状态 ?
  7. ????context.save(); ?
  8. ?
  9. ????//?向右下方移动绘图上下文 ?
  10. ????context.translate(70,?140); ?
  11. ?
  12. ????//?以原点为起点,绘制与前面相同的线段 ?
  13. ????context.beginPath(); ?
  14. ????context.moveTo(0,?0); ?
  15. ????context.lineTo(70,?-70); ?
  16. ????context.stroke(); ?
  17. ?
  18. ????//?恢复原有的绘图状态 ?
  19. ????context.restore(); ?
  20. ??} ?
  21. ?
  22. ??window.addEventListener("load",?drawDiagonal,?true); ?
  23. </script>?

我们详细研究一下上面这段通过平移方式绘制对角线的JavaScript代码。

(1) 首先,通过ID找到并访问canvas对象。(ID是diagonal。)

?

(2) 接着通过调用canvas对象的getContext函数获取上下文对象。

?

(3) 接下来,保存尚未修改的context,这样即使进行了绘制和变换操作,

也可以恢复到初始状态。如果不保存,那么在进行了平移和缩放等操作以后,

其影响会带到后续的操作中,而这不一定是我们所希望的。在变换前保存context状态可以方便以后恢复。

?

(4) 下一步是在context中调用translate函数。通过这个操作,当平移行为发生的时候,

我们提供的变换坐标会被加到结果坐标(对角线)上,结果就是将要绘制的对角线移动到

了新的位置上。不过,对角线呈现在canvas上是在绘制操作结束之后。

?

(5) 应用平移后,就可以使用普通的绘制操作来画对角线了。代码清单中调用了

三个函数来绘制对角线--beginPath、moveTo以及lineTo。绘制的起点是

原点(0,0),而非坐标点(70,140)。

?

(6) 在线条勾画出来之后,可以通过调用context.stroke()函数将其显示在canvas上。

?

(7) 最后,恢复context至原始状态,这样后续的canvas操作就不会被刚才的平移

操作影响了。图2-5显示了用这段代码绘制的对角线。