定义
Canvas API 提供了一个通过JavaScript 和 HTML的 canvas 元素来绘制图形的方式。它可以用于动画、游戏画面、数据可视化、图片编辑以及实时视频处理等方面。
基本用法
var canvas = document.getElementById('tutorial');
if (canvas.getContext){ //确定浏览器支持<canvas>元素
var ctx = canvas.getContext('2d');
}
1.canvas 元素创造了一个固定大小的画布,getContext()的方法,传入"2d",就可以获得渲染上下文和它的绘画功能。
2.在使用 canvas 元素之前,首先要检查 getContext() 方法的支持性。
绘制形状
绘制矩形 [ 矩形是唯一一种可以直接在 2D 上下文中绘制的形状。 ]
-
canvas提供了三种方法绘制矩形:
- fillRect(x, y, width, height) // 绘制一个填充的矩形
- strokeRect(x, y, width, height) // 绘制一个矩形的边框
- clearRect(x, y, width, height) // 清除指定矩形区域,让清除部分完全透明。

fillRect()函数绘制了一个边长为60px的黑色正方形。
strokeRect()函数绘制了一个边长为60px的正方形边框。
绘制路径 [ 通过路径可以创造出复杂的形状和线条。 ]
-
绘制路径需要用到的函数:
- beginPath() // 新建一条路径,生成之后,图形绘制命令被指向到路径上生成路径。
- stroke() // 通过线条来绘制图形轮廓。
- fill() // 通过填充路径的内容区域生成实心的图形。
- closePath() // 闭合路径之后图形绘制命令又重新指向到上下文中。
绘制直线
- 绘制直线需要用到的函数:
-
moveTo(x, y) // 将绘图游标移动到 (x,y) ,不画线。
-
lineTo(x, y) // 从上一点开始绘制一条直线,到 (x,y) 为止。

moveTo() 可以理解为起始坐标,lineTo()可以理解为终点坐标;
即起始坐标(50,150)与终点坐标(200,150)之间绘制一条直线
-
绘制圆弧
- 绘制圆弧需要用到的函数:
-
arc(x, y, r, sA, eA, c) // 以 (x,y) 为圆心绘 制半径为 r一条弧线,起始和结束角度(用弧度表示)分别为 sA 和eA 。最后一个参数表示 是否按逆时针方向计算。
-
arcTo(x1, y1, x2, y2, radius) :从上一点开始绘制一条弧线,到 (x2,y2) 为止,并且以 给定的半径 radius 穿过 (x1,y1)

arc()函数绘制以(150,70)为圆心绘制半径为50的圆形;
arcTo()函数绘制以(250,20)为起始坐标,到(350,80)坐标绘制半径为50 穿过(250,50)坐标的一条弧线。如果搞不太懂得可以点击查看 其他例子
-
绘制二次贝塞尔曲线及三次贝塞尔曲线
-
绘制需要用到的函数:
-
bezierCurveTo(c1x, c1y, c2x, c2y, x, y) // 从上一点开始绘制一条曲线,到 (x,y) 为 止,并且以 (c1x,c1y) 和 (c2x,c2y) 为控制点。
-
quadraticCurveTo(cx, cy, x, y) // 从上一点开始绘制一条二次曲线,到(x,y) 为止,并且以 (cx,cy) 作为控制点。

开始点、结束点(蓝色)、控制点(红色)
-
绘制文本
-
canvas 提供了两种方法来渲染文本:
- fillText(text, x, y [, maxWidth]) // 在指定的(x,y)位置填充指定的文本,绘制的最大宽度是可选的.
- strokeText(text, x, y [, maxWidth]) // 在指定的(x,y)位置绘制文本边框,绘制的最大宽度是可选的.

font :表示文本样式、大小及字体,用 CSS 中指定字体的格式来指定,例如 "10px Arial" 。
textAlign :表示文本对齐方式。可能的值有 "start" 、 "end" 、 "left" 、 "right" 和 "center" 。
textBaseline :表示文本的基线。可能的值有 "top" 、 "hanging" 、 "middle" 、 "alphabetic" 、"ideographic" 和 "bottom" 。
变换
-
通过如下方法来修改变换矩阵 :
- rotate(angle) // 围绕原点旋转图像 angle 弧度 弧度=(Math.PI/180)*角度。

rotate()是以原点(0,0)为旋转点,例子多加了ctx.translate(75,75)即移动改变原点
- scale(scaleX, scaleY) // 缩放图像

scale(scaleX, scaleY) 值即为缩放的倍数
- translate(x, y) :将坐标原点移动到 (x,y)
- transform(m1_1, m1_2, m2_1, m2_2, dx, dy) :直接修改变换矩阵
- setTransform(m1_1, m1_2, m2_1, m2_2, dx, dy) :将变换矩阵重置为默认状态,然后 再调用 transform() 。
绘制图像
-
使用 drawImage()三种不同的参数组合:
- drawImage(image, x, y) // (x,y)坐标绘制图片
- drawImage(image, x, y, w, h); // (x,y)坐标绘制w*h尺寸的图片
- drawImage(image, x, y, w, h, x1, y1, w1, h1); //在w*h原图(x,y)开始在坐标(x1,y1)绘制w1*h1尺寸的图片

