javascript - 自定义旋转算法需要可扩展性

标签 javascript math canvas rotation

我正在开发一个 Canvas 库,但我不知道应该如何围绕对象的中心进行旋转。下面是我当前用来渲染它们的函数以及我提供的示例对象。

我觉得有更好的方法来执行 4 个 if 语句,但我无法计算出它的数学原理。目前,我正在获取对象的每个“像素”并将其绕中心旋转,但我看不到扩展的空间。我做错了什么?

//Rendering function
Display.prototype.renderObject = function(object, direction) {
    if (typeof object.rotation !== 'number') object.rotation = 0;
    for (x=0;x<object.bounds.x;x++) {
        for (y=0;y<object.bounds.y;y++) {
            rotation = 45;
            if (x==0 && y==0) rotation += 0;
            if (x==0 && y==1) rotation += 90;
            if (x==1 && y==0) rotation += 270;
            if (x==1 && y==1) rotation += 180;
            display.drawRect(object.color[x][y],
                (display.width/2) - (players[playerIndex].position.x * 16) + (object.position.x * 16) - (object.bounds.x * object.scale)/4 - (object.bounds.x/3 * object.scale * Math.cos((object.rotation+rotation)*(Math.PI/180))),
                (display.height/2) + (players[playerIndex].position.y * 16) - (object.position.y * 16) - (object.bounds.y * object.scale)/4 - (object.bounds.y/3 * object.scale * Math.sin((object.rotation+rotation)*(Math.PI/180))),
                object.scale, object.scale, object.rotation * (direction || 1));
        }
    }
};

// Example object
block = {
    "color": [
        ["#FFF","#CCC"], // Some colors to make
        ["#999","#666"]  // a shaded illusion
    ],
    "position": {
        "x": 0,
        "y": 0
    },
    "bounds": {
        "x": 2, // color[0].length
        "y": 2  // color.length
    },
    "rotation": 0, // 0 to 360
    "scale": 4 // real pixels per object pixel
}

// Example usage
Display.renderObject(block);

- 编辑 -

也许我需要让它计算每个像素的中心坐标在哪里,然后获取从该中心到对象原点的距离以及每个像素偏移的旋转。

如果 x = 0y = 0,则为 +45 度(sin 和 -45)度与 cos+45 度与 sin。如果 (object.bounds.x-1)/2 为我们提供了处理 x 的中心坐标,则 Math.sqrt(Math.pow(x,2)+Math.pow( y,2)) 为我们提供了距离对象中心的色 block 的半径。我不知道该去哪里。

最佳答案

我不是 100% 确定你在问什么,但如果是如何围绕点的中心旋转点,你必须平移所有点,以便你反对旋转如果您愿意,可以以 origin 或点 [0, 0] 为中心。

旋转矩阵总是围绕原点旋转,因此没有办法绕过去(没有双关语)。

因此,在旋转点之前,请计算在旋转之前应用的增量值,旋转然后反转增量并再次应用以获取对象及其相对于原点的偏移。

因此第一步是计算增量,以找出需要将点平移多少才能将它们置于中心。

对于矩形来说很简单:就是它的 x 和 y 位置加上它的宽度和高度的一半:

 deltaX = x + width * 0.5;
 deltaY = y + height * 0.5;

然后您需要将该值减去分数。如何应用此增量取决于您:您可以提前对每个点执行此操作,也可以将其直接注入(inject)公式中。

然后旋转,完成后您只需再次将增量值添加到每个点即可。

这是基于 my article here 的旋转矩阵的较短版本:

var a = rotation * Math.PI / 180;   /// calculate angle once
x -= deltaX;                        /// apply pre-translation
y -= deltaY;

/// rotate and apply post-translation
nx = x *  Math.cos(a) + y * Math.sin(a) + deltaX;
ny = y * -Math.sin(a) + x * Math.cos(a) + deltaY;

您使用的 if 似乎来自使用它来优化 Angular 代码;当你使用 0、90 等时,cos 和 sin 会分别产生 1 和 0。然而,您并没有利用这种优化,因为当这些情况发生时,您可以简单地将 x 替换为 y 等。但是,您将然后绑定(bind)到 x 和 y 位置,所以我不确定您在这里想要实现什么目标..

我建议您在计算和应用 sin/cos 时删除它们 - 您可以缓存 sin 和 cos 并将它们用于所有点:

var angle = rotation * Math.PI / 180;
    sin = Math.sin(angle),
    cos = Math.cos(angle),
    ...calc deltas here...

...enter loop here, then for each point:...
x -= deltaX;
y -= deltaY;
nx = x *  cos + y * sin + deltaX;
ny = y * -sin + x * cos + deltaY;

现在每个点的成本更低,您的计算执行得更快。

希望这有帮助。

关于javascript - 自定义旋转算法需要可扩展性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21081292/

相关文章:

javascript - 如何从html中的url获取json数据

带舍入的 C++ 函数(跨平台)

javascript - 如何在 brython 中绘制 Canvas ?

javascript - 提高 Canvas 中矩形绕圆移动的速度

javascript - 如何调试 Javascript 错误?

javascript - 一个跨度内的按钮,都有一个事件。如果我单击按钮,跨度事件也会启动

javascript - extjs - 点击事件的多个委托(delegate)

matlab - 如何处理上溢和下溢?

ios - 更新陀螺仪相对于预定义方向的旋转数据?

javascript - 使用箭头绑定(bind)在 Canvas 上定位 Div