如何在JavaScript Canvas中偏移网格 解决康威生命游戏边界显示问题
康威生命游戏网格偏移实现方案
你可以通过全局坐标偏移的方式实现需求,无需改动数组的存储结构,就能让arry[10][10]对齐屏幕左上角,同时隐藏边缘的红色边界线。修改要点如下:
- 定义全局偏移常量统一管理偏移数值
- 网格、细胞绘制时统一减去偏移像素值,实现视觉上的平移
- 点击事件坐标映射时反向叠加偏移量,保证点击位置和数组索引正确对应
修改后的完整代码如下:
const canvas = document.getElementById('canvas'); const ctx = canvas.getContext('2d'); var cellSize = 16; var gridColor = "#4a4a4a"; // 全局偏移量,对应10个单元格 const OFFSET = 10; //set canvas resolution to screen resolution ctx.canvas.width = window.innerWidth; ctx.canvas.height = window.innerHeight; var cellsInRow = parseInt(ctx.canvas.height/cellSize)+20; var cellsInCollum = parseInt(ctx.canvas.width/cellSize)+20; //create array let arry = []; for(var i = 0; i < cellsInRow; i++){ arry[i] = []; for(var j = 0; j < cellsInCollum; j++){ arry[i][j] = 0; } } let arryOld = arry.map(row => [...row]); //draw on canvas setInterval(drawCells, 1); canvasBackground(); canvasGrid(); function getCursonPointer(canvas, event){ const rect = canvas.getBoundingClientRect(); const x = event.clientX - rect.left; const y = event.clientY - rect.top; console.log("x: " + x + " y: " + y); setCell(x, y); } canvas.addEventListener('mousedown', function(e){ getCursonPointer(canvas, e); }); //set cell in array function setCell(x, y){ // 点击坐标叠加偏移量,对应正确的数组索引 const offsetX = x + OFFSET * cellSize; const offsetY = y + OFFSET * cellSize; for(var i = 0; i < cellsInRow; i++){ for(var j = 0; j < cellsInCollum; j++){ if((offsetY >= (i*cellSize) && offsetY <= ((i*cellSize)+cellSize-1)) &&(offsetX >= (j*cellSize) && offsetX <= ((j*cellSize)+cellSize-1))){ arry[i][j] = arry[i][j] == 0 ? 1 : 0; } } } } function drawCells(){ for(var i = 0; i < cellsInRow; i++){ for(var j = 0; j < cellsInCollum; j++){ // 绘制坐标减去偏移量,实现网格平移 const posX = (j - OFFSET) * cellSize; const posY = (i - OFFSET) * cellSize; if(arry[i][j] == 1){ ctx.clearRect(posX +1, posY +1, cellSize-2, cellSize-2); ctx.fillStyle = "white"; ctx.font = "8px Arial"; ctx.fillText(i, posX + 4, posY + (cellSize/2)); }else{ ctx.fillStyle ="black"; ctx.fillRect(posX +1, posY +1, cellSize-2, cellSize-2); } } } } //draw background function canvasBackground(){ ctx.fillStyle = 'black'; ctx.fillRect(0, 0, canvas.width, canvas.height); } //draw the grid function canvasGrid(){ for(var i = 0; i < cellsInRow; i++){ const posY = (i - OFFSET) * cellSize; if(i == 10 || i == cellsInRow-10){ ctx.strokeStyle = "red"; } else if(i%10 == 0){ ctx.strokeStyle = "white"; }else{ ctx.strokeStyle = gridColor; } ctx.beginPath(); ctx.moveTo(0, posY); ctx.lineTo(canvas.width, posY); ctx.lineWidth = 1; ctx.stroke(); for(var j = 0; j < cellsInCollum; j++){ const posX = (j - OFFSET) * cellSize; if(j == 10 || j == cellsInCollum-10){ ctx.strokeStyle = "red"; } else if(j%10 == 0){ ctx.strokeStyle = "white"; }else{ ctx.strokeStyle = gridColor; } ctx.beginPath(); ctx.moveTo(posX, 0); ctx.lineTo(posX, canvas.height); ctx.lineWidth = 1; ctx.stroke(); } } }
修改后网格的第10行第10列会刚好对齐屏幕左上角,上下左右各10格的边界区域会被移到画布可视范围外,既隐藏了红色边界线,也解决了细胞触达可视边缘后停滞的问题。
内容的提问来源于stack exchange,提问作者Mr.Skalman
相关产品推荐
相关产品推荐

