【发布时间】:2021-08-23 10:56:00
【问题描述】:
上下文
我正在使用 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}]
所以每个矩形都有x 和y 坐标。
为了在屏幕上绘制矩形,我使用这个函数来计算每个“矩形”必须有多大才能适合画布边界:
// 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));
例如,width 和 height 可能是 800 和 600,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);
}
}
};
效果很好。用户绘制画布并将其保存到数据库中。
问题
我有一个pixelArtPreview 组件。这会从数据库中获取数据,并且对于每个 pixelArt,它将绘制一个矩形,但尺寸较小,因此我可以在页面上放置许多矩形,以向用户呈现像素艺术列表。
因此我需要重新计算数组中每个矩形的rectSize 以适应新的width 和height。这正是我目前正在努力的地方。
所以这是我提到的组件:
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)
这是所说的功能(用 cmets 我的学习过程是什么):
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 个独立的画布,可以在灰色边框上看到 - 我希望在小画布内看到整个像素艺术):
问题:
我需要找出正确的公式来计算新的rectSize,以便数组中的所有矩形都可以放入新的画布width 和height 中。
这甚至可能吗,还是我需要旧的rectSize 才能进行计算?
所以 TL;DR:每个矩形 x 有多大,以适合 y 画布中的所有 x 矩形。
非常感谢!
【问题讨论】:
标签: javascript math canvas