js图片旋转之后坐标定位问题

熟悉的陌生人
  • 3
新手上路,请多包涵

旋转

正方形A ===> 宽高200px, 上150px、左150px

白色点 ===> 上200px、左180px (位置不变)

正方形A旋转一定角度(旋转角度不固定本例是45°,旋转是用的css3的rotate按照中心点旋转)

怎么计算白色点距离旋转后B的上边和左边的距离?

求大佬解答谢谢

回复
阅读 1.3k
3 个回答

去了解下极坐标方程,可以视为坐标轴旋转45度,或者白色点逆时针旋转了45度,

计算出白色点的坐标,转换为极坐标,加上45度角,再转回直角坐标即可。

image.png
然后代入两边的X = -100;Y = 100减一下就行

直角转极坐标

function cartesian2Polar(x, y){
    distance = Math.sqrt(x*x + y*y)
    radians = Math.atan2(y,x) //This takes y first
    polarCoor = { distance:distance, radians:radians }
    return polarCoor
}

极坐标转直角坐标直接用
x = r*cos(θ),
y = r*sin(θ),

就行,懒得找库函数代码了

剩下的作业自己独立完成吧

因为数学不太行,不能直接写最终的矩阵,索性连推导过程也写一下。
分解为两步:

  1. 以坐标原点为中心,旋转指定角度;
  2. 平移,使得旋转后的中心点回到原来的位置。

已知旋转的矩阵:

$$ A = \begin{bmatrix} cos(a)&-sin(a)\\ sin(a)&cos(a) \end{bmatrix} $$

假设中心点原来的坐标是

$$ C = \begin{bmatrix}cX\\cY\end{bmatrix} $$

变换后成了

$$ C' = A·C = \begin{bmatrix}cX·cos(a) - cY·sin(a) \\ cX·sin(a) + cY·cos(a)\end{bmatrix} $$

把这个点平移回去,对应的向量

$$ M = C - C' = \begin{bmatrix}cX·(1 - cos(a)) + cY·sin(a) \\ cY·( 1 - cos(a)) - cX·sin(a) \end{bmatrix} $$

把旋转变换的矩阵和这个平移向量合成一个仿射矩阵

$$ S = \begin{bmatrix}A&M\\0&1\end{bmatrix} = \begin{bmatrix} cos(a)&-sin(a)&cX·(1 - cos(a)) + cY·sin(a)\\ sin(a)&cos(a)&cY·( 1 - cos(a)) - cX·sin(a)\\ 0&0&1 \end{bmatrix} $$

然后任意点 P(x, y) 旋转后的坐标

$$ P' = S · \begin{bmatrix}x\\y\\1\end{bmatrix} $$

推导过程应该没啥问题,不过中间的公式可能会写错。

https://codesandbox.io/s/matr...

class Matrix {
  constructor() {
    this.arr = [1, 0, 0, 0, 1, 0, 0, 0, 1];
  }
  translate(x, y) {
    this.arr = this._mult(this.arr, [1, 0, 0, 0, 1, 0, x, y, 1]);
  }
  rotate(angle) {
    const cos = Math.cos(angle);
    const sin = Math.sin(angle);
    this.arr = this._mult(this.arr, [cos, -sin, 0, sin, cos, 0, 0, 0, 1]);
  }
  _mult(a, b) {
    const ret = [];
    for (let y = 0; y < 3; y++) {
      for (let x = 0; x < 3; x++) {
        let sum = 0;
        for (let i = 0; i < 3; i++) {
          sum += b[i + y * 3] * a[x + i * 3];
        }
        ret[x + y * 3] = sum;
      }
    }
    return ret;
  }
}

const reverse = (x, y, cx, cy, angle) => {
  const matrix = new Matrix();
  matrix.translate(cx, cy);
  matrix.rotate(angle);
  const m = matrix.arr;
  x = x - cx;
  y = y - cy;
  const x1 = x * m[0] + y * m[3] + m[6];
  const y1 = x * m[1] + y * m[4] + m[7];
  return [x1, y1];
};

// The next codes use to show the result
const stage = (() => {
  const canvas = document.createElement("canvas");
  const ctx = canvas.getContext("2d");
  [canvas.width, canvas.height] = [800, 600];
  document.body.appendChild(canvas);
  return {
    canvas,
    ctx,
    reset() {
      ctx.setTransform(1, 0, 0, 1, 0, 0);
    },
    line(x1, y1, x2, y2, color) {
      ctx.beginPath();
      ctx.strokeStyle = color;
      ctx.moveTo(x1, y1);
      ctx.lineTo(x2, y2);
      ctx.stroke();
    },
    circle(x, y, radius = 5, color = "black") {
      ctx.beginPath();
      ctx.fillStyle = color;
      ctx.arc(x, y, radius, 0, 2 * Math.PI);
      ctx.fill();
    },
    rect(x, y, w, h, color = "black") {
      ctx.beginPath();
      ctx.strokeStyle = color;
      ctx.strokeWidth = 1;
      ctx.rect((x | 0) + 0.5, (y | 0) + 0.5, w, h);
      ctx.stroke();
    },
    text(str, x, y) {
      ctx.fillStyle = "black";
      ctx.font = "16px arial";
      ctx.fillText(str, x, y);
    },
    applyTranform(m) {
      ctx.setTransform({
        a: m[0],
        b: m[1],
        c: m[3],
        d: m[4],
        e: m[6],
        f: m[7],
      });
    },
  };
})();

const point = { x: 180, y: 200 };
const angle = -Math.PI / 4;
const rect = { x: 150, y: 150, width: 200, height: 200 };

stage.rect(rect.x, rect.y, rect.width, rect.height);
stage.rect(rect.x, rect.y, 20, 20);
stage.circle(point.x, point.y, 5, "blue");

const matrix = new Matrix();
matrix.translate(rect.x + rect.width / 2, rect.y + rect.height / 2);
matrix.rotate(angle);
stage.applyTranform(matrix.arr);
stage.rect(-rect.width / 2, -rect.height / 2, rect.width, rect.height, "blue");
stage.rect(-rect.width / 2, -rect.height / 2, 20, 20, "blue");

const [x, y] = reverse(
  point.x,
  point.y,
  rect.x + rect.width / 2,
  rect.y + rect.height / 2,
  -angle
);
stage.reset();
stage.circle(x, y, 5);
stage.line(x, y, rect.x, y, "red");
stage.line(x, y, x, rect.y, "red");

stage.text(
  (Math.abs(x - rect.x) | 0) + " : " + (Math.abs(y - rect.y) | 0),
  x + 10,
  y + 10
);
你知道吗?

宣传栏