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

标签 javascript html arrays html5-canvas

有一个大小为12 x 12的矩形网格,其中每个角都是可单击的,即距12 * 12网格的每个角6 * 3个单元格(单击4个角中的任意一个应选择6 * 3个单元格) )。

我创建了一个尺寸为12 * 12的多维数组,该数组将由0表示。并且根据角落用户选择,相应的6 * 3单元将变为1。
如何通过html canvas显示此概念?即如何以网格形式表示此数组,我也希望选择网格的角,即那些变成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

最佳答案

这就是我的方法:我将使用一维单元格数组。

我还将创建可单击单元格的数组,并在单元格数组中创建索引,并在单击时绘制相应的扩展rect。

请阅读我的代码中的注释。



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在评论:


  我需要所有4个角,但这取决于用户选择要单击哪个角,单击一个角后,他将无法单击另一个角。


在这种情况下,我要在之前的代码中添加一个全局变量let clicked = false;:尚未单击任何角。

当用户单击一个角clicked = true;时,不能单击其他角。

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 - 跨组件发送多个 Prop React

javascript - 用js格式化数字价格样式

javascript - HTML5 移动应用程序在手机屏幕关闭时运行?

javascript - 如果未选中所有复选框,如何取消选中所有复选框?

java - 为什么我的for循环无法与我的数组一起正常工作?

javascript - 如何遍历HTML节点以找到匹配项并从节点获取下一个innerHTML

javascript - 使用相同的类名切换 click()?

javascript - 在没有 setTimeout 的情况下在 componentDidMount() 中操作 DOM

java - 用Java编写二维数组

ios - 使用UiButton重复更改UILabel文本