绘制100万个方格的可点击网格

时间:2015-02-18 05:57:58

标签: javascript html css

我需要找到一种绘制1000x1000正方形网格的方法,每个正方形都是可点击的,它们必须是独立的颜色可变的。喜欢地雷游戏。我可以使用HTML(纯或使用Canvas或SVG),CSS和JavaScript。

我知道如何使用JavaScript和CSS创建一个具有这些特征的网格,它适用于10x10正方形,100x100正方形将变成高矩形并加载1000x1000,但是"正方形"压缩太大,边界相互碰撞,呈现一个完整的灰色页面。

我尝试使用HTML和JavaScript绘制SVG正方形,正方形'大小问题解决了,但我不知道如何让他们在点击时改变颜色,当我设置加载1000x1000方格时,它会冻结浏览并最终崩溃标签。

这在任何方面都可行吗?

修改

很抱歉,如果我不清楚,但是,我需要滚动条。对我来说没问题。

你可以看到我在这里描述的两个试验:

JavaScript和CSS



var lastClicked;
var grid = clickableGrid(100,100,function(el,row,col,i){
    console.log("You clicked on element:",el);
    console.log("You clicked on row:",row);
    console.log("You clicked on col:",col);
    console.log("You clicked on item #:",i);

    el.className='clicked';
    if (lastClicked) lastClicked.className='';
    lastClicked = el;
});

document.body.appendChild(grid);
     
function clickableGrid( rows, cols, callback ){
    var i=0;
    var grid = document.createElement('table');
    grid.className = 'grid';
    for (var r=0;r<rows;++r){
        var tr = grid.appendChild(document.createElement('tr'));
        for (var c=0;c<cols;++c){
            var cell = tr.appendChild(document.createElement('td'));
            ++i;
            cell.addEventListener('click',(function(el,r,c,i){
                return function(){
                    callback(el,r,c,i);
                }
            })(cell,r,c,i),false);
        }
    }
    return grid;
}
&#13;
.grid { margin:1em auto; border-collapse:collapse }
.grid td {
    cursor:pointer;
    width:30px; height:30px;
    border:1px solid #ccc;
}
.grid td.clicked {
    background-color:gray;
}
&#13;
&#13;
&#13;

JavaScript和HTML

&#13;
&#13;
 
    document.createSvg = function(tagName) {
        var svgNS = "http://www.w3.org/2000/svg";
        return this.createElementNS(svgNS, tagName);
    };
    
    var numberPerSide = 20;
    var size = 10;
    var pixelsPerSide = 400;
    
    
    
    var grid = function(numberPerSide, size, pixelsPerSide, colors) {
        var svg = document.createSvg("svg");
        svg.setAttribute("width", pixelsPerSide);
        svg.setAttribute("height", pixelsPerSide);
        svg.setAttribute("viewBox", [0, 0, numberPerSide * size, numberPerSide * size].join(" "));
        
        for(var i = 0; i < numberPerSide; i++) {
            for(var j = 0; j < numberPerSide; j++) {
              var color1 = colors[(i+j) % colors.length];
              var color2 = colors[(i+j+1) % colors.length];  
              var g = document.createSvg("g");
              g.setAttribute("transform", ["translate(", i*size, ",", j*size, ")"].join(""));
              var number = numberPerSide * i + j;
              var box = document.createSvg("rect");
              box.setAttribute("width", size);
              box.setAttribute("height", size);
              box.setAttribute("fill", color1);
              box.setAttribute("id", "b" + number); 
              g.appendChild(box);
              svg.appendChild(g);
            }  
        }
        svg.addEventListener(
            "click",
            function(e){
                var id = e.target.id;
                if(id)
                    alert(id.substring(1));
            },
            false);
        return svg;
    };
    
    var container = document.getElementById("container");
    container.appendChild(grid(100, 10, 2000, ["gray", "white"]));

    
&#13;
<div id="container">
    
</div>
&#13;
&#13;
&#13;

我将尝试实施给定的答案,尽快我接受或更新此问题。感谢。

为了记录,我设法使用画布绘制网格和点击的方块,并添加了一个事件监听器来了解用户点击的位置。

以下是JavaScript和HTML中的代码:

&#13;
&#13;
function getSquare(canvas, evt) {
    var rect = canvas.getBoundingClientRect();
    return {
        x: 1 + (evt.clientX - rect.left) - (evt.clientX - rect.left)%10,
        y: 1 + (evt.clientY - rect.top) - (evt.clientY - rect.top)%10
    };
}

function drawGrid(context) {
    for (var x = 0.5; x < 10001; x += 10) {
      context.moveTo(x, 0);
      context.lineTo(x, 10000);
    }
    
    for (var y = 0.5; y < 10001; y += 10) {
      context.moveTo(0, y);
      context.lineTo(10000, y);
    }
    
    context.strokeStyle = "#ddd";
    context.stroke();
}

function fillSquare(context, x, y){
    context.fillStyle = "gray"
    context.fillRect(x,y,9,9);
}

var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');

drawGrid(context);

canvas.addEventListener('click', function(evt) {
    var mousePos = getSquare(canvas, evt);
    fillSquare(context, mousePos.x, mousePos.y)
}, false);
&#13;
<body>
    <canvas id="myCanvas" width="10000" height="10000"></canvas>
</body>
&#13;
&#13;
&#13;

3 个答案:

答案 0 :(得分:7)

用HTML生成这么大的网格肯定会有问题。 在Canvas上绘制网格并使用mouse-picker technique确定单击哪个单元格会更有效。

这需要1次onclick和/或悬停事件而不是1,000,000次。 它还需要更少的HTML代码。

答案 1 :(得分:1)

我不会立即初始化所有广场,而是点击它们 -

&#13;
&#13;
(function() {
var divMain = document.getElementById('main'),
    divMainPosition = divMain.getBoundingClientRect(), 
    squareSize = 4, 
    square = function(coord) { 
        var x = coord.clientX - divMainPosition.x + document.body.scrollLeft + 
            document.documentElement.scrollLeft, 
            y = coord.clientY - divMainPosition.y + document.body.scrollTop + 
            document.documentElement.scrollTop; 
        return {
            x:Math.floor(x / squareSize), 
            y:Math.floor(y / squareSize)
        }
    }

divMain.addEventListener('click', function(evt) { 
    var sqr = document.createElement('div'), 
        coord = square(evt); 
    sqr.className = 'clickedSquare'; 
    sqr.style.width = squareSize + 'px'; 
    sqr.style.height = squareSize + 'px'; 
    sqr.style.left = (coord.x * squareSize) + 'px'; 
    sqr.style.top = (coord.y * squareSize) + 'px';
    sqr.addEventListener('click', function(evt) { 
        console.log(this); 
        this.parentNode.removeChild(this); 
        evt.stopPropagation(); 
    }); 
    this.appendChild(sqr); 
}); 
}()); 
&#13;
#main { 
    width:4000px;
    height:4000px;
    background-color:#eeeeee;
    position:relative; 
}

.clickedSquare {
    background-color:#dd8888;
    position:absolute; 
}
&#13;
<div id="main">
</div>
&#13;
&#13;
&#13;

  • 使用CSS定位来确定点击了哪个方块,
  • 在需要之前不会初始化正方形。

当然,我想这会开始对使用r体验产生负面影响,但这最终将取决于他们的浏览器和机器。

答案 2 :(得分:0)

使用您通常使用的相同格式,但添加:

sqauareElement.height = 10 //height to use
squareElement.width = 10 //width to use

由于尺寸的原因,这会添加相当大的卷轴,但这是我能想出的唯一合理的解释。