草庐IT

javascript - 绘制 100 万个正方形的可点击网格

coder 2023-08-10 原文

我需要找到一种方法来绘制一个 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;
}
.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>

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

解决方案

只是为了记录,我设法使用 Canvas 绘制网格和单击的方 block ,并添加了一个事件监听器以了解用户单击的位置。

这是 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生成这么大的网格肯定是有问题的。 在 Canvas 上绘制网格并使用 mouse-picker technique确定点击了哪个单元格会更有效率。

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

关于javascript - 绘制 100 万个正方形的可点击网格,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28576966/

有关javascript - 绘制 100 万个正方形的可点击网格的更多相关文章

  1. ruby-on-rails - 使用 javascript 更改数据方法不会更改 ajax 调用用户的什么方法? - 2

    我遇到了一个非常奇怪的问题,我很难解决。在我看来,我有一个与data-remote="true"和data-method="delete"的链接。当我单击该链接时,我可以看到对我的Rails服务器的DELETE请求。返回的JS代码会更改此链接的属性,其中包括href和data-method。再次单击此链接后,我的服务器收到了对新href的请求,但使用的是旧的data-method,即使我已将其从DELETE到POST(它仍然发送一个DELETE请求)。但是,如果我刷新页面,HTML与"new"HTML相同(随返回的JS发生变化),但它实际上发送了正确的请求类型。这就是这个问题令我困惑的

  2. ruby - 在 Mechanize 中使用 JavaScript 单击链接 - 2

    我有这个:AccountSummary我想单击该链接,但在使用link_to时出现错误。我试过:bot.click(page.link_with(:href=>/menu_home/))bot.click(page.link_with(:class=>'top_level_active'))bot.click(page.link_with(:href=>/AccountSummary/))我得到的错误是:NoMethodError:nil:NilClass的未定义方法“[]” 最佳答案 那是一个javascript链接。Mechan

  3. ruby-on-rails - 你能为 Ruby on Rails 推荐好的数据网格类/gem 吗? - 2

    您能为RubyonRails推荐好的数据网格类/gem吗?喜欢http://code.google.com/p/zend-framework-datagrid/采埃孚 最佳答案 你也可以试试datagridgem。这不仅关注带有列的网格,还关注过滤器。classSimpleReportincludeDatagridscopedoUser.includes(:group)endfilter(:category,:enum,:select=>["first","second"])filter(:disabled,:eboolean)fi

  4. 100个python算法超详细讲解:画直线 - 2

    1.问题描述使用Python的turtle(海龟绘图)模块提供的函数绘制直线。2.问题分析一幅复杂的图形通常都可以由点、直线、三角形、矩形、平行四边形、圆、椭圆和圆弧等基本图形组成。其中的三角形、矩形、平行四边形又可以由直线组成,而直线又是由两个点确定的。我们使用Python的turtle模块所提供的函数来绘制直线。在使用之前我们先介绍一下turtle模块的相关知识点。turtle模块提供面向对象和面向过程两种形式的海龟绘图基本组件。面向对象的接口类如下:1)TurtleScreen类:定义图形窗口作为绘图海龟的运动场。它的构造器需要一个tkinter.Canvas或ScrolledCanva

  5. javascript - jQuery 的 jquery-1.10.2.min.map 正在触发 404(未找到) - 2

    我看到有关未找到文件min.map的错误消息:GETjQuery'sjquery-1.10.2.min.mapistriggeringa404(NotFound)截图这是从哪里来的? 最佳答案 如果ChromeDevTools报告.map文件的404(可能是jquery-1.10.2.min.map、jquery.min.map或jquery-2.0.3.min.map,但任何事情都可能发生)首先要知道的是,这仅在使用DevTools时才会请求。您的用户不会遇到此404。现在您可以修复此问题或禁用sourcemap功能。修复:获取文

  6. ruby-on-rails - 计算数组中的项目跨越数千条记录的 100 条 - 2

    我有一个带有Postgres数据库的Rails应用程序,该数据库有一个带有jsonbgenres列的Artists表。有几十万行。该行中的每个流派列都有一个类似["rock","indie","seenlive","alternative","indierock"]的数组,其中包含不同的流派。我想要做的是在所有行中以JSON格式输出每种类型的计数。类似于:{"rock":532,"powermetal":328,"indie":862}有没有办法有效地做到这一点?更新...这是我目前得到的...genres=Artist.all.pluck(:genres).flatten.delet

  7. ruby-on-rails - 我将 Rails3 与 tinymce 一起使用。如何呈现用户关闭浏览器javascript然后输入xss? - 2

    我有一个用Rails3编写的站点。我的帖子模型有一个名为“内容”的文本列。在帖子面板中,html表单使用tinymce将“content”列设置为textarea字段。在首页,因为使用了tinymce,post.html.erb的代码需要用这样的原始方法来实现。.好的,现在如果我关闭浏览器javascript,这个文本区域可以在没有tinymce的情况下输入,也许用户会输入任何xss,比如alert('xss');.我的前台会显示那个警告框。我尝试sanitize(@post.content)在posts_controller中,但sanitize方法将相互过滤tinymce样式。例如

  8. ruby - 使用 Selenium WebDriver 启用/禁用 javascript - 2

    出于某种原因,我必须为Firefox禁用javascript(手动,我们按照提到的步骤执行http://support.mozilla.org/en-US/kb/javascript-settings-for-interactive-web-pages#w_enabling-and-disabling-javascript)。使用Ruby的SeleniumWebDriver如何实现这一点? 最佳答案 是的,这是可能的。而是另一种方式。您首先需要查看链接Selenium::WebDriver::Firefox::Profile#[]=

  9. ruby - Watir-Webdriver 是否支持点击目标为 javascript 的链接? - 2

    我是Ruby和Watir-Webdriver的新手。我有一套用VBScript编写的站点自动化程序,我想将其转换为Ruby/Watir,因为我现在必须支持Firefox。我发现我真的很喜欢Ruby,而且我正在研究Watir,但我已经花了一周时间试图让Webdriver显示我的登录屏幕。该站点以带有“我同意”区域的“警告屏幕”开头。用户点击我同意并显示登录屏幕。我需要单击该区域以显示登录屏幕(这是同一页面,实际上是一个表单,只是隐藏了)。我整天都在用VBScript这样做:objExplorer.Document.GetElementsByTagName("area")(0).click

  10. ruby-on-rails - 网格与Rails? - 2

    网格支撑排序数据。搜索全选/无轨道上有网格吗? 最佳答案 为铁路电网提供丰富的信息。请参阅此链接。http://www.2dconcept.com/jquery-grid-rails-plugin 关于ruby-on-rails-网格与Rails?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/5100498/

随机推荐