javascript - 如何将多维数组映射到 html Canvas 中的矩形网格?

标签 javascript html arrays html5-canvas

有一个大小为 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/

相关文章:

javascript - 使用 Bootstrap 3 选项卡上的复选框

ruby - 使用 delete_at 删除反向数组中的数组元素不起作用

php - Symfony2 MySql : Fetch array and get JSON array without column names

javascript - 从函数返回值并放入单独函数中的变量

javascript - 将焦点样式事件应用于 UL tagit 元素

javascript - 如何关闭 Accordion 菜单的打开部分?

javascript - 自动选择选项和单击时自动完成文本区域值

javascript - 如何用 dom 加载的 JavaScript 替换页面上的所有空 <img src ="">?

python - 如何在不使用循环的情况下为 3D numpy 数组中的每个值做出 N 个随机选择

javascript - Crossfilter reduce 函数