Canvas图形变换本质是变换坐标系而非图形本身;平移用translate()移动原点,旋转用rotate()(弧度制)需配合平移实现绕中心旋转,缩放用scale()影响尺寸与线宽,可用setTransform()重置或精确控制变换矩阵。

Canvas 实现图形的平移、旋转与缩放,本质不是“动图形”,而是“动坐标系”——所有后续绘制都自动按新坐标规则执行。掌握这个核心,就能避免常见错位、飞出画布、缩放模糊等问题。
平移:用 translate(x, y) 移动原点
调用 ctx.translate(x, y) 会把当前坐标系原点从 (0, 0) 挪到 (x, y)。之后所有绘图命令(如 fillRect(0, 0, 100, 50))的坐标都以这个新原点为基准。
- 平移是累积的:连续调用
translate(100, 50)和translate(20, 30),等效于一次translate(120, 80) - 若只影响单个图形,建议配对使用
save()和restore()隔离变换 - 示例:让一个矩形在画布中心绘制,可先
translate(canvas.width/2, canvas.height/2),再以(-50, -25)为起点画宽100高50的矩形
旋转:用 rotate(angle) 绕当前原点顺时针转
ctx.rotate(angle) 的 angle 单位是弧度(不是度数),且永远绕当前坐标系原点旋转。默认原点在左上角,所以直接 rotate 会让图形“绕左上角飞出去”。
- 要绕图形自身中心旋转,必须三步配合:先
translate(中心x, 中心y)→ 再rotate(弧度)→ 最后用负值平移回来translate(-中心x, -中心y) - 45° 要写成
Math.PI / 4;90° 是Math.PI / 2 - 文字、阴影、lineWidth 不受 rotate 影响——它们仍按原始方向渲染,旋转后可能倾斜但不自动重排
缩放:用 scale(sx, sy) 改变单位长度
ctx.scale(sx, sy) 表示:原来 1 单位 = 1 像素,现在 1 单位 = sx 像素(水平)或 sy 像素(垂直)。它会同时放大图形尺寸、线宽、字体大小等。
- 缩放后线条变粗、文字模糊?这是正常现象——因为像素被拉伸插值了。解决办法:缩放后手动调细
lineWidth(如 scale(2,2) 后设lineWidth = 0.5),或改用 CSS 缩放整个 canvas 元素(注意鼠标坐标需重新映射) - 想绕某点缩放(比如鼠标位置),同样需要先
translate(点x, 点y)→ 再scale(sx, sy)→ 最后translate(-点x, -点y) - 缩放因子在 0~1 之间是缩小,大于 1 是放大;负值可实现镜像(如
scale(-1, 1)水平翻转)
进阶控制:用 setTransform() 重置矩阵
当变换叠加过多导致混乱,或需要精确构造非标准变形(如斜切、复合旋转+缩放),推荐用 setTransform(a, b, c, d, e, f) 直接覆盖当前矩阵,而不是叠加。
- 最常用重置:回到初始状态就写
setTransform(1, 0, 0, 1, 0, 0) - 绕原点顺时针转 θ:用
setTransform(Math.cos(θ), Math.sin(θ), -Math.sin(θ), Math.cos(θ), 0, 0) - 更安全的做法:借助
DOMMatrix辅助计算,例如:const m = new DOMMatrix().translate(100, 50).rotate(30).scale(1.5);<br>ctx.setTransform(m.a, m.b, m.c, m.d, m.e, m.f);











