在不调用本机变换函数的情况下旋转 canvas 上的点

Rotate points on canvas without calling native transform functions

我有一个正方形,其顶点位置(当原点是 canvas 的中心时)如下所示:

let canvasCenter = [canvas.width / 2, canvas.height / 2],
    halfSize = this.size / 2,
    vertexPositions = [
        [halfSize, halfSize],
        [-halfSize, halfSize],
        [halfSize, -halfSize],
        [-halfSize, -halfSize],
    ];

当然,我在坐标系旋转的时候,在每个顶点画一个圆,对我来说是微不足道的。我只是调用本机转换函数:

context.translate(canvasCenter[0], canvasCenter[1]);
context.rotate(this.rotation);

for (let i = 0; i < 4; ++i) {
    let v = vertexPositions[i];

    context.beginPath();
    context.arc(v[0], v[1], 10, 0, 2 * Math.PI);
    context.fill();
}

context.rotate(-this.rotation);
context.translate(-canvasCenter[0], -canvasCenter[1]);

但是,我不只是想绘制顶点。我还想计算每个顶点在 canvas 上旋转和平移时的新位置(例如,判断它们是否在 canvas 的范围内)。我试过使用标准公式,如下所示,但是当我绘制这些顶点时,它给了我一个倾斜的形状,而不是一个旋转的正方形,所以我的计算显然有问题:

let cos = Math.cos(this.rotation),
    sin = Math.sin(this.rotation);

for (let i = 0; i < 4; ++i) {
    let v = vertexPositions[i];

    v[1] = v[1] * cos - v[0] * sin;
    v[0] = v[1] * sin + v[0] * cos;

    v[0] += canvasCenter[0];
    v[1] += canvasCenter[1];
}

请你帮我计算正确的顶点(旋转和平移后)。

原因

v[1] = v[1] * cos - v[0] * sin;
v[0] = v[1] * sin + v[0] * cos;

您在第一行更改 v[1],然后在第二行使用它。因此,您使用转换后的 V[1] 来查找转换后的 v[0],这是不正确的。

解决方案是将变量分开。

const a = v[1] * cos - v[0] * sin;
const b = v[1] * sin + v[0] * cos;
v[0] = b + canvasCenter[0];
v[1] = a + canvasCenter[1];

我称它们为 ab,因为我不确定为什么在 x 坐标中有 v[1] 而在 y 中有 v[0]。标准变换是

const x1 = x * cos - y * sin;
const y1 = x * sin + y * cos;
x = x1 + canvasCenter[0];
y = y1 + canvasCenter[1];