绘制100万个正方形的可点击网格
Draw clickable grid of 1 million squares
我需要找到一种方法来绘制1000x1000个正方形的网格,每个正方形都可以点击,并且它们必须独立变色。就像地雷游戏。我可以使用HTML(纯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;
}
.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;
}
JavaScript和HTML
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"]));
<div id="container">
</div>
我将尝试执行给定的答案,并尽快接受或更新此问题。谢谢
解决方案
为了记录,我设法使用画布绘制网格和单击的正方形,并添加了一个事件监听器来了解用户单击的位置。
以下是JavaScript和HTML中的代码:
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);
<body>
<canvas id="myCanvas" width="10000" height="10000"></canvas>
</body>
用HTML生成这么大的网格肯定会有问题。在画布上绘制网格,并使用鼠标选取器技术来确定单击了哪个单元格会更有效率。
这将需要1个onclick和/或悬停事件,而不是1000000。它还需要更少的HTML代码。
我不会立即初始化所有的方块,而是在点击它们时-
(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);
});
}());
#main {
width:4000px;
height:4000px;
background-color:#eeeeee;
position:relative;
}
.clickedSquare {
background-color:#dd8888;
position:absolute;
}
<div id="main">
</div>
- 使用CSS定位来确定点击了哪个方块
- 在需要之前不会初始化正方形
当然,我认为这会开始对使用r体验产生负面影响,但这最终取决于他们的浏览器和机器。
使用您通常使用的相同格式,但添加以下内容:
sqauareElement.height = 10 //height to use
squareElement.width = 10 //width to use
由于尺寸的原因,这将增加一个相当大的卷轴,但这是我能想到的唯一合乎逻辑的解释。
画布方法很好,但事件委派可以通过一个表或具有单个侦听器的<div>
元素来实现:
const tbodyEl = document.querySelector("table tbody");
tbodyEl.addEventListener("click", event => {
const cell = event.target.closest("td");
if (!cell || !tbodyEl.contains(cell)) {
return;
}
const row = +cell.getAttribute("data-row");
const col = +cell.getAttribute("data-col");
console.log(row, col);
});
const rows = 100;
const cols = 100;
for (let i = 0; i < rows; i++) {
const rowEl = document.createElement("tr");
tbodyEl.appendChild(rowEl);
for (let j = 0; j < cols; j++) {
const cellEl = document.createElement("td");
rowEl.appendChild(cellEl);
cellEl.classList.add("cell");
cellEl.dataset.row = i;
cellEl.dataset.col = j;
}
}
.cell {
height: 4px;
width: 4px;
cursor: pointer;
border: 1px solid black;
}
table {
border-collapse: collapse;
}
<table><tbody></tbody></table>
- 剑道网格jQuery动画()问题
- 使用Dnamics CRM 2011中的JavaScript读取子网格的所有记录,而不考虑活动页面
- 我可以更改剑道UI网格吗's的外键值
- jqGrid树网格问题
- 在Three.js中导出网格会提高性能吗
- 如何在剑道网格初始化后设置pageSizes
- 在threejs中使用纹理网格和线框网格
- 如何在可分组的剑道网格中设置空数据文本
- 如何在Angular UI网格中选择下一行
- ExtJS网格单元格编辑器,防止焦点松动问题
- 多维数据集网格未在指定的分区中绘制
- 光线投射从内部投射时不会碰到网格
- 使用javascript在MVC中查找网格长度时出错
- ExtJS使网格高度达到100%
- 绘制100万个正方形的可点击网格
- 如何在 Javascript 中创建一个模拟 100 行和 10 列网格的嵌套循环
- 对于 100 万条记录,mongo 中的批量处理非常慢
- Img在点击时扩展到100%(并且仍然停留在网格上)
- 将剑道UI网格高度设置为包装器的100%
- Google Maps V3渲染超过100万个标记(在合理的时间内)