map-interaction/dist/matrix-demo.js
zhangkun9038@dingtalk.com 41fa1390ae first add
2025-01-30 23:47:14 +08:00

185 lines
5.6 KiB
JavaScript

"use strict";
class Matrix3 {
constructor() {
this.elements = [
1, 0, 0,
0, 1, 0,
0, 0, 1
];
}
multiply(m) {
const a = this.elements;
const b = m.elements;
return new Matrix3().set([
a[0] * b[0] + a[1] * b[3] + a[2] * b[6],
a[0] * b[1] + a[1] * b[4] + a[2] * b[7],
a[0] * b[2] + a[1] * b[5] + a[2] * b[8],
a[3] * b[0] + a[4] * b[3] + a[5] * b[6],
a[3] * b[1] + a[4] * b[4] + a[5] * b[7],
a[3] * b[2] + a[4] * b[5] + a[5] * b[8],
a[6] * b[0] + a[7] * b[3] + a[8] * b[6],
a[6] * b[1] + a[7] * b[4] + a[8] * b[7],
a[6] * b[2] + a[7] * b[5] + a[8] * b[8],
]);
}
translate(tx, ty) {
return this.multiply(new Matrix3().set([
1, 0, tx,
0, 1, ty,
0, 0, 1
]));
}
scale(sx, sy) {
return this.multiply(new Matrix3().set([
sx, 0, 0,
0, sy, 0,
0, 0, 1
]));
}
rotate(angle) {
const c = Math.cos(angle);
const s = Math.sin(angle);
return this.multiply(new Matrix3().set([
c, -s, 0,
s, c, 0,
0, 0, 1
]));
}
set(values) {
this.elements = [...values];
return this;
}
transform(ctx) {
const [a, b, c, d, e, f] = [
this.elements[0],
this.elements[3],
this.elements[1],
this.elements[4],
this.elements[2],
this.elements[5]
];
//console.log('Applying transform:', { a, b, c, d, e, f });
ctx.transform(a, b, c, d, e, f);
}
}
class MapDemo {
constructor() {
this.matrix = new Matrix3();
this.canvas = document.createElement('canvas');
this.ctx = this.canvas.getContext('2d');
this.initCanvas();
this.initControls();
this.draw();
}
initCanvas() {
this.canvas.width = 800;
this.canvas.height = 600;
this.canvas.style.border = '1px solid black';
document.body.appendChild(this.canvas);
const dpr = window.devicePixelRatio || 1;
this.canvas.width *= dpr;
this.canvas.height *= dpr;
this.ctx.scale(dpr, dpr);
}
initControls() {
document.addEventListener('keydown', (e) => {
//console.log('Key pressed:', e.key);
const step = 20;
const scaleFactor = 0.1;
const rotateAngle = Math.PI / 18;
//console.log('Before transform - Matrix:', this.matrix);
switch (e.key.toLowerCase()) {
case 'w':
case 'arrowup':
this.matrix = this.matrix.translate(0, -step);
break;
case 's':
case 'arrowdown':
this.matrix = this.matrix.translate(0, step);
break;
case 'a':
case 'arrowleft':
this.matrix = this.matrix.translate(-step, 0);
break;
case 'd':
case 'arrowright':
this.matrix = this.matrix.translate(step, 0);
break;
case 'z':
this.matrix = this.matrix.scale(1 + scaleFactor, 1 + scaleFactor);
break;
case 'x':
this.matrix = this.matrix.scale(1 - scaleFactor, 1 - scaleFactor);
break;
case 'q':
this.matrix = this.matrix.rotate(-rotateAngle);
break;
case 'e':
this.matrix = this.matrix.rotate(rotateAngle);
break;
}
//console.log('After transform - Matrix:', this.matrix);
e.preventDefault();
this.draw();
});
}
drawGrid() {
const ctx = this.ctx;
ctx.strokeStyle = '#ddd';
ctx.lineWidth = 1;
// 绘制网格
for (let x = -500; x <= 500; x += 50) {
ctx.beginPath();
ctx.moveTo(x, -500);
ctx.lineTo(x, 500);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(-500, x);
ctx.lineTo(500, x);
ctx.stroke();
}
// 绘制坐标轴
ctx.strokeStyle = 'black';
ctx.lineWidth = 2;
ctx.beginPath();
ctx.moveTo(-500, 0);
ctx.lineTo(500, 0);
ctx.moveTo(0, -500);
ctx.lineTo(0, 500);
ctx.stroke();
// 绘制坐标标签
ctx.fillStyle = 'black';
ctx.font = '12px Arial';
for (let x = -500; x <= 500; x += 100) {
ctx.fillText(x.toString(), x + 5, 15);
ctx.fillText(x.toString(), 5, -x + 5);
}
}
draw() {
const ctx = this.ctx;
// 保存当前状态并重置变换
ctx.save();
ctx.setTransform(1, 0, 0, 1, 0, 0);
ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
ctx.restore();
// 应用当前矩阵变换
ctx.save();
this.matrix.transform(ctx);
// 绘制内容
this.drawGrid();
ctx.restore();
}
}
// 初始化代码
document.addEventListener('DOMContentLoaded', () => {
new MapDemo();
const info = document.createElement('div');
info.innerHTML = `
<h3>操作说明:</h3>
<p>平移: W/A/S/D 或 方向键</p>
<p>缩放: Z/X</p>
<p>旋转: Q/E</p>
`;
document.body.appendChild(info);
});
//# sourceMappingURL=matrix-demo.js.map