我怎样才能找出大小,一个矩形必须是,以适应 canvas 内的所有矩形,使用固定数量的矩形?

How can I find out the size, a rect has to be, to fit all rects inside a canvas, using a fixed amout of rects?

上下文

我正在使用 canvas 创建着色像素游戏克隆 我将 canvas 的状态保存在一个如下所示的数组中:

[{\"x\":0,\"y\":0,\"pickedColor\":\"white\",\"colorCode\":null},{\"x\":0,\"y\":1,\"pickedColor\":\"white\",\"colorCode\":null},{\"x\":0,\"y\":2,\"pickedColor\":\"white\",\"colorCode\":null},{\"x\":0,\"y\":3,\"pickedColor\":\"#8bc34a\",\"colorCode\":null},{\"x\":0,\"y\":4,\"pickedColor\":\"#8bc34a\",\"colorCode\":null},{\"x\":0,\"y\":5,\"pickedColor\":\"#8bc34a\",\"colorCode\":null},{\"x\":0,\"y\":6,\"pickedColor\":\"#8bc34a\",\"colorCode\":null},{\"x\":0,\"y\":7,\"pickedColor\":\"#8bc34a\",\"colorCode\":null},{\"x\":0,\"y\":8,\"pickedColor\":\"#8bc34a\",\"colorCode\":null},{\"x\":0,\"y\":9,\"pickedColor\":\"#8bc34a\",\"colorCode\":null},{\"x\":0,\"y\":10,\"pickedColor\":\"#8bc34a\",\"colorCode\":null},{\"x\":0,\"y\":11,\"pickedColor\":\"#8bc34a\",\"colorCode\":null},{\"x\":0,\"y\":12,\"pickedColor\":\"#8bc34a\",\"colorCode\":null},{\"x\":0,\"y\":13,\"pickedColor\":\"white\",\"colorCode\":null},{\"x\":0,\"y\":14,\"pickedColor\":\"white\",\"colorCode\":null},{\"x\":0,\"y\":15,\"pickedColor\":\"white\",\"colorCode\":null},{\"x\":0,\"y\":16,\"pickedColor\":\"white\",\"colorCode\":null},{\"x\":0,\"y\":17,\"pickedColor\":\"white\",\"colorCode\":null},{\"x\":0,\"y\":18,\"pickedColor\":\"white\",\"colorCode\":null},{\"x\":0,\"y\":19,\"pickedColor\":\"white\",\"colorCode\":null},{\"x\":1,\"y\":0,\"pickedColor\":\"white\",\"colorCode\":null},{\"x\":1,\"y\":1,\"pickedColor\":\"white\",\"colorCode\":null},{\"x\":1,\"y\":2,\"pickedColor\":\"white\",\"colorCode\":null},{\"x\":1,\"y\":3,\"pickedColor\":\"white\",\"colorCode\":null},{\"x\":1,\"y\":4,\"pickedColor\":\"white\",\"colorCode\":null},{\"x\":1,\"y\":5,\"pickedColor\":\"white\",\"colorCode\":null},{\"x\":1,\"y\":6,\"pickedColor\":\"white\",\"colorCode\":null},{\"x\":1,\"y\":7,\"pickedColor\":\"white\",\"colorCode\":null},{\"x\":1,\"y\":8,\"pickedColor\":\"white\",\"colorCode\":null},{\"x\":1,\"y\":9,\"pickedColor\":\"white\",\"colorCode\":null},{\"x\":1,\"y\":10,\"pickedColor\":\"white\",\"colorCode\":null},{\"x\":1,\"y\":11,\"pickedColor\":\"white\",\"colorCode\":null},{\"x\":1,\"y\":12,\"pickedColor\":\"#8bc34a\",\"colorCode\":null},{\"x\":1,\"y\":13,\"pickedColor\":\"#8bc34a\",\"colorCode\":null},{\"x\":1,\"y\":14,\"pickedColor\":\"white\",\"colorCode\":null},{\"x\":1,\"y\":15,\"pickedColor\":\"white\",\"colorCode\":null},{\"x\":1,\"y\":16,\"pickedColor\":\"white\",\"colorCode\":null},{\"x\":1,\"y\":17,\"pickedColor\":\"white\",\"colorCode\":null},{\"x\":1,\"y\":18,\"pickedColor\":\"white\",\"colorCode\":null},{\"x\":1,\"y\":19,\"pickedColor\":\"white\",\"colorCode\":null},{\"x\":2,\"y\":0,\"pickedColor\":\"white\",\"colorCode\":null},{\"x\":2,\"y\":1,\"pickedColor\":\"white\",\"colorCode\":null},{\"x\":2,\"y\":2,\"pickedColor\":\"white\",\"colorCode\":null},{\"x\":2,\"y\":3,\"pickedColor\":\"white\",\"colorCode\":null}]

所以每个矩形都有 xy 坐标。 为了在屏幕上绘制矩形,我使用此函数来计算每个“矩形”必须有多大才能容纳在 canvas 范围内:

// width / height comes from props and rectSize comes from props
const [rectCountX, setRectCountX] = useState(Math.floor(width / rectSize));
const [rectCountY, setRectCountY] = useState(Math.floor(height / rectSize));

例如 widthheight 可能是 800600,而 rectSize 可能是 30。 这计算了我可以在每个方向上绘制多少 rects

这是我绘制初始板的方式:

const generateDrawingBoard = (ctx) => {
    // Generate an Array of pixels that have all the things we need to redraw

    for (var i = 0; i < rectCountX; i++) {
      for (var j = 0; j < rectCountY; j++) {
        // this is the quint essence whats saved in a huge array. 1000's of these pixels.
        // With the help of this, we can redraw the whole canvas although canvas has not state or save functionality :)
        const pixel = {
          x: i,
          y: j,
          pickedColor: "white",
          // we don't know the color code yet, we generate that afterwards
          colorCode: null,
        };
        updateBoardData(pixel);
        ctx.fillStyle = "white";
        ctx.strokeRect(i * rectSize, j * rectSize, rectSize, rectSize);
      }
    }
  };

效果很好。用户绘制canvas并存入数据库

问题

我有 pixelArtPreview 个组件。这从数据库中获取数据,对于每个 pixelArt,它将绘制一个矩形,但尺寸较小,因此我可以在页面上放置许多矩形,以向用户展示像素艺术列表。

因此我需要重新计算数组中每个矩形的 rectSize 以适应新的 widthheight。这正是我目前正在努力的地方。

这是我提到的组件:

import { useEffect, useRef, useState } from "react";
import { drawPixelArtFromState } from "../utils/drawPixelArtFromState";

const PixelArtPreview = ({ pixelArt }) => {
  const canvasRef = useRef(null);
  const [ctx, setCtx] = useState(null);
  const [canvas, setCanvas] = useState(null);

  useEffect(() => {
    const canvas = canvasRef.current;
    // This is where I scale the original size
    // the whole pixelArt comes from the database and looks like this (example data):

    // { pixelArtTitle: "some title", pixelArtWidth: 1234, pixelArtHeight: 1234, pixels: [... (the array I shows above with pixels)]}
    canvas.width = pixelArt.pixelArtWidth * 0.5;
    canvas.height = pixelArt.pixelArtHeight * 0.5;
    setCanvas(canvas);
    const context = canvas.getContext("2d");
    setCtx(context);
  }, []);

  useEffect(() => {
    if (!ctx) return;
    drawPixelArtFromState(pixelArt, ctx);
  }, [pixelArt, ctx]);
  return <canvas className="m-4 border-4" ref={canvasRef} />;
};

export default PixelArtPreview;

但是神奇的事情发生在导入的函数中 drawPixelFromState(pixelArt, ctx)

这就是所说的功能(附有我的想法过程的注释):

export const drawPixelArtFromState = (pixelArt, ctx) => {
  // how much pixels have been saved from the original scale when the art has been created
  const canvasCount= JSON.parse(pixelArt.pixels).length;

  // how many pixels we have on X
  const xCount = JSON.parse(pixelArt.pixels)[canvasCount- 1].x;
  // how many pixels we have on Y
  const yCount = JSON.parse(pixelArt.pixels)[canvasCount- 1].y;

  // total pixles (canvas height * canvas.width with the scale of 0.5 so it matches the canvas from the component before)
  // this should give me all the pixels inside the canvas
  const canvasPixelsCount =
    pixelArt.pixelArtWidth * 0.5 * (pixelArt.pixelArtHeight * 0.5);

  // now i try to find out how big each pixel has to be
  const newRectSize = canvasPixelsCount / canvasCount;

  // this is for example 230 rects which can't be I see only 2 rects on the canvas with that much of a rectSize
  console.log(newRectSize);

  // TODO: Parse it instantly where we fetch it
  JSON.parse(pixelArt.pixels).forEach((pixel) => {
    ctx.fillStyle = "white";
    ctx.strokeRect(
      pixel.x * newRectSize,
      pixel.y * newRectSize,
      newRectSize,
      newRectSize
    );

    ctx.fillStyle = pixel.pickedColor;
    ctx.fillRect(
      pixel.x * newRectSize,
      pixel.y * newRectSize,
      newRectSize,
      newRectSize
    );
  });
};

这是该示例在屏幕上的样子(这些是 4 个独立的 canvas,可以在灰色边框上看到 - 我希望在小 canvas 中看到整个像素艺术) :

问题:

我需要找出正确的公式来计算新的 rectSize,这样数组中的所有矩形都可以放入新的 canvas widthheight 中。 这甚至可能吗?还是我需要旧的 rectSize 才能进行计算?

所以 TL;DR:每个矩形 x 有多大,才能容纳 y 中的所有 x 个矩形 canvas。

非常感谢!

对不起大家,经过几个小时的努力终于点击了。 我做的计算:

// now i try to find out how big each pixel has to be
  const newRectSize = canvasPixelsCount / rectCount;

给我像素的面积。但我只需要它的一侧(因为 canvas.fillRect 只关心 x 值并关心该区域)。所以我需要它的平方根。

// now i try to find out how big each pixel has to be
  const newRectSize = Math.sqrt(canvasPixelsCount / rectCount);

现在可以完美运行了。

截图: