我使用javascript创建了一些形状(pacman看对象),我使用画布内置的矩阵变换为它们制作动画。对象可以在四个方向上移动(向左,向右,向上,向下),并且形状基本上将在画布上来回移动,直到按下另一个按钮。当我使用内置的canvas转换函数时,这些功能正常工作;然而,当我尝试实现自己的转换时,一些奇怪的事情正在发生。
在正常情况下(当我使用画布变换时)我首先将画布原点转换为正在旋转的点,围绕此" new"进行旋转。原点,然后将原点翻译回原来的版本,见以下代码:
function renderContent(pm) {
var t = new Transform();
context.save();
context.beginPath();
context.fillStyle = "Yellow";
context.strokeStyle = "Yellow";
context.save();
var tCopy1 = t;
context.translate(pm.posX, pm.posY);
context.rotate(-pm.direction * Math.PI / 180);
context.translate(-pm.posX, -pm.posY);
context.arc(pm.posX, pm.posY, pm.size, (pm.startAngle) * Math.PI, (pm.endAngle) * Math.PI);
context.lineTo(pm.posX, pm.posY);
context.stroke();
context.fill();
var m = t.m;
t.transform(m);
context.restore();
context.restore();
}
为了实现我自己的转换,我有一个包含以下函数的转换类:
function Transform() {
this.identity();
}
Transform.prototype.identity = function () {
this.m = [1, 0, 0, 1, 0, 0];
};
Transform.prototype.rotate = function (rad) {
var c = Math.cos(rad);
var s = Math.sin(rad);
var m11 = this.m[0] * c + this.m[2] * s;
var m12 = this.m[1] * c + this.m[3] * s;
var m21 = this.m[0] * -s + this.m[2] * c;
var m22 = this.m[1] * -s + this.m[3] * c;
this.m[0] = m11;
this.m[1] = m12;
this.m[2] = m21;
this.m[3] = m22;
};
Transform.prototype.translate = function (x, y) {
this.m[4] += this.m[0] * x + this.m[2] * y;
this.m[5] += this.m[1] * x + this.m[3] * y;
};
Transform.prototype.scale = function (sx, sy) {
this.m[0] *= sx;
this.m[1] *= sx;
this.m[2] *= sy;
this.m[3] *= sy;
};
在renderContext()函数中,我使用了与translate()和rotate()基本相同的函数调用(这使得pacman对象在它们到达画布边框时可以转身)但是出于某种原因,通过我的实现,物体不转(180度)。
对于我的转换,我基本上实例化一个转换对象,调用对象上的转换操作,制作转换矩阵的副本,然后使用转换中的结果矩阵设置画布: E.G:
var t = new Transform();
var tCopy1 = t;
tCopy1.translate(pm.posX, pm.posY);
t.rotate(-pm.direction * Math.PI / 180);
t.translate(-pm.posX, -pm.posY);
...
var m = t.m;
t.transform(m);
这可能需要查看很多代码,但是实现旋转矩阵转换的正确方法是什么(因为canvas.rotate()正在运行)?
答案 0 :(得分:1)
这是pacman绕方向角顺时针旋转。
<强>更新强>
现在显示紫色的变换错误。旋转看起来正确但翻译已关闭。
更新2
我认为我之前的测试很糟糕。变换看起来很好,只有一些微调to_radians。新测试显示上下文翻译/轮换后跟Transform
类。
var can = document.getElementById('can');
var context = can.getContext('2d');
var to_rad = Math.PI / 180; // to radians
function main() {
context.fillStyle="black";
context.fillRect(0, 0, can.width, can.height);
var pm = {
direction: 0,
posX: 50,
posY: 100,
size: 20,
startAngle: 45,
endAngle: 315
};
var i = 0;
function loopTest() {
pm.direction = i * 90;
pm.posX = 50 * (i+1);
renderContent(pm);
setTimeout(function(){
renderContent2(pm);
}, 1000);
i++;
if (i < 4) {
setTimeout(loopTest, 2000);
}
}
loopTest();
}
function renderContent(pm) {
context.save();
context.beginPath();
context.fillStyle = "Yellow";
context.strokeStyle = "Yellow";
context.translate(pm.posX, pm.posY);
context.rotate(pm.direction * to_rad);
context.translate(-pm.posX, -pm.posY);
context.arc(pm.posX, pm.posY, pm.size, pm.startAngle * to_rad, pm.endAngle * to_rad);
context.lineTo(pm.posX, pm.posY);
context.stroke();
context.fill();
context.fillStyle="red";
context.font="16px Arial";
context.textAlign="center";
context.fillText(pm.direction, pm.posX,pm.posY+pm.size);
context.restore();
}
function renderContent2(pm) {
var t = new Transform();
context.save();
context.beginPath();
context.fillStyle = "#990099";
context.strokeStyle = "#990099";
t.translate(pm.posX, pm.posY);
t.rotate(pm.direction * to_rad);
t.translate(-pm.posX, -pm.posY);
context.transform.apply(context, t.m);
context.arc(pm.posX, pm.posY, pm.size, pm.startAngle * to_rad, pm.endAngle * to_rad);
context.lineTo(pm.posX, pm.posY);
context.stroke();
context.fill();
context.fillStyle="White";
context.font="16px Arial";
context.textAlign="center";
context.fillText(pm.direction, pm.posX,pm.posY+pm.size);
context.restore();
}
function Transform() {
this.identity();
}
Transform.prototype.identity = function () {
this.m = [1, 0, 0, 1, 0, 0];
};
Transform.prototype.rotate = function (rad) {
var c = Math.cos(rad);
var s = Math.sin(rad);
var m11 = this.m[0] * c + this.m[2] * s;
var m12 = this.m[1] * c + this.m[3] * s;
var m21 = this.m[0] * -s + this.m[2] * c;
var m22 = this.m[1] * -s + this.m[3] * c;
this.m[0] = m11;
this.m[1] = m12;
this.m[2] = m21;
this.m[3] = m22;
};
Transform.prototype.translate = function (x, y) {
this.m[4] += this.m[0] * x + this.m[2] * y;
this.m[5] += this.m[1] * x + this.m[3] * y;
};
Transform.prototype.scale = function (sx, sy) {
this.m[0] *= sx;
this.m[1] *= sx;
this.m[2] *= sy;
this.m[3] *= sy;
};
main();
canvas {
border:3px solid red;
}
<canvas id="can" width="300" height="200"></canvas>