You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JavaScript实现旋转矩阵遇问题:2D旋转时点间距异常缩小

搞定2D旋转矩阵的点间距问题

嘿,我太懂你想亲手啃透旋转底层数学的执念了——直接用Three.js确实省心,但自己撸一遍才是真的把原理刻进脑子里。你遇到的旋转后点间距变小的问题,其实根本不是旋转矩阵本身的锅(2D旋转矩阵是正交变换,本来就不会改变两点间距离),大概率是坐标原点没处理对,或者旋转流程有疏漏,我给你一步步拆解:

最可能的元凶:旋转原点没选对

画布默认的坐标系是左上角为(0,0),但我们旋转图形时,肯定是想绕图形中心(或者画布中心)转对吧?如果直接对画布上的原始坐标应用旋转矩阵,相当于绕左上角旋转——这时候图形会一边转一边往角落跑,视觉上看起来就像“间距变小、在后退”,其实是旋转后的图形在原坐标系下的投影错觉。

正确的旋转流程必须是这三步:

  1. 把所有点的坐标平移到以旋转中心为原点(也就是点坐标减去旋转中心的坐标)
  2. 应用标准的2D旋转矩阵
  3. 把旋转后的坐标平移回原来的坐标系(加上旋转中心的坐标)

别踩“重复旋转”的坑

另外还要注意:一定要保存原始点的副本!如果你的循环是每一帧都执行,却每次都对已经旋转过的点再次应用旋转,虽然旋转矩阵叠加不会缩放,但如果是动画的话,角度累加容易出错(不过你当前的问题不是这个,但提前避坑总是好的)。

给你写个正确的代码示例

假设你的PTS.Demo.pts是原始点数组,旋转中心就是画布中心,代码应该这么写:

// 先备份原始点,避免每次旋转修改原始数据
const originalPoints = [...PTS.Demo.pts];
const sin = Math.sin;
const cos = Math.cos;
// 这里可以改成随时间变化的角度,比如做动画的话ang += 0.01
const rotationAngle = (Math.PI / 180) * 10; // 转10度
const canvasCenter = { x: canvas.width / 2, y: canvas.height / 2 };

for (let p = 0; p < originalPoints.length; p++) {
  const [x, y] = originalPoints[p];
  
  // 步骤1:平移到旋转中心(临时原点)
  const tempX = x - canvasCenter.x;
  const tempY = y - canvasCenter.y;
  
  // 步骤2:应用2D旋转矩阵 [cosθ, -sinθ; sinθ, cosθ]
  const rotatedX = tempX * cos(rotationAngle) - tempY * sin(rotationAngle);
  const rotatedY = tempX * sin(rotationAngle) + tempY * cos(rotationAngle);
  
  // 步骤3:平移回画布坐标系
  PTS.Demo.pts[p][0] = rotatedX + canvasCenter.x;
  PTS.Demo.pts[p][1] = rotatedY + canvasCenter.y;
}

验证方法

你可以先画个正方形的四个顶点测试:用上面的代码旋转后,正方形应该还是正方形,边长完全不变。如果变成菱形或者边长变短,那肯定是坐标平移的步骤漏了。

额外排查点

如果按上面的改了还是有问题,检查下:

  • 有没有在绘制时不小心用了ctx.scale()?缩放会直接改变点间距
  • 画布有没有被拉伸?比如CSS设置的画布尺寸和实际像素尺寸不一致,会导致视觉上的缩放错觉

内容的提问来源于stack exchange,提问作者openquestions

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 12:34:51