
4.2 绘制图形
本节将介绍一些基本图形的绘制,包括矩形、直线、圆形、曲线等形状或路径。
4.2.1 矩形

视频讲解
canvas仅支持一种原生的图形绘制:矩形。绘制其他图形都至少需要生成一条路径。不过,拥有众多路径生成的方法,绘制复杂图形也很轻松。
canvas提供了三种方法绘制矩形:
fillRect(x, y, width, height):绘制一个填充的矩形。
strokeRect(x, y, width, height):绘制一个矩形的边框。
clearRect(x, y, width, height):清除指定矩形区域,让清除部分完全透明。
参数说明如下:
x:矩形左上角的x坐标。
y:矩形左上角的y坐标。
width:矩形的宽度,以像素为单位。
height:矩形的高度,以像素为单位。
【示例】下面示例分别使用上述3种方法绘制了3个嵌套的矩形,预览效果如图4.4所示。


图4.4 绘制矩形
在上面代码中,fillRect()方法绘制了一个边长为100px的黑色正方形。clearRect()方法从正方形的中心开始擦除了一个60px×60px的正方形,接着strokeRect()在清除区域内生成一个50px×50px的正方形边框。
提示:不同于路径函数,以上3个函数绘制之后,会马上显现在canvas上,即时生效。
4.2.2 路径

视频讲解
图形的基本元素是路径。路径是通过不同颜色和宽度的线段或曲线相连形成的不同形状的点的集合。一个路径,甚至一个子路径,都是闭合的。使用路径绘制图形的步骤如下:
第1步,创建路径起始点。
第2步,使用画图命令绘制路径。
第3步,把路径封闭。
第4步,生成路径之后,可以通过描边或填充路径区域来渲染图形。
需要调用的方法说明如下:
beginPath():开始路径。新建一条路径,生成之后,图形绘制命令被指向到路径上生成路径。
closePath():闭合路径。闭合路径之后图形绘制命令又重新指向到上下文中。
stroke():描边路径。通过线条来绘制图形轮廓。
fill():填充路径。通过填充路径的内容区域生成实心的图形。
提示:生成路径的第一步是调用beginPath()方法。每次调用这个方法之后,表示开始重新绘制新的图形。闭合路径closePath()不是必需的。当调用fill()方法时,所有没有闭合的形状都会自动闭合,所以不需要调用closePath()方法,但是调用stroke()时不会自动闭合。
【示例1】下面示例绘制一个三角形,效果如图4.5所示。代码仅提供绘图函数draw(),完整代码可以参考4.2.1节示例,后面各节示例类似。

使用moveTo(x, y)方法可以将笔触移动到指定的坐标x和y上。当初始化canvas,或者调用beginPath()方法后,通常会使用moveTo()方法重新设置起点。
【示例2】用户可以使用moveTo()方法绘制一些不连续的路径。下面示例绘制一个笑脸图形,效果如图4.6所示。

图4.5 绘制三角形

图4.6 绘制笑脸

上面代码中使用到arc()方法,调用它可以绘制圆形,在后面小节中将详细说明。
4.2.3 直线

视频讲解
使用lineTo()方法可以绘制直线,用法如下所示:
lineTo(x,y)
参数x和y分别表示终点位置的x坐标和y坐标。lineTo(x, y)将绘制一条从当前位置到指定(x, y)位置的直线。
【示例】下面示例将绘制两个三角形,一个是填充的,另一个是描边的,效果如图4.7所示。

在上面示例代码中,从调用beginPath()方法准备绘制一个新的形状路径开始,使用moveTo()方法移动到目标位,两条线段绘制后构成三角形的两条边。当路径使用填充(filled)时,路径自动闭合;而使用描边(stroked)则不会闭合路径。如果没有添加闭合路径closePath()到描边三角形中,则只绘制了两条线段,并不是一个完整的三角形。

图4.7 绘制三角形
4.2.4 圆弧

视频讲解
使用arc()方法可以绘制弧或者圆,用法如下所示:
context.arc(x, y, r, sAngle, eAngle, counterclockwise);
参数说明如下:
x:圆心的x坐标。
y:圆心的y坐标。
r:圆的半径。
sAngle:起始角,以弧度计。(提示:弧的圆形的三点钟位置是0°。)
eAngle:结束角,以弧度计。
counterclockwise:可选参数,定义绘图方向。false为顺时针,为默认值,true为逆时针。
如果使用arc()创建圆,可以把起始角设置为0,结束角设置为2*Math.PI。
【示例1】下面示例绘制了12个不同的角度以及填充的圆弧。主要使用两个for循环,生成圆弧的行列(x,y)坐标。每一段圆弧的开始都调用beginPath()方法。代码中,每个圆弧的参数都是可变的,(x,y)坐标是可变的,半径(radius)和开始角度(startAngle)都是固定的。结束角度(endAngle)在第一列开始时是180°(半圆),然后每列增加90°。最后一列形成一个完整的圆。效果如图4.8所示。

