fillText(text, x, y, maxWidth)strokeText(text, x, y, maxWidth)fontctx.font = 'bold 100px Arial'
textAlignconst canvas = document.getElementById('canvas')
canvas.width = window.innerWidth
canvas.height = window.innerHeight
const ctx = canvas.getContext('2d')
// 辅助线
ctx.strokeStyle = '#999'
ctx.setLineDash([8, 8])
ctx.moveTo(300, 50)
ctx.lineTo(300, 600)
ctx.stroke()
// font 设置字号字体
ctx.font = "24px Arial"
/*
* textAlign
* start:基于文本起始位对齐,默认
* end:基于文本结束位对齐
* left:左对齐
* right:右对齐
* center:居中对齐
* */
ctx.textAlign = 'start'
ctx.fillText('start', 300, 50)
ctx.textAlign = 'end'
ctx.fillText('end', 300, 100)
ctx.textAlign = 'left'
ctx.fillText('left', 300, 150)
ctx.textAlign = 'right'
ctx.fillText('right', 300, 200)
ctx.textAlign = 'center'
ctx.fillText('center', 300, 250)

textBaselineconst canvas = document.getElementById('canvas')
canvas.width = window.innerWidth
canvas.height = window.innerHeight
const ctx = canvas.getContext('2d')
// 辅助线
ctx.strokeStyle = '#999'
ctx.setLineDash([8, 8])
ctx.moveTo(30, 200)
ctx.lineTo(700, 200)
ctx.stroke()
// font 设置字号字体
ctx.font = "24px Arial"
/*
* textBaseline
* top:上对其
* middle:垂直居中对齐
* bottom:下对齐
* hanging:悬挂基线对齐
* alphabatic:标准字母基线对齐,默认
* ideographic:表意文字基线
* */
ctx.textBaseline = 'top'
ctx.fillText('top', 50, 200)
ctx.textBaseline = 'middle'
ctx.fillText('middle', 100, 200)
ctx.textBaseline = 'bottom'
ctx.fillText('bottom', 200, 200)

ctx.measureText(text): 可以让某些元素随文字宽度的变化而变化
const canvas = document.getElementById('canvas')
canvas.width = window.innerWidth
canvas.height = window.innerHeight
const ctx = canvas.getContext('2d')
// 文字内容
const text = 'canvas-------------'
// 矩形左上角位置
const [x, y] = [50, 100]
// 矩形宽度
const height = 60
// 字体
ctx.font = '36px Arial'
// 水平居中
ctx.textAlign = 'center'
// 垂直居中
ctx.textBaseline = 'middle'
// 文字宽度
const width = ctx.measureText(text).width + 36
// 绘制矩形
ctx.strokeRect(x, y, width, height)
// 绘制文字
ctx.fillText(text ,x + width / 2, y + height / 2)
drawImage(image, x, y)drawImage(image, x, y,width,height)drawImage(image, x1, y1,w1,h1,x2,y2,w2,h2)const canvas = document.getElementById('canvas')
canvas.width = window.innerWidth
canvas.height = window.innerHeight
const ctx = canvas.getContext('2d')
const img = new Image()
img.src = 'https://img-blog.csdnimg.cn/2a9fb7b01db54ec48be865fc02902e30.png'
img.onload = function() {
const { width, height } = img
// 绘图 + 移动 drawImage(image, x, y)
// ctx.drawImage(img, 100, 50)
// 绘图 + 移动 + 缩放 drawImage(image, x, y, width, height)
// ctx.drawImage(img, 200, 100, width / 2, height / 2)
// 绘图 + 裁剪 + 移动 + 缩放 drawImage(image, x1, y1, w1, h1, x2, y2, w2, h2) */
ctx.drawImage(img, width / 2, 0, width / 2, height / 2, 100, 50, width / 2, height / 2)
}
以下为上面三种示例的效果展示:



ctx.getImageData(x, y, width, height)获取canvas的ImageData()对象(可以以此原理获取真实图片的数据)
在canvas 中显示ImageData:putImageData(ImageData, dx, dy, dirtyX, dirtyY, dirtyWidth, dirtyHeight)
首先我们要理解 ImageData 中的像素集合和图像栅格的对应关系:
const imgDt = ctx.getImageData(0, 0, 1, 1)
console.log(imgDt)
以下是打印出来的属性:

