【问题标题】:How can I address cells on a canvas grid properly?如何正确处理画布网格上的单元格?
【发布时间】:2019-12-23 21:03:03
【问题描述】:

我想使用 Canvas API 创建一个方形网格,其中每个单元格的底部有一个 1px 边框,右侧有一个 1px 边框。然后整个网格会在其周围绘制一个 1px 的边框,所以它看起来像这样:

一旦网格存在,我想编写一个函数来突出显示给定的单元格。因此,例如调用highlightCell(1, 3, 'green') 会导致:

我认为这很简单,但我正在努力解决这个问题。我的问题是,当我考虑到必须跨越像素线时——从例如 3.5 到 7.5,而不是从 3 到 7 绘制,以免线条模糊——计算坐标的数学似乎不像我那样工作期望在边缘,我得到这样的结果,突出显示没有正确放置。

我的数学是:

  • 我想要一个 700x700 像素的网格,分为 35 个单元格
  • 画布本身为 702x702 像素,以允许每边有 1 像素的边框
  • 单元格的东边界为 1 像素,南边界为 1 像素,因此高亮矩形为 19x19 像素
  • 其中 w 是以 px 为单位的画布宽度,h 是其高度,从 (0.5, 0.5) --> (w + 0.5, 0.5) --> (w + 0.5, h + 0.5) --> (0.5, h + 0.5) --> (0.5, 0.5),为第一个和最后一个像素行以及第一个和最后一个像素列创建一条实线。内部空间为 700x700。
  • 通过在 ??? 处绘制一个 19x19 像素的矩形来突出显示单元格 2,4。我无法在这里找到一个始终有效的值。

我很感激有人解释我做错了什么,因为我确信这是愚蠢的,但我就是看不到它。

Here's the JS Fiddle of my attempt.

【问题讨论】:

  • 必须是画布吗?
  • 是的,这是我想用画布做迷宫的起点,在迷宫打开时擦除网格的一部分。

标签: javascript canvas


【解决方案1】:

我会通过分离逻辑和绘图来做到这一点。例如,拥有一个state 对象和一个drawFrame 函数;像这样:

// setup state
const state = {
  __arr: [],
  __width: 20,
  __height: 20,
  __cell: {
    width: 20,
    height: 20,
  },
  __onUpdate: () => {},
  __calcIndex(x, y) {
    const index = x + y * this.__width;
    if (index >= this.__arr.length || index < 0) {
      throw new Error('Invalid index!');
    }
    return index;
  },
  init(onUpdate) {
    this.__arr = Array(this.__width * this.__height).fill(0);
    this.__onUpdate = onUpdate;
  },
  get(x, y) {
    const index = this.__calcIndex(x, y);
    return this.__arr[index];
  },
  set(x, y, value) {
    const index = this.__calcIndex(x, y);
    this.__arr[index] = value;
    this.__onUpdate();
  },
};

// setup drawing logic
const canvas = document.createElement('canvas');
document.body.append(canvas);
const ctx = canvas.getContext('2d');

const drawFrame = () => {
  const cell = state.__cell;
  ctx.lineWidth = 1;
  ctx.strokeStyle = 'black';
  ctx.fillStyle = 'orangered';
  for (let x = 0; x < state.__width; x++) {
    for (let y = 0; y < state.__width; y++) {
      ctx.strokeRect(cell.width * x, cell.height * y, cell.width, cell.height);
      if (state.get(x, y) !== 0) {
        ctx.fillRect(1 + cell.width * x, 1 + cell.height * y, cell.width-1, cell.height-1);
      }
    }
  }
}

state.init(drawFrame);
canvas.width = state.__width * state.__cell.width;
canvas.height = state.__height * state.__cell.height;
drawFrame();

state.set(2, 4, 1);
state.set(3, 5, 1);
state.set(2, 6, 1);
state.set(7, 4, 1);

【讨论】:

    猜你喜欢
    • 2011-01-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-28
    • 1970-01-01
    • 1970-01-01
    • 2020-10-22
    • 1970-01-01
    相关资源
    最近更新 更多