一、基本的画布功能
创建 <canvas>元素时至少要设置 width 和 height 属性,这样才能告诉浏览器在多大面积上绘图。出现在标签包裹里的内容会在浏览器不支持 <canvas>元素时显示。比如:
<canvas id="drawing" width="200" height="200">A drawing of something.</canvas>
1.1 绘图上下文
使用 getContext() 方法可以获取对绘图上下文的引用。对于平面图形,需要给这个方法传入参数“2d”,表示要获取 2D 上下文对象:
const drawing = document.getElementById('drawing')
// 确保浏览器支持 canvas
if (drawing.getContext) {
const canvas = drawing.getContext('2d')
// 其他代码
}
可以使用 toDataURL() 方法导出<canvas>元素上的图像。这个方法接收一个参数:要生成图像的 MIME 类型(与用来创建图形的上下文无关)。例如,从画布上导出一张 PNG格式的图片:
const drawing = document.getElementById('drawing')
// 确保浏览器支持 canvas
if (drawing.getContext) {
// 取得图像的数据 URI
const imageURI = drawing.toDataURL('image/png')
// 显示图片
const image = document.creatElement('img')
image.src = imageURI
document.body.appendChild(image)
}
1.2 填充和描边
填充以指定样式(颜色、渐变或图像)自动填充形状,而描边只为图形边界着色。显示效果取决于两个属性:fillStyle 和 strokeStyle。
这两个属性可以是字符串、渐变对象或图案对象,默认值都为“#000000”。字符串表示颜色值,可以是 CSS 支持的任一格式:名称、十六进制代码、rgb、rgba、hsl 或 hsla。比如:
const drawing = document.getElementById('drawing')
// 确保浏览器支持 canvas
if (drawing.getContext) {
const canvas = drawing.getContext('2d')
canvas.fillStyle = 'red'
canvas.strokeStyle = '#0000ff'
}
1.3 绘制矩形
方法有3个:fillRect()、strokeRect() 和 clearRect()。这些方法都接收4个参数:矩形 x 坐标、矩形 y 坐标、矩形宽度和矩形高度。
1.3.1 fillRect
const drawing = document.getElementById('drawing')
if (drawing.getContext) {
const canvas = drawing.getContext('2d')
// 绘制红色矩形
canvas.fillStyle = '#ff0000'
canvas.fillRect(10, 10, 50, 50)
// 绘制半透明蓝色矩形
canvas.fillStyle = 'rgba(0, 0, 255, 0.5)'
canvas.fillRect(30, 30, 50, 50)
}
绘制效果如下:
1.3.2 strokeRect
const drawing = document.getElementById('drawing')
if (drawing.getContext) {
const canvas = drawing.getContext('2d')
// 绘制红色轮廓的矩形
canvas.strokeStyle = '#ff0000'
canvas.strokeRect(10, 10, 50, 50)
// 绘制半透明蓝色轮廓的矩形
canvas.strokeStyle = 'rgba(0, 0, 255, 0.5)'
canvas.strokeRect(30, 30, 50, 50)
}
绘制效果如下:
描边宽度由 lineWidth 属性控制,它可以是任意整数值。类似地,lineCap 属性控制线条端点的形状[“butt”(平头)、“round”(出圆头)或“square”(出方头)],而 lineJoin 属性控制线条交点的形状[“round”(圆转)、“bevel”(取平)或“miter”(出尖)]。
1.3.3 clearRect
擦除画布中某个区域
const drawing = document.getElementById('drawing')
if (drawing.getContext) {
const canvas = drawing.getContext('2d')
// 绘制红色矩形
canvas.fillStyle = '#ff0000'
canvas.fillRect(10, 10, 50, 50)
// 绘制半透明蓝色矩形
canvas.fillStyle = 'rgba(0, 0, 255, 0.5)'
canvas.fillRect(30, 30, 50, 50)
// 在前两个矩形重叠的区域上擦除一个矩形区域
canvas.clearRect(40, 40, 10, 10)
}
绘制效果如下:
1.4 绘制路径
要绘制路径,必须首先调用 beginPath() 方法以表示要开始绘制新路径。然后,再调用下列方法来绘制路径:
- arc(x, y, radius, startAngle, endAngle, counterclockwise)
- x: x 坐标
- y: y 坐标
- radius: 半径
- startAngle: 起始角度
- endAngle: 结束角度
- counterclockwise: 可选的Boolean值,如果为 true,逆时针绘制圆弧,反之,顺时针绘制
- arcTo(x1, y1, x2, y2, radius): 以给定半径 radius,经由 (x1, y1) 绘制一条从上一点到 (x2, y2) 的弧线
- bezierCurveTo(c1x, c1y, c2x, c2y, x, y): 以 (c1x, c1y) 和 (c2x, c2y) 为控制点,绘制一条从上一点到 (x, y) 的弧线(三次贝塞尔曲线)
- lineTo(x, y): 绘制一条从上一点到 (x, y) 的直线
- moveTo(x, y): 不绘制线条,只把绘制光标移动到 (x, y)
- quadraticCurveTo(cx, cy, x, y): 以 (cx, cy) 为控制点,绘制一条从上一点到 (x, y) 的弧线(二次贝塞尔曲线)
- rect(x, y, width, height): 以给定宽度和高度在坐标点 (x, y) 绘制一个矩形。这个方法与 fillRect() 和 strokeRect() 的区别在于,它创建的是一条路径,而不是独立的图形
创建路径之后,可以使用 closePath() 方法绘制一条返回起点的线
const drawing = document.getElementById('drawing')
if (drawing.getContext) {
const canvas = drawing.getContext('2d')
// 创建路径
canvas.beginPath()
// 绘制外圆
canvas.arc(100, 100, 99, 0, 2 * Math.PI)
// 绘制内圆
canvas.moveTo(194, 100)
canvas.arc(100, 100, 94, 0, 2 * Math.PI)
// 绘制分针
canvas.moveTo(100, 100)
canvas.lineTo(100, 15)
// 绘制时针
canvas.moveTo(100, 100)
canvas.lineTo(35, 100)
// 描画路径
canvas.stroke()
}
绘制效果如下:
1.5 绘制文本
提供了 fillText() 和 strokeText() 两个方法。都接收4个参数:要绘制的字符串、x 坐标、y 坐标和可选的最大像素宽度。而且,这两个方法最终绘制的结果都取决于以下3个属性:
- font: 以 CSS 语法指定的字体样式、大小、字体族等,比如“10px Arial”
- textAlign: 指定文本的对齐方式,可能的值包括“start”、“end”、“left”、“right”和“center”。推荐使用“start”和“end”,不使用“left”和“right”
- textBaseLine: 指定文本的基线,可能的值包括“top”、“hanging”、“middle”、“alphabetic”、“ideographic”和“bottom”
这些属性都有相应的默认值,因此没必要每次绘制文本时都设置它们。fillText() 方法使用 fillStyle 属性绘制文本,而 strokeText() 方法使用 strokeStyle 属性
// 正常
canvas.font = '14px Arial'
canvas.textAlign = 'center'
canvas.textBaseLine = 'middle'
canvas.fillText('12', 100, 20)
// 与开头对齐
canvas.textBaseLine = 'start'
canvas.fillText('12', 100, 40)
// 与末尾对齐
canvas.textBaseLine = 'end'
canvas.fillText('12', 100, 60)
1.6 变换
- rotate(angle): 围绕原点把图像旋转 angle 弧度
- scale(scaleX, scaleY): 通过在 x 轴乘以 scaleX、在 y 轴乘以 scaleY 来缩放图像
- translate(x, y): 把原点移动到(x, y)。执行这个操作后,坐标(0, 0)就会变成(x, y)
- transform(m1_1, m1_2, m2_1, m2_2, dx, dy): 像下面这样通过矩形乘法直接修改矩阵
m1_1 m2_1 dx
m1_2 m2_2 dy
0 0 1 - setTransform(m1_1, m1_2, m2_1, m2_2, dx, dy): 把矩形重置为默认值,再以传入的参数调用 transform()
1.7 阴影
可以根据以下属性值自动为已有形状或路径生成阴影
- shadowColor: CSS 颜色值,表示要绘制的阴影颜色,默认为黑色
- shadowOffsetX: 阴影 x 坐标偏移量
- shadowOffsetY: 阴影 y 坐标偏移量
- shadowBlur: 像素,表示阴影的模糊量
canvas.shadowColor = 'rgba(0, 0, 0, 0.5)'
canvas.shadowOffsetX = 5
canvas.shadowOffsetY = 5
canvas.shadowBlur = 4
1.8 渐变
调用上下文的 createLinearGradient() 方法。这个方法接收4个参数:起点 x 坐标、起点 y 坐标、终点 x 坐标和终点 y 坐标。调用之后,会以指定大小创建一个新的 CanvasGradient 对象并返回实例
有了 gradient 对象后,接下来要使用 addColorStop() 方法为渐变指定色标。这个方法接收两个参数:色标位置和 CSS 颜色字符串。色标位置通过 0 ~ 1 范围内的值表示,0 是第一种颜色,1 是最后一种颜色。比如:
const gradient = canvas.createLinearGradient(30, 30, 70, 70)
gradient.addColorStop(0, 'white')
gradient.addColorStop(1, 'black')