有一个大小为 12 x 12 的矩形网格,其中每个 Angular 都是可点击的,即 12*12 网格的每个 Angular 有 6*3 个单元格(单击任何 4 个 Angular 应选择 6 *3 个单元格)。
我创建了一个大小为 12*12 的多维数组,它将由 0 表示。根据用户选择的 Angular ,相应的 6*3 单元格将变为 1。 如何通过 html canvas 显示这个概念?这就是如何以网格的形式表示这个数组,我还想选择网格的一 Angular ,即那些变成 1 的单元格以不同的颜色表示.
addBed = (x,y) => {let test = Array(12).fill(0).map(x => Array(12).fill(0));
let bedX = 3, bedY = 6; // BED AREA = 6*3
let dx = 1, dy = 1;
let endX = bedX, endY = bedY;
const roomX = 11, roomY = 11
if(x === roomX) {
dx = -1
endX = roomX-bedX
}
if (y === roomY) {
dy = -1
endY = roomY-bedY
}
for(let i = x; dx === 1 ? i < endX : i > endX; i += dx) {
for(let j = y; dy === 1 ? j < endY: j > endY; j += dy) {
test[i][j] = 1;
}
}
console.log(test)
// this.setState({ testMap: test });
}
addBed(0,0); // this will make the first corner to be turned to 1
最佳答案
这就是我的做法:我会使用单元格的一维数组。
我还会创建可点击单元格的数组,其中包含单元格数组中的索引和相应的扩展矩形,以便在单击时绘制。
请阅读我代码中的注释。
let ctx = room.getContext("2d");
let cw = room.width = 300;//the width of the canvas
let ch = room.height = 300;//the height of the canvas
let size = 25;//the size of every cell
let rows = 12;//number of rows
let cols = 12;//number of columns
// initiate the cells array
let cells = new Array(cols*rows);
// the clickable cells: the index in the cells array and the extended rect position (x,y) and size (w,h)
let clickble = [
{index:0, rect:{x:0,y:0,w:size*3,h:size*6}},
{index:11, rect:{x:300-size*3,y:0,w:size*3,h:size*6}},
{index:12*11, rect:{x:0,y:300-size*6,w:size*3,h:size*6}},
{index:12*12-1, rect:{x:300-size*3,y:300-size*6,w:size*3,h:size*6}}
]
// fill the cells array with values
for (y = 0; y <= rows; y++) {
for (x = 0; x < cols; x++) {
let index = x + y * cols;
let cell = {}
cell.x = x*size;
cell.y = y*size;
cells[index] = cell;
}
}
//draw every cell in the grid of cells
cells.forEach((c,i)=>{
ctx.beginPath();
ctx.strokeRect(c.x,c.y,size,size);
})
// mark the cells clickble
clickble.forEach(c=>{ctx.fillRect(cells[c.index].x,cells[c.index].y,size,size);})
// when clicking on the canvas
room.addEventListener("click",(evt)=>{
//get the mouse position
let m = oMousePos(room, evt);
for(let i = 0; i < clickble.length; i++ ){
let cell = cells[clickble[i].index];
ctx.beginPath();
//get the extended rect
ctx.rect(cell.x,cell.y,size,size);
// if the click happened inside one of the clickable cells
if (ctx.isPointInPath(m.x, m.y)){
let rect = clickble[i].rect;
// draw the extended rect
ctx.beginPath();
ctx.fillStyle = "red";
ctx.fillRect(rect.x,rect.y,rect.w,rect.h);
//breack the loop. No need to search further
break;}
}
})
// a function to detect the mouse position on the canvas
function oMousePos(canvas, evt) {
var ClientRect = canvas.getBoundingClientRect();
return {
x: Math.round(evt.clientX - ClientRect.left),
y: Math.round(evt.clientY - ClientRect.top)
}
}
<canvas id="room"></canvas>
更新
OP 正在评论:
I need all the 4 corners, but it depends on the user to choose which corner to be clicked, after clicking one corner, he will not be able to click another corner.
在这种情况下,我在前面的代码中添加了一个全局变量 let clicked = false;
:还没有点击 Angular 。
当用户点击一个 Angular 时clicked = true;
并且不能点击其他 Angular 。
if (ctx.isPointInPath(m.x, m.y)){
clicked = true;
................
因为点击只发生在 if(!clicked)
room.addEventListener("click",(evt)=>{
if(!clicked){...........}
let ctx = room.getContext("2d");
let cw = room.width = 300;
let ch = room.height = 300;
let size = 25;
let rows = 12;
let cols = 12;
let clicked = false;
let cells = new Array(cols*rows)
// the clickables cells: the index in the cells array and the extended rect position (x,y) and size (w,h)
let clickbles = [
{index:0, rect:{x:0,y:0,w:size*3,h:size*6}},
{index:11,rect:{x:300-size*3,y:0,w:size*3,h:size*6}},
{index:12*11,rect:{x:0,y:300-size*6,w:size*3,h:size*6}},
{index:12*12-1,rect:{x:300-size*3,y:300-size*6,w:size*3,h:size*6}}
]
//draw the grid of cells
for (y = 0; y <= rows; y++) {
for (x = 0; x < cols; x++) {
let index = x + y * cols;
let cell = {}
cell.x = x*size;
cell.y = y*size;
cells[index] = cell;
}
}
cells.forEach((c,i)=>{
ctx.beginPath();
ctx.strokeRect(c.x,c.y,size,size);
})
// mark the cells clickbles
clickbles.forEach(c=>{ctx.fillRect(cells[c.index].x,cells[c.index].y,size,size);})
// when clicking on the canvas
room.addEventListener("click",(evt)=>{
if(!clicked){
//get the mouse position
let m = oMousePos(room, evt);
for(let i = 0; i < clickbles.length; i++ ){
let cell = cells[clickbles[i].index];
let rect = clickbles[i].rect;
ctx.beginPath();
ctx.rect(cell.x,cell.y,size,size);
// if the click happened inside one of the clickables cells
if (ctx.isPointInPath(m.x, m.y)){
clicked = true;
// draw the extended rect
ctx.beginPath();
ctx.fillStyle = "red";
ctx.fillRect(rect.x,rect.y,rect.w,rect.h);
//breack the loop. No need to search further
break;}
}
}
})
function oMousePos(canvas, evt) {
var ClientRect = canvas.getBoundingClientRect();
return {
x: Math.round(evt.clientX - ClientRect.left),
y: Math.round(evt.clientY - ClientRect.top)
}
}
<canvas id="room"></canvas>
我希望这就是你要问的
关于javascript - 如何将多维数组映射到 html Canvas 中的矩形网格?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57022032/