Skip to content

Latest commit

 

History

History
242 lines (173 loc) · 6.23 KB

07.md

File metadata and controls

242 lines (173 loc) · 6.23 KB

二维变换

前言

前提基础是根据 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);
})();

01-07-01

旋转

/**
 * @param {number} angle 设置绘制的旋转角度
 *  范围为 0 - Math.PI * 2
 * */
context.rotate(angle);

注意

  • 旋转设置context.rotate(angle);,是将上下文contextX轴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);
})();

01-07-02

缩放

/**
 * @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倍
})();

01-07-03

形变

/**
 * 形变操作方法,会多次叠加变换
 * @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);
})();

01-07-04