<canvas>
最早在Mac OS X Dashboard上被引入,而后被应用于Safari。Firefox 1.5起支持了这个元素。后来成为了HTML 5标准的一部分。
尽管SVG也可以做动画,但是一般还是常用于静态图形。canvas做动画更得心应手——当然也有人用canvas做图表。
今天下午 @Fakefish作了“就是你了,Canvas!”的分享,介绍了Canvas的基本知识,以及自己写Canvas的一些心得。下面是我的听讲笔记。
Canvas元素
canvas
元素的定义:
<canvas id="tutorial" width="150" height="150"></canvas>
canvas
只有两个可选属性,width
和height
,可以通过DOM或CSS设置。
替用内容
为老旧浏览器准备替用内容:
<canvas id="stockGraph" width="150" height="150">
current stock price: $3.15 +0.15
</canvas>
<canvas id="clock" width="150" height="150">
<img src="images/clock.png" width="150" height="150"/>
</canvas>
渲染上下文
首先需要取得canvas对象的DOM节点,然后渲染上下文:
canvas = document.getElementById('tutorial')
ctx = canvas.getContext('2d')
看到2d
我以为还会有3d
,结果没有……目前只支持2d,将来可能会有基于OpenGL ES的3d.
绘制矩形
ctx.fillStyle = 'rgba(200,0,0, 0.5)'
ctx.fillRect(10, 10, 55, 50)
rgba
是颜色和透明度,fillRect
是左上角坐标和宽、高。
空心的用strokeRect
画,擦除用clearRect
。
曲线
画曲线好麻烦。
- 用
beginPath
创建路径。 - 实际绘制路径,例如用
moveTo
、lineTo
、arcTo
、quadraticCurveTo
、bezierCurveTo
之类的函数。 -
closePath
会尝试用直线连接当前端点与起始端点。如果图形已经关闭或只有一点,它什么也不做。(此步可选。) - 以上只是定了路径,要用
stroke
或fill
,才能显示出来。调用fill
的话,会自动闭合开放路径,可以省去写closePath
的功夫。
图像
drawImage(image, x, y)
drawImage(image, x, y, width, height) # 缩放
drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight) # 截图
如果是视频的话,可以监听video的播放事件,然后用drawImage
获取当前播放的帧。
变形
用rotate
可以旋转,注意这是以画布原点为中心的。如果需要以图形的端点或中心点为中心,就需要translate
原点。translate
前后用save
和restore
保存状态。
缩放用scale
。
transfarm
允许直接操作变形矩阵。
组合
利用globalCompositeOperation
设置图形间composite关系。例如globalCompositeOperation = source-in
会导致新图形与原有内容重叠的部分绘制出来,其他部分变为透明。这可以用来裁切一部分画面,只显示裁切出来的画面——不过clip
用来干这个更好,clip
裁切路径,路径之外的都不会显示出来,这样就不用为了裁切而绘制新图形了。
动画
基本上每一帧需要做这些事情:
- 清空画面,最简单的做法是用
clearRect
。如果需要残影,可以用fillRect
,使用和背景色一样的矩形,但是又有一点透明度(例如0.2
)。 - 保存canvas状态。
- 绘制动画图形。
- 恢复canvas状态。
动画的操控用setInterval
和setTimeout
来做。setInterval
定期重绘,setTimeout
只执行一次。此外,还可以利用用户的输入来实现操控。
setInterval
的问题是有时候动画的执行时间会超过设置的时间间隔(例如CPU或显卡不给力),而且,即使用户切换了标签页,动画也会在后台默默执行(看,或不看,canvas就在那里)。requestAnimFrame
就会判断是否位于当前标签页,也会为动画选择合适的FPS。
例子
@Fakefish 参加SegmentFault 30行js比赛的作品。
基本思路,遍历数组加上随机过程,产生一些躁动的粒子,粒子运动到设定范围内就会固定下来,最终形成图案。此外,粒子在固定范围内也有比较小的几率会逃逸出去,增加一点变化。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。