尝试更改 html 画布上网格中正方形的颜色,但不起作用,也不知道为什么,此时仔细检查了一百次

问题描述 投票:0回答:1

React 中的生命游戏项目,尝试更改单击时的单元格颜色,但它不起作用;我真的不知道为什么不。堆栈溢出似乎希望我更具体,但我实际上不知道问题是什么;它引用我的数组坐标就好了(console.log 已确认),但它告诉我 y 轴 grid[x][y] 上存在类型错误,并且我不知道类型错误是否引用了该索引处的值或者是否尝试使用索引本身;我一直盯着它看,但我无法弄清楚。

我的画布组件(还没有开始将其拆分;还没有评论得很好)

import { useRef, useEffect } from "react";

export default function GameOfLifeCanvas() {
  //! component wide variables
  //! create reference to canvas
  const canvasRef = useRef(null);
  const resolution = 20;
  const width = 400;
  const height = 400;
  const cellTypes = [
    {
      name: "standardCell",
      liveRepresentation: 1,
      color: "",
      behavior: {},
    },
  ];
  //! cellTypeCount is the number of cell types; alive, x, y, z = 4;; + 1 for dead cell
  const cellTypeCount = cellTypes.length + 1;

  //! run when component mounts
  useEffect(() => {
    const columns = width / resolution;
    const rows = height / resolution;
    const canvas = canvasRef.current;
    const context = canvas.getContext("2d");

    let grid = () => {
      //! start with empty array
      const grd = [];
      //! for every row
      for (let i = 0; i < rows; i++) {
        const row = [];
        //! for every column
        for (let ii = 0; ii < columns; ii++) {
          //! push 0 to row
          row.push(Math.floor(Math.random() * cellTypeCount));
        }
        //! push row to columns for every column
        grd.push(row);
      }
      return grd;
    };

    function mouseClick(e) {
      let mouseX, mouseY;

      if (e.offsetX) {
        mouseX = e.offsetX;
        mouseY = e.offsetY;
      } else if (e.layerX) {
        mouseX = e.layerX;
        mouseY = e.layerY;
      }
      let gridX = Math.floor(mouseX / resolution);
      let gridY = Math.floor(mouseY / resolution);
      console.log(gridX, gridY);

      let xy = grid[gridX][gridY];
      if (xy == 0) {
        grid[gridX][gridY] = 1;
        console.log("white");
      } else if (xy === 1) {
        grid[gridX][gridY] = 0;
        console.log("black");
      }

      render(grid);
    }

    canvas.addEventListener("mousedown", mouseClick, false);

    render(grid());
    function render(grid) {
      for (let col = 0; col < grid.length; col++) {
        for (let row = 0; row < grid[col].length; row++) {
          const cell = grid[col][row];

          context.beginPath();
          //   context.rect(
          //     col * resolution,
          //     row * resolution,
          //     resolution,
          //     resolution
          //   );
          //! truthy is black falsy is white
          context.fillStyle = cell ? "black" : "white";
          context.fillRect(
            col * resolution,
            row * resolution,
            resolution,
            resolution
          );
          context.stroke();
        }
      }
      console.log(grid);
    }
  }, []);
  return (
    <>
      <canvas ref={canvasRef} width={width} height={height}></canvas>
    </>
  );
}

javascript html reactjs conways-game-of-life
1个回答
0
投票

为了将网格矩阵初始化为其初始状态,您创建了一个名为 grid 的函数。在第一次渲染中,该函数被调用,并将其返回值传递给渲染函数。

但是,每当用户单击画布并且需要更新网格时,您似乎都在修改函数而不是其返回值

grid[gridX][gridY] = 1;

相反,您应该将网格矩阵存储在变量中,并对其进行操作。

在下面的代码片段中,我将您的

grid
函数放置在全局
create_empty_grid
函数中。在组件的第一次渲染期间,调用此函数并将返回值存储在变量中。在 mousedown 事件中,我们修改变量并使用它重新渲染画布。

import { useRef, useEffect } from "react";

const resolution = 20;
const width = 400;
const height = 400;
const cellTypes = [
  {
    name: "standardCell",
    liveRepresentation: 1,
    color: "",
    behavior: {},
  },
];

const create_empty_grid = () => {
  const columns = width / resolution;
  const rows = height / resolution;

  //! cellTypeCount is the number of cell types; alive, x, y, z = 4;; + 1 for dead cell
  const cellTypeCount = cellTypes.length + 1;

  //! start with empty array
  const grd = [];
  //! for every row
  for (let i = 0; i < rows; i++) {
    const row = [];
    //! for every column
    for (let ii = 0; ii < columns; ii++) {
      //! push 0 to row
      row.push(Math.floor(Math.random() * cellTypeCount));
    }
    //! push row to columns for every column
    grd.push(row);
  }
  return grd;
};

export default function GameOfLifeCanvas() {
  //! component wide variables
  //! create reference to canvas
  const canvasRef = useRef(null);

  //! run when component mounts
  useEffect(() => {
    const canvas = canvasRef.current;
    const context = canvas.getContext("2d");

    let grid = create_empty_grid();

    function mouseClick(e) {
      let mouseX, mouseY;

      if (e.offsetX) {
        mouseX = e.offsetX;
        mouseY = e.offsetY;
      } else if (e.layerX) {
        mouseX = e.layerX;
        mouseY = e.layerY;
      }
      let gridX = Math.floor(mouseX / resolution);
      let gridY = Math.floor(mouseY / resolution);
      console.log(gridX, gridY);

      let xy = grid[gridX][gridY];
      if (xy == 0) {
        grid[gridX][gridY] = 1;
        console.log("white");
      } else if (xy === 1) {
        grid[gridX][gridY] = 0;
        console.log("black");
      }

      render(grid);
    }

    canvas.addEventListener("mousedown", mouseClick, false);

    render(grid);
    function render(grid) {
      for (let col = 0; col < grid.length; col++) {
        for (let row = 0; row < grid[col].length; row++) {
          const cell = grid[col][row];

          context.beginPath();
          //! truthy is black falsy is white
          context.fillStyle = cell ? "black" : "white";
          context.fillRect(
            col * resolution,
            row * resolution,
            resolution,
            resolution
          );
          context.stroke();
        }
      }
      console.log(grid);
    }
  }, []);
  return <canvas ref={canvasRef} width={width} height={height}></canvas>;
}

© www.soinside.com 2019 - 2024. All rights reserved.