translate方法用于移动Canvas坐标系的原点位置,是变换操作中最基础也是最常用的方法。
ctx.translate(x, y)
| 参数 | 类型 | 说明 |
|---|---|---|
| x | number | 水平方向的移动距离 |
| y | number | 垂直方向的移动距离 |
translate方法将坐标系的原点从当前位置移动到(x, y)位置。调用后,所有后续绑制的图形坐标都是相对于新原点的。
const canvas = document.getElementById('canvas')
const ctx = canvas.getContext('2d')
// 默认原点在(0, 0)
ctx.fillRect(0, 0, 50, 50) // 绑制在画布左上角
// 平移原点到(100, 50)
ctx.translate(100, 50)
// 现在原点在(100, 50)
ctx.fillRect(0, 0, 50, 50) // 绑制在画布(100, 50)位置
translate调用会累积,每次调用都在当前原点基础上移动:
ctx.translate(50, 0) // 原点: (50, 0)
ctx.translate(30, 20) // 原点: (80, 20)
ctx.translate(20, 30) // 原点: (100, 50)
使用save和restore可以隔离平移变换:
// 保存当前状态
ctx.save()
// 平移并绑制
ctx.translate(100, 100)
ctx.fillRect(0, 0, 50, 50)
// 恢复状态(平移被撤销)
ctx.restore()
// 此时原点回到(0, 0)
ctx.fillRect(0, 0, 50, 50)
当图形需要绑制在特定位置时,translate可以简化坐标计算:
// 不使用translate
function drawHouse(ctx, x, y) {
ctx.fillRect(x, y, 100, 80)
ctx.beginPath()
ctx.moveTo(x, y)
ctx.lineTo(x + 50, y - 50)
ctx.lineTo(x + 100, y)
ctx.fill()
}
// 使用translate
function drawHouse(ctx) {
ctx.fillRect(0, 0, 100, 80)
ctx.beginPath()
ctx.moveTo(0, 0)
ctx.lineTo(50, -50)
ctx.lineTo(100, 0)
ctx.fill()
}
// 调用时
ctx.save()
ctx.translate(100, 100)
drawHouse(ctx)
ctx.restore()
function drawPattern() {
for (let i = 0; i < 5; i++) {
ctx.save()
ctx.translate(i * 80, 0)
drawShape()
ctx.restore()
}
}
// 绘制一个由多个部分组成的对象
function drawCharacter(x, y) {
ctx.save()
ctx.translate(x, y)
// 身体(相对于角色中心)
ctx.fillRect(-15, -20, 30, 40)
// 头部
ctx.beginPath()
ctx.arc(0, -30, 15, 0, Math.PI * 2)
ctx.fill()
ctx.restore()
}
translate可以使用负值,将原点向左或向上移动:
ctx.translate(-50, -50) // 原点向左上移动
变换累积
// 错误:忘记累积效应
for (let i = 0; i < 5; i++) {
ctx.translate(50, 0)
ctx.fillRect(0, 0, 30, 30)
}
// 结果:矩形位置分别是 50, 100, 150, 200, 250
// 正确:使用save/restore或setTransform
for (let i = 0; i < 5; i++) {
ctx.save()
ctx.translate(50 + i * 50, 0)
ctx.fillRect(0, 0, 30, 30)
ctx.restore()
}
性能考虑
// 频繁save/restore可能影响性能
// 对于简单场景,可以使用setTransform重置
ctx.setTransform(1, 0, 0, 1, x, y) // 直接设置平移
小数坐标
// translate支持小数,但可能导致模糊
ctx.translate(10.5, 20.5)