Chapter 2, Canvas
Canvas是一个位图画布, 最早由Apple公司提出, 由于这种二维绘图API对浏览器来说非常有用, 所以后来被纳入到HTML5规范.
使用Canvas后可以避免对Flash和SVG插件的依赖, 也不用只有IE支持的VML, 并且使用Canvas不需要将所有图元当作对象储存, 因此性能上也是非常不错的.
目前主流的浏览器都已经支持Canvas,IE也在IE9版本中加入了对Canvas的支持,但是对现存浏览器也不用担心,使用浏览器检测就可以做到简单的fallback。
那么Canvas怎么用呢?首先在HTML中添加Canvas标签,通过js获取到Canvas对象及其上下文(context)。接着就是调用Canvas的API啦,个人感觉还是听强大的,当年虽然玩了一些MFC的绘图API,但是那种C++的偏底层的API确实用起来感觉很麻烦。
2维的绘图能干什么呢?画直线,画曲线、椭圆、矩形啥都能画,并且样式上是用标准的CSS的,还支持CSS3的样式(如渐变、透明度等效果),并且可以显示文本和贴图。所以Canvas能做到的事情非常多,这也是为什么现在移动终端做游戏的首选吧~(PC 端的情况也一样,Web Game有着跨平台的优势,并且开发成本也相对较低)。
Canvas的实质?还记得上面说的“使用Canvas不需要将所有图元当作对象储存”吗?使用Canvas时,我们实际要操作的是其上下文(context),通过document.querySelector('canvas').getContext("2d");获得。接着在上下文中执行动作,最后将这些动作应用到上下文中。有句话说的非常好:“可以将canvas的这种编辑方式想象为数据库事务:开发人员先发起一个事务,然后执行某些操作,最后提交事务”。比较具体一点的例子可以这样解释:需要画一个圆时,我会这样:
context.arc(centerX,centerY,radius,0,2*Math.PI,false);
当我使用context.fill()方法时,要画出的圆会直接显示在画布上,而看不到画出圆的轨迹。
那么如何做出动画效果呢?无非就是对canvas进行重绘(设置定时器),控制动画帧的速度,达到效果与性能的平衡,另外对于性能的优化,可以对最小区域进行局部重绘,具体内容本文不予深入讨论。
讲了这么多写个小Demo看看:
demo的效果如图所示,画了一个简单的五角星。涉及到了几个常用的API而已,为了通用性,我把它实现为绘制多角形的函数

说下大概的框架代码:
// 保存上下文 context.save(); // 移动原点 context.translate(offsetX, offsetY); // 以原点为起点,开始绘制 context.beginPath(); // do something context.moveTo(posX, posY); context.lineTo(desX, desY); context.stroke(); // 恢复上下文 context.restore();
上述代码只是画了一条线段,如果要画一个封闭的图形,需要在画到最后一个点后使用closePath方法达到图形的闭合。为了获得更好的效果可以设置strokeStyle和fillStyle进行CSS样式设置,注意只有当对路径应用绘制(stroke)或填充(fill)时,才会显示出效果。
至于上面讲到的变换,即translate、scale等方法,可以做到平移、旋转和缩放。是否担心性能问题?Don't worry about it.就算不显式调用,渲染引擎还是会隐式调用的。而且经常通过平移坐标原点比起moveTo的方法会使得代码更具阅读性,至于你怎么选择,反正我是这么做了: )
最后值得需要注意的地方时关于绘制图片,建议使用:
var img = new Image();
img.src = "img.png";
img.onload = function(){
//do somgthing..
}
保证图片加载后再绘制到canvas中,否则图片会显示不出来。
See also:




&