阴影
-
通过如下方法来设置阴影 :
- shadowColor = color //用 CSS 颜色格式表示的阴影颜色,默认为黑色
- shadowOffsetX = float // 形状或路径 x 轴方向的阴影偏移量,默认为 0
- shadowOffsetY = float // 形状或路径 y 轴方向的阴影偏移量,默认为 0
- shadowBlur = float // 模糊的像素数,默认 0,即不模糊

渐变
-
通过如下方法来设置渐变 :
- createLinearGradient(x1, y1, x2, y2) //表示渐变的起点 (x1,y1) 与终点 (x2,y2)
- createRadialGradient(x1, y1, r1, x2, y2, r2) // 前三个定义一个以 (x1,y1) 为原点,半径为 r1 的圆,后三个参数则定义另一个以 (x2,y2) 为原点,半径为 r2 的圆
- addColorStop(position, color) // position表示渐变中颜色所在的相对位置,color 参数必须是一个有效的 CSS 颜色值

模式
-
模式其实就是重复的图像,可以用来填充或描边图形
- createPattern(image, type) //type的值包括 "repeat" 、 "repeat-x" 、"repeat-y" 和 "no-repeat" 。

使用图像数据
- 通过如下方法来修改图片数据 :
- getImageData(x, y, w, h) //取得坐标为(x,y)、大小为 w×h 像素的区域的图像数据
- putImageData() // 方法把图像数据绘制到画布上

合成
-
通过如下方法来合成 :
- globalAlpha // 指定所有绘制的透明度。默认值为 0
- globalCompositeOperation //表示后绘制的图形怎样与先绘制的图形结合

实践1-手画时钟
看完前面有关Canvas的语法,接下里就实践画一个时钟,基本可以把前面的知识点串起来。最终效果如下:

- 边框:绘制矩形
- 刻度线:绘制直线
- 原点:绘制圆弧
- 时间点:绘制文本
- 时针/分针/秒针:绘制直线
实现过程:
- 绘制边框
在坐标(450,150)绘制一个150*150的矩形

- 绘制原点
由前面的矩形的坐标和大小就可以得出原点的坐标:
x坐标:起始点X坐标+矩形宽度的一半
y坐标:起始点Y坐标+矩形高度的一半
建议先画原点,以原点为基线画刻度线。


- 绘制刻度线
12个刻度线,根据规律可以分为6组:(12,6)(3,9)(1,2)(4,5)(7,8)(10,11)
举例. 绘制(12,6)的刻度线:
12的X坐标:起始点X坐标+矩形宽度的一半;
12的Y坐标:即起始点Y坐标,可以得到12的起始坐标(525, 150),
但刻度线是有一定长度的,所以把起始坐标向下移动10个像素,最终得到(525, 160)。
6的X坐标:起始点X坐标+矩形宽度的一半;
6的Y坐标:即起始点Y坐标+矩形高度,可以得到6的起始坐标(525, 300),
然后把起始坐标向上移动10个像素,最终得到(525, 290)。
举例. 绘制(1,2)的刻度线:
1的X坐标:起始X坐标+3/4矩形宽度;
1的Y坐标:即起始点Y坐标,可以得到1的起始坐标(572,150),
由于1的坐标有一定倾斜,这里采用的方法X坐标左下移动5个像素,Y坐标向下移动10个像素,最终得到(567, 160)。
2的X坐标:起始X坐标+矩形宽度;
2的Y坐标:即起始点Y坐标+1/4矩形高度,可以得到2的起始坐标(600,182),
然后把起始坐标左下方移动Y坐标10的像素,最终得到(590, 187)。
其他刻度线如同上面推算即可。
- 绘制数字和时针/分针/秒针
如果绘制刻度线顺利完成,到这一步就雷同了,应该没什么难度了~
实践2-动态填充圆弧背景色
完成实践1,应该基本熟悉和掌握Canvas的基本绘制形状的语法,接下来会实现动态填充圆形的背景色的例子,来熟悉Canvas中有点弧和角度的知识点。最终效果如下:

- 最外层的圆弧
- 内层的圆弧
- 填充背景的圆弧
- 白色的圆弧
- 数字
- 滑动条
实现过程:
-
最外层的圆弧/内层的圆弧/白色的圆弧

-
填充背景的圆弧

如何把滑动条选中的值换算为对应的弧度是实现效果的重点:
由于滑动条的最大值为100,圆弧刚好分为4区,即每区占0.25,而每区的弧度为0.5*PI,即滑动条的数组*2=每区的弧度。
从上图可以看到1.5*PI在起始点,如果滑动值为100时,结束角也为1.5*PI,即起始角和结束角一样,就跟我们预期不一致。所以我们的开始角只能为-0.5*PI,这样就达到我们的预期效果了。

- 获取滑动条的值

在获取滑动条值,更新到画布时,记得要清除数字区域,要不就会重叠了。

相关代码
有需要例子代码的同学,可以前往查看
参考
- 《JavaScript高级程序设计(第3版)》
- 《JavaScript权威指南(第6版)》
- MDN web docs
结语
Canvas很强大,能实现各种炫酷的图形效果,本文章只是简单介绍Canvas的基本语法,仅入门篇,后续会推出一些实践的例子。互相学习!一起进步!