javascript - 如何从转换后的楼层 map 中正确计算坐标?

标签 javascript matrix canvas

我有一个上下文,我在其中绘制了几个矩形。然后上下文应用了转换,将其变成平面图的 3D 幻觉。

Matrix Example

我正在尝试创建一个公式来计算光标悬停在哪个坐标上,而不使用 Path2D。这是因为我需要能够计算它是什么坐标,即使没有绘制图 block ,而是无论如何都在网格上。

转换矩阵有一个...

  • 水平

    • 缩放 1.0
    • 倾斜 0.5
    • (columns * 32) 的移动(列数:6)
  • 垂直

    • 缩放 0.5
    • 倾斜 -1.0
    • 移动 0

Real mouse position in canvas的帮助下的回答,我相信我在正确的道路上,但是,当鼠标向下和向左移动时,尽管在同一列上,列也会减少。向右下行时,尽管在同一行,行也会减少。

const rows = 10;
const columns = 6;

const $coordinate = $("#coordinate");

const $canvas = $("#canvas");

canvas.width = (rows * 32) + (columns * 32);
canvas.height = (rows * 16) + (columns * 16);

const context = $canvas[0].getContext("2d");

context.imageSmoothingEnabled = false;

context.save();
  
context.fillStyle = "white";

context.setTransform(1, 0.5, -1, 0.5, (columns * 32), 0);

// (a) horizontal scaling: 1
// (b) horizontal skewing: 0.5
// (c) vertical skewing: -1
// (d) vertical scaling: 0.5
// (e) horizontal moving: (columns * 32)
// (f) vertical moving: 0

const matrix = {
    vertical: {
    scaling: 1.0,
    skewing: 0.5,
    
    moving: (columns * 32)
  },
  
  horizontal: {
    scaling: 0.5,
    skewing: -1,
    
    moving: 0
  }
};

for(let row = 0; row < rows; row++) {
  for(let column = 0; column < columns; column++) {
    context.rect(row * 32, column * 32, 31.5, 31.5);
  }
}

context.fill();


$canvas.mousemove(function(e) {
    const position = {
    left: e.pageX - $canvas.offset().left,
    top: e.pageY - $canvas.offset().top
  };
  
  const innerPosition = {
    left: position.left * matrix.horizontal.scaling + position.top * matrix.vertical.skewing + matrix.horizontal.moving, 
    top: position.left * matrix.horizontal.skewing + position.top * matrix.vertical.scaling + matrix.vertical.moving
  };

    const coordinate = {
    row: Math.trunc(innerPosition.top / 32),
    column: Math.trunc(innerPosition.left / 32)
  };
  
  $coordinate.html(coordinate.row + "x" + coordinate.column);
});
#canvas {
  background: green;
}

#coordinate {
  position: absolute;

  font-family: Arial, sans-serif;

  font-size: 16px;

  left: 12px;
  top: 12px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<canvas id="canvas"></canvas>

<div id="coordinate">0x0</div>

我没有使用任何框架(但 JQuery 除外,与问题无关)。我怎样才能计算出准确的坐标?

最佳答案

您对 setTransform(a, b, c, d, e, f) 的调用创建了一个 3x3 仿射变换矩阵:

|  a  c  e  |
|  b  d  f  |
|  0  0  1  |

给定您当前的值 (1, 0.5, -1, 0.5, n, 0) 有一个矩阵:

|  0.5     1  -n/2  | 
| -0.5     1  +n/2  |
|    0     0     1  |

将该变换矩阵应用于您的鼠标坐标(需要表示为 1x3 矩阵 [x, y, 1] 应该提供所需的网格坐标:

const rows = 10;
const columns = 6;

const $coordinate = $("#coordinate");

const $canvas = $("#canvas");

canvas.width = (rows * 32) + (columns * 32);
canvas.height = (rows * 16) + (columns * 16);

const context = $canvas[0].getContext("2d");

context.imageSmoothingEnabled = false;

context.save();
  
context.fillStyle = "white";

context.setTransform(1, 0.5, -1, 0.5, (columns * 32), 0);

// (a) horizontal scaling: 1
// (b) horizontal skewing: 0.5
// (c) vertical skewing: -1
// (d) vertical scaling: 0.5
// (e) horizontal moving: (columns * 32)
// (f) vertical moving: 0

for(let row = 0; row < rows; row++) {
  for(let column = 0; column < columns; column++) {
    context.rect(row * 32, column * 32, 31.5, 31.5);
  }
}

context.fill();


$canvas.mousemove(function(e) {
    const position = {
    left: e.pageX - $canvas.offset().left,
    top: e.pageY - $canvas.offset().top
  };
  
  const innerPosition = {
    left: position.left * 0.5 + position.top - (columns * 32) / 2,
    top: position.left * -0.5 + position.top + (columns * 32) / 2
  };

    const coordinate = {
    row: Math.floor(innerPosition.top / 32),
    column: Math.floor(innerPosition.left / 32)
  };
  
  $coordinate.html(coordinate.row + "x" + coordinate.column);
});
#canvas {
  background: green;
}

#coordinate {
  position: absolute;

  font-family: Arial, sans-serif;

  font-size: 16px;

  left: 12px;
  top: 12px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<canvas id="canvas"></canvas>

<div id="coordinate">0x0</div>

关于javascript - 如何从转换后的楼层 map 中正确计算坐标?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63004060/

相关文章:

javascript - 在 VS 中,有没有办法忽略某些 typescript 文件上的错误但仍将它们编译进去?

javascript - 在原型(prototype)代理之上分配一个属性

javascript - 设置数组属性是否符合标准?

c++ - 基于伪代码编写的高斯消元中的std::bad_alloc

javascript - 如何获取div中的所有元素

Python Numpy - 将非常小的数字视为零

arrays - 线性索引,逻辑索引等

javascript - 最快的高斯模糊不起作用

javascript - 下载的 Canvas 显示不同的字体

javascript - 性能 : CSS3 animations vs. HTML5 Canvas