You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.19 08:24:02