Reputation: 5933
I have created the following code on jsfiddle. The goal is to remove a box from the canvas after it has been clicked. What actually happens is that the grid is cleared and completely redrawn WITH the removed box in it's old spot. The grid will only appear empty when all of the given objects have been removed... I am puzzled! What am I doing wrong?
jQuery(function(){
GridBox = new GridBox();
GridBox.init();
var canvas = GridBox.canvas;
canvas.on( 'click', GridBox.clickHandler );
});
function GridBox()
{
this.target = { x: 0, y: 0 };
this.current = { x: 0, y: 0 };
this.boxHeight = 50;
this.boxWidth = 50;
this.width = 500;
this.height = 500;
this.context = null;
this.canvas = null;
var self = this,
init = false,
bw = this.width,
bh = this.height,
p = 0,
cw = bw + ( p * 2 ) + 1,
ch = bh + ( p * 2 ) + 1;
/**
* Array of boxes that are painted on the grid.
* Each box has its own x and y coordinates.
*/
this.boxesOnGrid = [
{ x: 2, y: 2 },
{ x: 9, y: 2 },
{ x: 5, y: 5 }
];
/**
* Initiate this object
* @constructor
*/
this.init = function()
{
if( !init ) {
var canvas = jQuery( '<canvas/>' ).attr({ width: cw, height: ch }).appendTo( 'body' );
this.canvas = canvas;
this.context = this.canvas.get( 0 ).getContext( '2d' );
this.createGrid();
init = true;
}
};
this.clearGrid = function()
{
alert( 'clearing grid' );
this.context.clearRect( 0, 0, 500, 500 );
};
/**
* Create the grid
*/
this.createGrid = function()
{
for( var x = 0; x <= bw; x += this.boxWidth ) {
this.context.moveTo( 0.5 + x + p, p );
this.context.lineTo( 0.5 + x + p, bh + p );
}
for( var x = 0; x <= bh; x += this.boxHeight ) {
this.context.moveTo( p, 0.5 + x + p );
this.context.lineTo( bw + p, 0.5 + x + p );
}
this.context.strokeStyle = "#aaa";
this.context.stroke();
var boxes = this.boxesOnGrid;
this.boxesOnGrid = [];
for( key in boxes ) {
var currentBox = boxes[ key ];
alert( 'i want to create box ' + currentBox.x + 'x' + currentBox.y );
this.createBoxAt( currentBox.x, currentBox.y );
}
};
/**
* Find a suitable path between two boxes
*/
this.findPath = function()
{
};
this.clickHandler = function( event )
{
var clickOffset = {
x: event.offsetX,
y: event.offsetY
}, clickedBox = {
x: Math.ceil( clickOffset.x / 50 ),
y: Math.ceil( clickOffset.y / 50 )
};
for( key in GridBox.boxesOnGrid ) {
if( GridBox.boxesOnGrid[ key ].x === clickedBox.x && GridBox.boxesOnGrid[ key ].y === clickedBox.y ) {
GridBox.clearGrid();
GridBox.removeBox( key );
GridBox.createGrid();
}
}
};
/**
* Remove a box from the grid by removing it from the boxes array
* and re-drawing the grid.
*/
this.removeBox = function( key )
{
alert( 'removing box ' + key );
this.boxesOnGrid.splice( key, 1 );
};
/**
* Create a box at a given coordinate on the grid
* @param {int} x
* @param {int} y
*/
this.createBoxAt = function( x, y )
{
var box = {
x: x * this.boxWidth - this.boxWidth,
y: y * this.boxHeight - this.boxHeight
};
this.createBox( box.x, box.y );
this.saveBox( x, y );
};
this.createBox = function( xpos, ypos )
{
this.context.rect( xpos, ypos, this.boxWidth, this.boxHeight );
this.context.fillStyle = '#444';
this.context.fill();
};
this.saveBox = function( x, y )
{
this.boxesOnGrid.push( { x: x, y: y } );
};
}
Upvotes: 1
Views: 197
Reputation: 35309
Change createBox
to the following.
this.createBox = function( xpos, ypos )
{
this.context.beginPath();
this.context.rect( xpos, ypos, this.boxWidth, this.boxHeight );
this.context.fillStyle = '#444';
this.context.fill();
this.context.closePath();
};
Your not properly starting/ending paths, so the previous path isnt cleared when you redraw thus filling them all in again. Another way around it is to just use fillRect
instead.
The first step to create a path is calling the beginPath method. Internally, paths are stored as a list of sub-paths (lines, arcs, etc) which together form a shape. Every time this method is called, the list is reset and we can start drawing new shapes.
Upvotes: 4