前提基础是根据 canvas
DOM创建的二维上下文
context = canvas.getContext('2d')
以下操作例子 demo 源码地址 https://github.com/chenshenhai/canvas-note/tree/master/demo/basic/2d-deformation
/**
* @param {number} x 设置绘制的 原点坐标X轴坐标
* @param {number} y 设置绘制的 原点坐标Y轴坐标
* */
context.translate(x, y);
- 位移是将上下文
context
原点移动到相对画布canvas
的(x, y)
位置 - 只要设置了
context.translate(x, y);
,那么后续的上下文context
原点坐标(0, 0)
就以相对画布canvas
的(x, y)
坐标未开始。 - 如果设置了
context.translate(x, y);
,后续绘制的context
原点和canvas
原点重合,就需要反向操作一次位移设置重置原点context.translate(-x, -y);
- 如果不重置,每次位移都会相对最初始的位置叠加
<canvas id="canvas-1"></canvas>
(function() {
// 位移 canvas-1
const canvas = document.getElementById('canvas-1');
canvas.width = 400;
canvas.height = 400;
const context = canvas.getContext('2d');
context.fillRect(0, 0, 100, 100);
// 将原点移动到 坐标(200, 200)
context.translate(200, 200);
// 此时原点坐标为(200, 200),画图坐标为(0, 0)是以(200, 200)为相对原点
context.fillRect(0, 0, 100, 100);
})();
/**
* @param {number} angle 设置绘制的旋转角度
* 范围为 0 - Math.PI * 2
* */
context.rotate(angle);
- 旋转设置
context.rotate(angle);
,是将上下文context
的X轴
和Y轴
做相对画布角度为angle
的旋转。 - 旋转后的角度会一致保留,影响下次的,如果下次绘制要以原来画布
canvas
角度为主,非变化后上下文context
角度,就需要自己手动重置画布旋转角度context.rotate(-angle);
- 如果不重置,每次角度设置都会相对最初始的角度叠加
<canvas id="canvas-2"></canvas>
(function() {
// 旋转 canvas-2
const canvas = document.getElementById('canvas-2');
canvas.width = 400;
canvas.height = 400;
const context = canvas.getContext('2d');
// 默认一个黑色正方形
context.fillStyle = '#000';
context.fillRect(100, 100, 100, 100);
// 以原点坐标为(100, 100)
context.translate(100, 100);
// 旋转角度为PI/4,即度数为 45°,
context.rotate(Math.PI / 4);
// 画出一个旋转了的正方形
context.fillStyle = '#ccc';
context.fillRect(0, 0, 100, 100);
})();
/**
* @param {number} x 设置绘制的 X轴缩放比例倍数
* @param {number} y 设置绘制的 Y轴缩放比例倍数
* */
context.scale(x, y);
- 缩放除了长度和宽度缩放,图形本身坐标也缩放
- 缩放的影响也是会叠加的,如果绘制后下次不再影响,需要手动重置
context.scale(1/x, 1/y)
<canvas id="canvas-3"></canvas>
(function() {
// 缩放 canvas-3
const canvas = document.getElementById('canvas-3');
canvas.width = 400;
canvas.height = 400;
const context = canvas.getContext('2d');
// 默认一个黑色正方形
context.fillStyle = '#000';
context.fillRect(100, 100, 100, 100);
context.scale(0.5,0.5);
// 画出一个缩放0.5倍的灰色正方形
context.fillStyle = '#ccc';
context.fillRect(100, 100, 100, 100);
// 会发现(x, y)偏移原点的长度也缩放了0.5倍
})();
/**
* 形变操作方法,会多次叠加变换
* @param {number} m11 X轴方向的缩放倍数
* @param {number} m12 X轴方向的倾斜偏移
* @param {number} m21 Y轴方向的倾斜偏移
* @param {number} m22 Y轴方向的缩放倍数
* @param {number} dx X轴方向位移长度
* @param {number} dy Y轴方向位移长度
* */
context.transform(m11, m12, m21, m22, dx, dy);
/**
* 重置形变操作,设置新的形变操作
* @param {number} m11 X轴方向的缩放倍数
* @param {number} m12 X轴方向的倾斜偏移
* @param {number} m21 Y轴方向的倾斜偏移
* @param {number} m22 Y轴方向的缩放倍数
* @param {number} dx X轴方向位移长度
* @param {number} dy Y轴方向位移长度
* */
context.setTransform(m11, m12, m21, m22, dx, dy);
/**
* 重置形变操作,并用上次的一样的变量调用 context.transform 方法。
* */
context.resetTransform();
- | - | - |
---|---|---|
m11 (X轴缩放倍数默认为1) |
m21 (Y轴方向的倾斜偏移,cos(PI/2)-cos(0)) |
dx (X轴方向位移长度,默认0) |
m12 (X轴方向的倾斜偏移, sin(0)-sin(PI/2)) |
m22 (Y轴缩放倍数默认为1) |
dy (X轴方向位移长度,默认0) |
0 | 0 | 1 |
所以会出现初始矩阵
- | - | - |
---|---|---|
1 | 0 | 0 |
0 | 1 | 0 |
0 | 0 | 1 |
二维图形的形变变化也是矩阵变化
<canvas id="canvas-4"></canvas>
(function() {
// 变形 canvas-4
const canvas = document.getElementById('canvas-4');
canvas.width = 400;
canvas.height = 400;
const context = canvas.getContext('2d');
context.globalAlpha = 0.5;
// 默认一个黑色正方形
context.fillStyle = '#000';
context.fillRect(100, 100, 100, 100);
context.transform(1, Math.sin(Math.PI/4), 0, 1, 0, 0)
// 画出一个变形的正方形
context.fillStyle = 'red';
context.fillRect(100, 100, 100, 100);
context.resetTransform();
context.transform(1, 0, Math.sin(Math.PI/4), 1, 0, 0)
// 画出一个变形的正方形
context.fillStyle = 'blue';
context.fillRect(100, 100, 100, 100);
})();