185 lines
5.6 KiB
JavaScript
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
|