Canvas 2D 快速上手
使用Canvas进行2D绘制,需要使用Canvas的上下文对象,上下文对象提供了一些方法(API)来绘制图形。
我们不仅可以通过Canvas绘制图形,还可以通过Canvas绘制动画。
静态绘制
绘制直线
首先,我们需要获取到Canvas的上下文对象,这里的上下文可以理解为画笔。我们需要使用坐标系来让画笔在Canvas上绘制图形,Canvas的坐标系是左上角为原点,向右为x轴,向下为y轴。
1 | <canvas id="canvas"></canvas> |
1 | const canvas = document.getElementById('canvas') |
然后使用beginPath()
方法开始绘制路径,使用moveTo()
方法设置路径的起点,使用lineTo()
方法设置路径的终点,最后使用stroke()
方法绘制路径。
其中strokeStyle
是设置路径的颜色。
1 | ctx.beginPath() |
这样,我们就可以在Canvas上绘制一条红色的直线。
绘制折线
我们可以使用lineTo()
方法设置多个路径的终点,然后使用stroke()
方法绘制路径。
1 | ctx.beginPath() |
lineTo()方法可以设置多个路径的终点,然后使用stroke()
方法绘制路径。就可以得到一条折线。
绘制多边形
如果我们将路径的起点和终点连接起来,就可以得到一个多边形,也就是让lineTo()
方法的终点和起点相同。
1 | ctx.beginPath() |
这样,我们就可以在Canvas上绘制一个红色边框的三角形。
我们还可以使用fill()
方法代替stroke()
方法来填充路径,这样就可以得到一个红色填充的三角形。
1 | // ctx.strokeStyle = 'red' // 设置路径的颜色 |
如果我们将stroke()
方法和fill()
方法都使用,那么就会先绘制路径,再填充路径。
假如我们没有将lineTo()
方法的终点和起点连接起来,直接使用fill()
方法,这种方式也可以得到一个多边形,他会自动将路径的起点和终点连接起来。
我们也可以使用closePath()
方法来关闭路径让其自动连接起点和终点,这样也可以得到一个多边形。
1 | ctx.beginPath() |
绘制矩形
矩形是Canvas中最常用的图形之一,我们可以使用rect()
方法来绘制矩形。
1 | ctx.rect(0, 0, 100, 100) // 设置矩形的起点坐标和宽高 |
官方也给我们一个更方便的方式来绘制矩形,那就是使用strokeRect()
方法和fillRect()
方法。
1 | ctx.strokeRect(0, 0, 100, 100) // 设置矩形的起点坐标和宽高 |
使用strokeRect()
方法绘制矩形,会得到一个边框为红色的空心矩形。
使用fillRect()
方法绘制矩形,会得到一个填充为红色的实心矩形。
我们还可以使用clearRect()
方法来清除矩形,这个方法会清除矩形内的所有内容。
1 | ctx.beginPath() |
我们可以看到在红色的矩形内有一个空白矩形,这个矩形就是被清除的矩形。clearRect()
方法可以理解Canvas画布的橡皮擦,可以清除矩形内的所有内容。
绘制圆弧
我们可以通过arc(x, y, r, startAngle, endAngle, anticlockwise)
方法来绘制圆弧,这个方法可以设置圆弧的起点坐标(x, y)、半径(r)、起始角度(startAngle)、结束角度(endAngle)、是否是逆时针(anticlockwise,可选,默认顺时针)。
这里的角度是从x轴正方向开始计算的,顺时针为正,逆时针为负。
1 | ctx.beginPath() |
这里的角度是弧度。弧度是弧长的度量单位,1弧度等于180度,π等于180度,所以Math.PI 就是一个半圆。这里也可以使用角度来设置圆弧,但是需要将角度转换为弧度,角度转弧度的公式是:弧度 = 角度 * Math.PI / 180。
当人我们也可以在半圆画完之后,继续使用lineTo()
方法来绘制路径,这样就可以得到一个不规则的图形。
1 | ctx.beginPath() |
贝塞尔曲线
假如我们想画不规则的曲线,可以使用贝塞尔曲线。贝塞尔曲线有三次贝塞尔曲线和二次贝塞尔曲线。
贝塞尔曲线(读作 [bezje])是一种使用数学方法描述的曲线,被广泛用于计算机图形学和动画中。在矢量图中,贝塞尔曲线用于定义可无限放大的光滑曲线。
贝塞尔曲线由至少两个控制点进行描述。Web 技术中使用的是三次贝塞尔曲线,即使用四个控制点 P0、P1、P2 和 P3 描述的曲线。
二次贝赛尔曲线:quadraticCurveTo(cp1x, cp1y, x, y)
,这个方法可以设置二次贝塞尔曲线的控制点坐标(cp1x, cp1y)和终点坐标(x, y)。
三次贝赛尔曲线:bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y)
,这个方法可以设置三次贝塞尔曲线的控制点坐标(cp1x, cp1y)、控制点坐标(cp2x, cp2y)和终点坐标(x, y)。
绘制文字
我们可以使用fillText(text, x, y, maxWidth)
方法和strokeText(text, x, y, maxWidth)
方法来绘制文字,这个方法可以设置文字内容(text)、文字的起点坐标(x, y)、文字的最大宽度(maxWidth,可选,默认不限制)。
1 | ctx.font = '20px Arial' // 设置文字的字体、大小 和css的font属性一样 |
fillText()
方法会填充文字,strokeText()
方法只会绘制文字的边框。
绘制图片
我们可以使用drawImage(image, dx, dy, dWidth, dHeight)
方法来绘制图片,这个方法可以设置图片的起点坐标(dx, dy)、图片的宽度(dWidth)、图片的高度(dHeight)。
首先我们新建一个图片对象,将其的src设置为图片的地址,然后使用drawImage()
方法来绘制图片。
1 | const img = new Image() |
如果我们的图片过大,在绘制的时候图片还没有加载完成,那么就会绘制失败。
这时候我们可以使用onload
事件来监听图片加载完成,然后在绘制图片。
1 | img.onload = () => { |
如果我们只想展示图片的一部分,可以使用drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight)
方法,这个方法可以设置图片的起点坐标(sx, sy)、图片的宽度(sWidth)、图片的高度(sHeight)、绘制图片的起点坐标(dx, dy)、绘制图片的宽度(dWidth)、绘制图片的高度(dHeight)。
前四个参数是设置图片的起点坐标和宽高,后四个参数是设置绘制图片的起点坐标和宽高也就是在Canvas上的位置和大小。
1 | ctx.drawImage(img, 0, 0, 100, 50, 0, 0, 100, 50) // 设置图片的起点坐标和宽高 绘制图片的起点坐标和宽高 |
样式相关
颜色
在前面我们已经用到过fillStyle
和strokeStyle
这两个属性,这两个属性可以设置填充和描边的颜色。
1 | ctx.fillStyle = 'red' // 设置填充的颜色 |
他们的书写方式和CSS的书写方式一样,都是使用颜色名称或者十六进制颜色值。还可以设置渐变,例如:
1 | ctx.fillStyle = ctx.createLinearGradient(0, 0, 100, 100) // 设置渐变 |
我们还可以使用globalAlpha
属性来设置透明度,这个属性可以设置全局的透明度,也就是所有绘制的内容都会受到这个属性的影响。
1 | ctx.globalAlpha = 0.5 // 设置全局的透明度 |
默认fillStyle
和strokeStyle
的颜色都是黑色,globalAlpha
的透明度是1。如果一个上下文设置过fillStyle
或者strokeStyle
,那么这个上下文的所有绘制都会使用这个颜色,直到设置新的fillStyle
或者strokeStyle
。
线条样式
除了以上颜色相关的属性,我们还可以设置线条样式,例如:
1 | ctx.lineWidth = 10 // 设置线条的宽度 |
我们通常都给一个线条或者一个路径设置线条样式后,还想给另外一个设置样式,那么我们要重新恢复成默认的话是非常麻烦的。
所以我们可以使用save()
和restore()
方法来保存和恢复线条样式。
1 | // 线条1及样式... |
这里的保存和恢复是栈的结构,所以save()
和restore()
方法可以嵌套使用。
并且他们只存储状态,不存储绘制的内容。
变换
我们可以通过translate(x, y)
方法来设置Canvas的坐标系,这个方法可以设置Canvas的起点坐标(x, y)。注意不是移动画板,而是移动Canvas的坐标系。
1 | ctx.translate(100, 100) // 设置Canvas的起点坐标 |
还可以通过rotate(angle)
方法来设置Canvas的旋转角度,这个方法可以设置Canvas的旋转角度(angle)。同样,这个方法也是移动Canvas的坐标系。
1 | ctx.rotate(Math.PI / 2) // 设置Canvas的旋转角度 |
ctx.scale(x, y)
方法可以设置Canvas的缩放比例,这个方法可以设置Canvas的缩放比例(x, y)。
1 | ctx.scale(2, 2) // 设置Canvas的缩放比例 |
通过上述方法变形了一大堆,如果我们想恢复该怎么操作?
同样,我们可以使用save()
和restore()
方法来保存和恢复变换。
1 | ctx.save() // 保存变换 |
总结
Canvas的2D绘制API还有很多,这里只是简单的介绍了一下,如果想要了解更多,可以查看Canvas的官方文档。
Canvas 2D 快速上手