1

<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只有两个可选属性,widthheight,可以通过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创建路径。
  • 实际绘制路径,例如用moveTolineToarcToquadraticCurveTobezierCurveTo之类的函数。
  • closePath会尝试用直线连接当前端点与起始端点。如果图形已经关闭或只有一点,它什么也不做。(此步可选。)
  • 以上只是定了路径,要用strokefill,才能显示出来。调用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前后用saverestore保存状态。

缩放用scale

transfarm允许直接操作变形矩阵。

组合

利用globalCompositeOperation设置图形间composite关系。例如globalCompositeOperation = source-in会导致新图形与原有内容重叠的部分绘制出来,其他部分变为透明。这可以用来裁切一部分画面,只显示裁切出来的画面——不过clip用来干这个更好,clip裁切路径,路径之外的都不会显示出来,这样就不用为了裁切而绘制新图形了。

动画

基本上每一帧需要做这些事情:

  • 清空画面,最简单的做法是用clearRect。如果需要残影,可以用fillRect,使用和背景色一样的矩形,但是又有一点透明度(例如0.2)。
  • 保存canvas状态。
  • 绘制动画图形。
  • 恢复canvas状态。

动画的操控用setIntervalsetTimeout来做。setInterval定期重绘,setTimeout只执行一次。此外,还可以利用用户的输入来实现操控。

setInterval的问题是有时候动画的执行时间会超过设置的时间间隔(例如CPU或显卡不给力),而且,即使用户切换了标签页,动画也会在后台默默执行(看,或不看,canvas就在那里)。requestAnimFrame就会判断是否位于当前标签页,也会为动画选择合适的FPS。

例子

@Fakefish 参加SegmentFault 30行js比赛的作品。

http://jsfiddle.net/7g5JP/5/

基本思路,遍历数组加上随机过程,产生一些躁动的粒子,粒子运动到设定范围内就会固定下来,最终形成图案。此外,粒子在固定范围内也有比较小的几率会逃逸出去,增加一点变化。


weakish
24.6k 声望844 粉丝

a vigorously lazy deadbeat with matured immaturity