在上面代码中,“var anticlockwise= i%2==0 ? false : true;”语句作用于第一、三行是顺时针的圆弧,anticlockwise作用于二、四行为逆时针圆弧。if语句让一、二行描边圆弧,下面两行填充路径。
使用arcTo()方法可以绘制曲线,该方法是lineTo()的曲线版,它能够创建两条切线之间的弧或曲线。用法如下所示:
context.arcTo(x1,y1,x2,y2,r);
参数说明如下:
x1:弧的起点的x坐标。
y1:弧的起点的y坐标。
x2:弧的终点的x坐标。
y2:弧的终点的y坐标。
r:弧的半径。
【示例2】本例使用lineTo()和arcTo()方法绘制直线和曲线,然后连成圆角弧线,效果如图4.9所示。


图4.8 绘制圆和弧

图4.9 绘制圆角弧线
4.2.5 二次方曲线

视频讲解
使用quadraticCurveTo()方法可以绘制二次方贝塞尔曲线,用法如下。
context.quadraticCurveTo(cpx,cpy,x,y);
参数说明如下:
cpx:贝塞尔控制点的x坐标。
cpy:贝塞尔控制点的y坐标。
x:结束点的x坐标。
y:结束点的y坐标。
二次方贝塞尔曲线需要两个点。第一个点是用于二次贝塞尔计算中的控制点,第二个点是曲线的结束点。曲线的开始点是当前路径中最后一个点。如果路径不存在,需要使用beginPath()和moveTo()方法来定义开始点,演示说明如图4.10所示。

图4.10 二次方贝塞尔曲线演示示意图
操作步骤如下:
第1步,确定开始点,如moveTo(20,20)。
第2步,定义控制点,如quadraticCurveTo(20,100,x,y)。
第3步,定义结束点,如quadraticCurveTo(20,100,200,20)。
【示例1】下面示例先绘制一条二次方贝塞尔曲线,再绘制出其控制点和控制线。

在浏览器中的运行效果如图4.11所示,其中曲线即为二次方贝塞尔曲线,两条直线为控制线,两直线的交点即为曲线的控制点。

图4.11 二次方贝塞尔曲线及其控制点
【示例2】下面示例组合直线和二次方曲线,封装了一个圆角矩形函数,使用它可以绘制圆角矩形图形,效果如图4.12所示。

图4.12 绘制圆角矩形
具体代码解析请扫码学习。

线上阅读
4.2.6 三次方曲线

视频讲解
使用bezierCurveTo()方法可以绘制三次方贝塞尔曲线,用法如下。
context.bezierCurveTo(cp1x,cp1y,cp2x,cp2y,x,y);
参数说明如下:
cp1x:第一个贝塞尔控制点的x坐标。
cp1y:第一个贝塞尔控制点的y坐标。
cp2x:第二个贝塞尔控制点的x坐标。
cp2y:第二个贝塞尔控制点的y坐标。
x:结束点的x坐标。
y:结束点的y坐标。
三次方贝塞尔曲线需要三个点,前两个点是用于三次贝塞尔计算中的控制点,第三个点是曲线的结束点。曲线的开始点是当前路径中最后一个点,如果路径不存在,需要使用beginPath()和moveTo()方法来定义开始点,演示说明如图4.13所示。
操作步骤如下:
第1步,确定开始点,如moveTo(20,20)。
第2步,定义第一个控制点,如bezierCurveTo(20, 100, cp2x, cp2y, x, y)。
第3步,定义第二个控制点,如bezierCurveTo(20,100,200,100,x,y)。
第4步,定义结束点,如bezierCurveTo(20,100,200,100,200,20)。
【示例】下面示例绘制了一条三次方贝塞尔曲线,还绘制出了两个控制点和两条控制线。

在浏览器中的预览效果如图4.14所示,其中曲线即为三次方贝塞尔曲线,两条直线为控制线,两直线上方的端点即为曲线的控制点。

图4.13 三次方贝塞尔曲线演示示意图

图4.14 三次方贝塞尔曲线