先从第一行开始,遍历每一列,遍历完成后;进入下一行,遍历每一列,遍历完成后;进入下一行,遍历每一列,遍历完成后…直到遍历完最后一行的最后一列。

下面举两个个简单的例子说明其中的用处:
0.299*r+0.587*g+0.114*b,这是固定不变的const canvas = document.getElementById('canvas')
canvas.width = window.innerWidth
canvas.height = window.innerHeight
const ctx = canvas.getContext('2d')
const img = new Image()
// 需注意的是,这个只能处理本地的图片,线上的图片是不能置灰的
img.src = './images/1.png'
img.onload = draw
function draw() {
// 图像尺寸
const { width, height } = img
// 1.在canvas 中绘制图像
ctx.drawImage(img, 0, 0)
// 2.从canvas 中获取图像的ImageData
const imgDt = ctx.getImageData(0, 0, width, height)
const data = imgDt.data
// 像素遍历
for (let i = 0; i < data.length; i += 4) {
const [r, g, b] = [
data[i],
data[i + 1],
data[i + 2],
]
const lm = 0.299 * r + 0.587 * g + 0.114 * b
data[i] = lm
data[i + 1] = lm
data[i + 2] = lm
}
// 3.在canvas 中显示ImageData
ctx.putImageData(imgDt, 800, 0)
}
这是效果图:

const canvas = document.getElementById('canvas')
canvas.width = window.innerWidth
canvas.height = window.innerHeight
const ctx = canvas.getContext('2d')
const img = new Image()
img.src = './images/1.png'
img.onload = render
// 色块尺寸
let size = 20
function render() {
// 图像尺寸
const { width, height } = img
// *1.在canvas 中绘制图像
ctx.drawImage(img, 0, 0)
// 2.从canvas 中获取图像的ImageData
const imgDt = ctx.getImageData(0, 0, width, height)
const data = imgDt.data
// 行列遍历
// 首先获取一个size的宽高的区域,然后获取左上角的第一个像素,并画一个矩形,然后再每隔一个size遍历一次,以此类推
for (let y = 0; y < height; y += size) {
for (let x = 0; x < width; x += size) {
const ind = (y * width + x) * 4
// [r, g, b]即左上角的点的颜色
const [r, g, b] = [
data[ind],
data[ind + 1],
data[ind + 2],
]
ctx.fillStyle = `rgb(${r},${g},${b})`
ctx.fillRect(x, y, size, size)
}
}
}
可以修改size的大小来控制马赛克的程度。效果如下:

上下文对象的状态就是上下文对象的属性。比如描边颜色,填充颜色,投影,线条样式,变换信息等等。
管理上下文状态的方法:save() restore()
save() 保存当前状态restore()恢复上一次保存的状态const canvas = document.getElementById('canvas')
canvas.width = window.innerWidth
canvas.height = window.innerHeight
const ctx = canvas.getContext('2d')
// 在此时保存了初始颜色#000
ctx.save()
ctx.fillStyle = 'red'
ctx.fillRect(0, 0, 400, 200)
// 在此时还原了上次保存的颜色
ctx.restore()
// 最终这个长方形的颜色是黑色的
ctx.fillRect(0, 0, 300, 200)
最终效果:

const canvas = document.getElementById('canvas')
canvas.width = window.innerWidth
canvas.height = window.innerHeight
const ctx = canvas.getContext('2d')
// 向左以及上都偏移100
ctx.translate(100, 100)
// 整体顺时针旋转 1/4
ctx.rotate(Math.PI / 4)
// 整体缩小0.5倍
ctx.scale(0.5, 0.5)
ctx.fillRect(0, 0, 400, 200)
最终效果:

总结:对canvas 坐标系进行变换后,以后绘制的图形都会受这种变换影响。而我们有时会不想让其它图形受此影响,这样我们就需要用save() 和restore() 将变换方法和绘制图形的方法包裹起来。