Canvas Grid Part 3
Last time we managed to create a very simple grid and change colors when you clicked on a cell. But, being a first attempt the grid wasn’t flexible and it had a lot of duplicated code. In this post we are going to improve it.
Before we start, let’s take a look at the finished result.
Click a square
Let’s start by creating a Grid object. This object should have the basic properties for a grid.
var Grid = {
//Canvas Size
canvasWidth: 300,
canvasHeight: 300,
//Columns and Rows
numberOfColumns: 5,
numberOfRows: 5,
//Size of the cells
cellWidth: function() { return this.canvasWidth/this.numberOfColumns; },
cellHeight: function() { return this.canvasHeight/this.numberOfRows; },
};
Now we have one place to adjust the size of the Canvas, the number of rows/columns, and the cell sizes will be automatically calculated.
We also need to adjust the setup of the Canvas to use the grid.
//Setup the Canvas
$("#display").attr({
width: Grid.canvasWidth,
height: Grid.canvasHeight,
});
Now we need to actually draw the grid. Last time I just drew outlines of squares, but I think it will be easier this time to simply draw lines.
//Draw the GridLines
drawGrid: function(display){
display.beginPath();
//Draw the Vertical lines
for(var i=0; i < this.numberOfColumns; i++){
//Move to the top of the canvas
display.moveTo(i*this.cellWidth(), 0)
//Draw the line
display.lineTo( i*this.cellWidth(), this.canvasHeight );
}
//Draw the Horizontal lines.
for(var i=0; i < this.numberOfRows; i++){
//Move to the left of the canvas
display.moveTo(0, i*this.cellHeight())
//Draw the line
display.lineTo( this.canvasWidth, i*this.cellHeight() );
}
display.stroke();
},
Now we can simply tell the Grid to draw its self. It will draw properly no matter how many rows and columns we want, and we can adjust the size of the canvas.
To handle clicking on the grid, we need two more methods. One to know which cell the user clicked on, and one to redraw a specific cell.
//Find which cell was clicked.
cellMouseIn: function(evt, offset){
//Create an Object to hold the column/row
var position = {
column: -1,
row: -1,
};
//Find the poistion of the mouse
var x_pos = Math.floor(evt.pageX - offset.left);
var y_pos = Math.floor(evt.pageY - offset.top);
//Now which column was it clicked?
for(var column=0; column < this.numberOfColumns; column++){
//Find the column
if( x_pos > column*this.cellWidth() && x_pos < (column+1)*this.cellWidth() ){
//Found it!
position.column = column;
//Fow find the row
for(var row=0; row < this.numberOfRows; row++){
//Find the row
if( y_pos > row*this.cellHeight() && y_pos < (row+1)*this.cellHeight()){
//Found it!
position.row = row;
}
} //End Row
}
} // End Column
//Return the found position
return position;
},
//(re)Draw a cell at the position.
drawCell: function(display, position){
var y_pos = position.row * this.cellHeight();
var x_pos = position.column * this.cellWidth();
//Draw the cell
display.fillRect( x_pos, y_pos, this.cellWidth(), this.cellHeight());
//ReDraw the grid
this.drawGrid(display);
},
Now all we have to do is adjust our onMouseDown and onMouseUp functions to use the grid, and register these events.
var display; //This is going to be our Drawing Context
$(document).ready(function(){
//Setup the Canvas
$("#display").attr({
width: Grid.canvasWidth,
height: Grid.canvasHeight,
}) /* Register Events */
.bind("mousedown", onMouseDown)
.bind("mouseup", onMouseUp);
//Get the context
display = $("#display")[0].getContext("2d");
//Draw it
draw();
});
function onMouseDown(evt){
//Change the Squares Color.
display.fillStyle = "#0F0";
display.strokeStyle = "#FFF";
//Get the cell That the mouse is in
var position = Grid.cellMouseIn(evt, $("#display").offset() )
//Now redraw it
Grid.drawCell(display, position);
//Now display the cell info
$("#text").html( position.column +","+ position.row);
}
function onMouseUp(evt){
//Change the color back.
display.fillStyle = "#000";
display.strokeStyle = "#FFF";
//Get the cell That the mouse is in
var position = Grid.cellMouseIn(evt, $("#display").offset() )
//Now redraw it
Grid.drawCell(display, position);
}
//Draw on the Canvas
function draw(){
//Lets draw the outline of four squares on a black canvas.
//Draw the background
display.fillStyle = "#000";
display.fillRect(0,0, Grid.canvasWidth, Grid.canvasHeight);
//all the squares will be white.
display.strokeStyle = "#FFF";
display.lineWidth = 2;
//Tell the Grid to draw
Grid.drawGrid(display);
}
That's it!
There are still some bugs with it, but it works for the most part.
You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.