Search code examples
javascripthtmlcanvas

Creating a Clickable Grid in a Web Browser


I want to draw a grid of 10 x 10 squares on a HTML5 canvas with number 1-100 displayed on the squares. Clicking a square should call a JavaScript function with the square's number passed as a variable to the function.


Solution

  • First, I encourage you to read this answer to another question involving the HTML5 Canvas. You need to understand that there are no squares. In order to detect a click on a 'square', you would have to keep track of a mapping from each canvas coordinate to the square(s) that it logically contains, handle a single click event on the entire canvas, work out which square(s) you want to change, and then redraw the canvas with the changes you want.

    Then—since you seem to have no objection to using a more appropriate technology—I encourage you to do this in either HTML (where each 'square' is something like a <div> that is absolutely-positioned and sized and colored using CSS), or SVG (using <rect> if you need the squares to be able to be rotated, or want to introduce other shapes).

    HTML and SVG are both 'retained-mode' graphics mode systems, where drawing a shape 'retains' the concept of that shape. You can move the shape, change its colors, size, etc. and the computer will automatically redraw it for you. Moreover, and more importantly for your use case, you can (with both HTML and SVG):

    function changeColor(evt){
      var clickedOn = evt.target;
      // for HTML
      clickedOn.style.backgroundColor = '#f00';
    
      // for SVG
      clickedOn.setAttribute('fill','red');
    }
    mySquare.addEventListener('click',changeColor,false);
    

    Edit: I've created a simple implementation in JavaScript and HTML: http://jsfiddle.net/6qkdP/2/

    Here's the core code, in case JSFiddle is down:

    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'));
          cell.innerHTML = ++i;
          cell.addEventListener('click',(function(el,r,c,i){
            return function(){ callback(el,r,c,i); }
           })(cell,r,c,i),false);
        }
      }
      return grid;
    }