diff --git a/learn-canvas/1-create-canvas.ts b/learn-canvas/1-create-canvas.ts
index 95a5ef7..8ad15c8 100644
--- a/learn-canvas/1-create-canvas.ts
+++ b/learn-canvas/1-create-canvas.ts
@@ -4,11 +4,11 @@
*/
import {initCanvas} from './share';
+import {GridSize} from './constant';
function syDraw() {
const drawReact = (ctx: CanvasRenderingContext2D) => {
- ctx.fillStyle = 'blue';
- ctx.fillRect(40, 40, 120, 80);
+ ctx.fillRect(GridSize, GridSize, GridSize * 2, 80);
}
let ctx = initCanvas();
diff --git a/learn-canvas/17-transform2.ts b/learn-canvas/17-transform2.ts
new file mode 100644
index 0000000..05dd3c6
--- /dev/null
+++ b/learn-canvas/17-transform2.ts
@@ -0,0 +1,187 @@
+/**
+ * @author 素燕(我有个公众号:素燕)
+ * @description transform 的理解
+ * scale, rotate, translate (move), and skew the context
+ * https://html.spec.whatwg.org/multipage/canvas.html#dom-context-2d-settransform-dev
+ */
+
+import { initCanvas, SYAxisPos } from './share';
+import { GridSize, TextColor } from './constant';
+
+function syRunDemo() {
+ const drawSkew = (ctx: CanvasRenderingContext2D) => {
+ ctx.save();
+ ctx.strokeStyle = '#1c4587';
+ // ctx.translate(origin.x, origin.y);
+ ctx.setTransform(4, .1, .1, 2, 1, 2);
+ let width = 120;
+ let height = 80;
+ // ctx.strokeRect(-width - 40, -height - 40, width, height);
+ ctx.fillRect(40, 40, width, height);
+ ctx.restore();
+ }
+
+ const move = (ctx: CanvasRenderingContext2D, x: number, y: number) => {
+ ctx.save();
+
+ const drawArrow = (dash: number[]) => {
+ ctx.beginPath();
+ ctx.lineJoin = 'round';
+ ctx.setLineDash(dash);
+ ctx.moveTo(0, 0);
+ ctx.lineTo(GridSize * 3, GridSize * 3);
+ ctx.lineTo(3 * GridSize - GridSize * 0.5, 3*GridSize);
+ ctx.moveTo(GridSize * 3, GridSize * 3);
+ ctx.lineTo(3 * GridSize, 3*GridSize - GridSize * 0.5);
+ ctx.stroke();
+ ctx.closePath();
+ }
+
+ drawArrow([8]);
+
+ ctx.fillStyle = TextColor;
+ ctx.font = '30px Times';
+ ctx.fillText('Translate 位置移动', GridSize * 3, GridSize);
+
+ /**
+ * 平移,相当于修改 e、f 的值,初始矩阵
+ * | a c e |
+ * | b d f |
+ * | 0 0 1 |
+ * x' = ax + cy + e
+ * y' = bx + dy + f
+ *
+ * | 1 0 0 |
+ * | 0 1 0 |
+ * | 0 0 1 |
+ *
+ * | 1 0 40 |
+ * | 0 1 20 |
+ * | 0 0 1 |
+ *
+ * x' = 1*x + 0*y + 40 = x + 40
+ * y' = 0*x + 1*y + 20 = y + 20
+ *
+ */
+ ctx.transform(1, 0, 0, 1, x, y);
+ drawArrow([0]);
+
+ ctx.restore();
+ }
+
+ const scale = (ctx: CanvasRenderingContext2D, x: number, y: number) => {
+ ctx.save();
+ ctx.fillStyle = TextColor;
+ ctx.font = '30px Times';
+ ctx.fillText('Scale 缩放', -GridSize * 3, GridSize);
+
+ ctx.restore();
+ ctx.save();
+ ctx.globalAlpha = 0.2;
+ ctx.fillRect(-GridSize*6, GridSize, GridSize*3, GridSize*2);
+
+ /**
+ * 平移,相当于修改 e、f 的值,初始矩阵
+ * | a c e |
+ * | b d f |
+ * | 0 0 1 |
+ * x' = ax + cy + e
+ * y' = bx + dy + f
+ *
+ * 初始矩阵:
+ * | 1 0 0 |
+ * | 0 1 0 |
+ * | 0 0 1 |
+ *
+ * 缩放后的矩阵
+ * | 4 0 0 |
+ * | 0 2 0 |
+ * | 0 0 1 |
+ *
+ * x' = 4*x + 0*y + 0 = 4x
+ * y' = 0*x + 2*y + 0 = 2y
+ *
+ */
+ ctx.transform(x, 0, 0, y, 0, 0);
+ // 等价于 scale
+ // ctx.scale(x, y)
+ ctx.globalAlpha = 1;
+ // x,y,width,height 均按照缩放比例进行缩放
+ /**
+ * x = x * scaleX
+ * y = y * scaleY
+ * width = width * scaleX
+ * height = height * scaleY
+ */
+ ctx.fillRect(-GridSize*6, GridSize, GridSize*3, GridSize*2);
+
+ ctx.restore();
+ }
+
+ const rotate = (ctx: CanvasRenderingContext2D, angle: number) => {
+ ctx.save();
+ ctx.fillStyle = TextColor;
+ ctx.font = '30px Times';
+ ctx.fillText('Rotate旋转', GridSize * 3, -0.5*GridSize);
+
+ ctx.restore();
+ ctx.save();
+
+ ctx.save();
+
+ const drawArrow = (dash: number[]) => {
+ ctx.beginPath();
+ ctx.lineJoin = 'round';
+ ctx.strokeStyle = '#32C5FF'
+ ctx.setLineDash(dash);
+ ctx.moveTo(0, 0);
+ ctx.lineTo(GridSize * 3, -GridSize * 3);
+ ctx.lineTo(3 * GridSize - GridSize * 0.5, -3*GridSize);
+ ctx.moveTo(GridSize * 3, -GridSize * 3);
+ ctx.lineTo(3 * GridSize, -3*GridSize + GridSize * 0.5);
+ ctx.stroke();
+ ctx.closePath();
+ }
+
+ drawArrow([8]);
+
+ /**
+ * 平移,相当于修改 e、f 的值,初始矩阵
+ * | a c e |
+ * | b d f |
+ * | 0 0 1 |
+ * x' = ax + cy + e
+ * y' = bx + dy + f
+ *
+ * 初始矩阵:
+ * | 1 0 0 |
+ * | 0 1 0 |
+ * | 0 0 1 |
+ *
+ * 缩放后的矩阵
+ * | cosθ -sinθ 0 |
+ * | sinθ cosθ 0 |
+ * | 0 0 1 |
+ *
+ * x' = cos45*x + -sin45*y + 0 = cos45*x - sin45*y
+ * y' = sin45*x + cos45*y + 0 = sin45*x + cos45*y
+ *
+ */
+ ctx.transform(Math.cos(angle), Math.sin(angle), -Math.sin(angle), Math.cos(angle), 0, 0);
+ drawArrow([0]);
+
+ ctx.restore();
+ }
+
+ // 1. 创建 canvas
+ let ctx = initCanvas(SYAxisPos.Center);
+
+ move(ctx, GridSize*2, GridSize);
+ scale(ctx, 0.5, 2);
+ rotate(ctx, 0.4);
+
+ // drawSkew(ctx);
+
+}
+
+syRunDemo();
\ No newline at end of file
diff --git a/learn-canvas/2-shape-rect.ts b/learn-canvas/2-shape-rect.ts
index 551d21d..9ba6473 100644
--- a/learn-canvas/2-shape-rect.ts
+++ b/learn-canvas/2-shape-rect.ts
@@ -4,20 +4,19 @@
*/
import {initCanvas} from './share';
+import {GridSize} from './constant';
function syRunDrawRectDemo() {
const drawReact = (ctx: CanvasRenderingContext2D) => {
- ctx.fillStyle = '#555';
- ctx.fillRect(40, 40, 80, 80);
+ ctx.fillRect(GridSize * 8, GridSize, GridSize * 2, GridSize * 2);
}
const strokeReact = (ctx: CanvasRenderingContext2D) => {
- ctx.strokeStyle = '#555';
- ctx.strokeRect(200, 40, 120, 80);
+ ctx.strokeRect(GridSize * 8, GridSize * 4, GridSize * 2, GridSize);
}
const clearReact = (ctx: CanvasRenderingContext2D) => {
- ctx.clearRect(120, 200, 80, 80);
+ ctx.clearRect(GridSize * 9, GridSize * 1, GridSize * 1, GridSize * 1);
}
const drawColorPannel = (ctx: CanvasRenderingContext2D) => {
@@ -25,7 +24,7 @@ function syRunDrawRectDemo() {
for (let j = 0; j < 6; j++){
ctx.fillStyle = 'rgb(' + Math.floor(255-42.5*i) + ',' +
Math.floor(255-42.5*j) + ',0)';
- ctx.fillRect(j*25, i*25, 25, 25);
+ ctx.fillRect(GridSize + j*GridSize, GridSize + i*GridSize, GridSize, GridSize);
}
}
}
diff --git a/learn-canvas/3-shape-path.ts b/learn-canvas/3-shape-path.ts
index cf065a1..8e0374f 100644
--- a/learn-canvas/3-shape-path.ts
+++ b/learn-canvas/3-shape-path.ts
@@ -4,27 +4,28 @@
*/
import { initCanvas } from './share';
+import {GridSize} from './constant';
function syRunDrawPathDemo() {
-// 绘制一根线
-const drawLine = (ctx: CanvasRenderingContext2D) => {
- // 不调用 beginPath 会有意想不到的结果
- ctx.beginPath();
- // 移动移动到某个位置,可以作为绘图的起点,或者绘制之间不连接的 path
- // 线宽
- ctx.lineWidth = 30;
- // 线顶点的样式 'butt', 'round', 'square'
- // butt 默认样式,不会导致线变长
- // round 圆头,会导致两顶点处的线变长 lineWidth/2
- // square 方头,会导致两顶点处线变长 lineWidth/2
- ctx.lineCap = 'round';
-
- // 在画线的过程中需要注意最终线被画到了那个区域
- ctx.moveTo(80, 120);
- // lineTo 画一条直线
- ctx.lineTo(320, 120);
- ctx.stroke();
-}
+ // 绘制一根线
+ const drawLine = (ctx: CanvasRenderingContext2D) => {
+ // 不调用 beginPath 会有意想不到的结果
+ ctx.beginPath();
+ // 移动移动到某个位置,可以作为绘图的起点,或者绘制之间不连接的 path
+ // 线宽
+ ctx.lineWidth = 20;
+ // 线顶点的样式 'butt', 'round', 'square'
+ // butt 默认样式,不会导致线变长
+ // round 圆头,会导致两顶点处的线变长 lineWidth/2
+ // square 方头,会导致两顶点处线变长 lineWidth/2
+ ctx.lineCap = 'round';
+
+ // 在画线的过程中需要注意最终线被画到了那个区域
+ ctx.moveTo(GridSize * 2, GridSize * 2);
+ // lineTo 画一条直线
+ ctx.lineTo(GridSize * 5, GridSize * 5);
+ ctx.stroke();
+ }
const drawLineJoinStyle = (ctx: CanvasRenderingContext2D) => {
ctx.beginPath();
@@ -42,7 +43,6 @@ const drawLine = (ctx: CanvasRenderingContext2D) => {
// ctx.lineJoin = 'round';
let dashs = ctx.getLineDash();
- console.log('dashs = ', dashs);
ctx.setLineDash([20]);
ctx.stroke();
@@ -68,45 +68,39 @@ const drawLine = (ctx: CanvasRenderingContext2D) => {
ctx.fill();
}
-const drawArcs = (ctx: CanvasRenderingContext2D) => {
- // arc(x, y, radius, startAngle, endAngle, counterclockwise)
- ctx.beginPath();
- // false 顺时针 true 逆时针
- // 弧度和角度
- // 弧度是角的度量单位
- // 弧长等于半径的弧,其所对的圆心角为一弧度
- // 弧度表示:弧长与半径长相等所对应的角度
- // 圆的弧长为 2πr,一个圆的弧度为 2πr / r = 2π,π为圆周率,约为 3.14 2π = 2*3.14=6.28
- // 1π 为 180度,1度 = π / 180, 1弧度 = 180 / π
-
- // 起点为 3 点钟方向
- // 画一弧度
- // ctx.arc(80, 160, 40, 0, 1, false); // Outer circle
- // 画 90 度
- // ctx.arc(80, 160, 40, 0, Math.PI / 180 * 90);
- ctx.arc(80, 160, 40, 0, Math.PI / 180 * 360, false);
-
- // 如何才能让起点为 12 点钟方向
- // ctx.arc(80, 160, 40, Math.PI / 180 * 270, Math.PI / 180 * 180, false);
+ const drawArcs = (ctx: CanvasRenderingContext2D) => {
+ // arc(x, y, radius, startAngle, endAngle, counterclockwise)
+ ctx.beginPath();
+ // false 顺时针 true 逆时针
+ // 弧度和角度
+ // 弧度是角的度量单位
+ // 弧长等于半径的弧,其所对的圆心角为一弧度
+ // 弧度表示:弧长与半径长相等所对应的角度
+ // 圆的弧长为 2πr,一个圆的弧度为 2πr / r = 2π,π为圆周率,约为 3.14 2π = 2*3.14=6.28
+ // 1π 为 180度,1度 = π / 180, 1弧度 = 180 / π
+
+ // 起点为 3 点钟方向
+ // 画一弧度
+ // ctx.arc(80, 160, 40, 0, 1, false); // Outer circle
+ // 画 90 度
+ // ctx.arc(80, 160, 40, 0, Math.PI / 180 * 90);
+ ctx.arc(80, 160, 40, 0, Math.PI / 180 * 360, false);
+
+ // 如何才能让起点为 12 点钟方向
+ // ctx.arc(80, 160, 40, Math.PI / 180 * 270, Math.PI / 180 * 180, false);
- ctx.stroke();
-}
+ ctx.stroke();
+ }
// 1. 创建 canvas
let ctx = initCanvas();
- // 初始化画布的一些属性
- // 设置线的颜色
- ctx.strokeStyle = 'red';
- ctx.fillStyle = '#222';
- ctx.lineWidth = 4;
-
// 在画布中画一个矩形区域
- // drawLine(ctx);
- // drawRect(ctx);
- // drawTriangle(ctx);
+ drawLine(ctx);
+ drawRect(ctx);
+ drawTriangle(ctx);
drawArcs(ctx);
- // drawLineJoinStyle(ctx);
+ drawLineJoinStyle(ctx);
}
syRunDrawPathDemo();
\ No newline at end of file
diff --git a/learn-canvas/constant.ts b/learn-canvas/constant.ts
index 1755a02..a0287c4 100644
--- a/learn-canvas/constant.ts
+++ b/learn-canvas/constant.ts
@@ -5,4 +5,8 @@
export const BgColor = '#222';
export const TextColor = '#fff';
-export const LineColor = '';
\ No newline at end of file
+export const ContentColor = '#C741B1';
+export const StrokeColor = '#FEFF06';
+export const GridLineColor = '#42A0B8';
+export const AxisLineColor = '#fff';
+export const GridSize = 80;
\ No newline at end of file
diff --git a/learn-canvas/index.html b/learn-canvas/index.html
index cdad018..3e4cb07 100644
--- a/learn-canvas/index.html
+++ b/learn-canvas/index.html
@@ -46,8 +46,9 @@
-
+
+