Reputation: 24749
If I draw a green circle on a black background, then draw the same circle in black, a green shadow/glow is left behind. The circle is not actually erased.
How do I make it purely black again and remove the glow?
I've tried context.shadowColor = "transparent";
Here is a snippet:
context.beginPath();
context.arc(x-1, y-2, 2, 0, 2*Math.PI);
context.fillStyle = "#FF0000";
//context.strokeStyle = "#FF0000";
//context.stroke();
context.fill();
context.beginPath();
context.arc(x-1, y-2, 2, 0, 2*Math.PI);
context.fillStyle = "#000000";
//context.strokeStyle = "#000000";
//context.stroke();
context.fill();
Here is the full object:
Upvotes: 0
Views: 224
Reputation: 54089
How to clear the canvas.
By the looks of the image you gave you are wanting to write a game or an animation of some sort.
The general way games and animations are done are by redrawing the entire game screen every frame. This greatly simplifies the design of the rendering engine. Makes it easy to draw one thing over the other by simply changing the order in which you draw them. To make something vanish just don't render it.
I am assuming you know how to load images
Clearing the screen
You have several ways to clear the screen.
// assuming ctx is the 2d Context and width and height are the canvas width and height.
ctx.clearRect(0, 0, width, height);
Or by filling the screen with a rectangle.
var backgroundColour = "#000";
ctx.fillStyle = backgroundColour;
ctx.fillRect(0, 0, width, height);
Or use a background image
var backgroundImage = new Image();
backgroundImage.src = "backgroundImage URL";
// then wait for image to load.
// then
ctx.drawImage(backgroundImage, 0, 0, width, height);
Drawing sprites
Now you can draw the graphics. Again there are many ways to do this. One approch is to keep a list of all the objects and draw them all in one go after the screen has cleared.
// create or load a game sprite (image)
var gameSprite = new Image();
gameSprite.src = "gameSprite URL";
// create a list of sprites.
var mySprites = [
{x : 10, y : 10, image : gameSprite}, // sprite 1
{x : 30, y : 60, image : gameSprite}, // sprite 2
{x : 70, y : 40, image : gameSprite} // sprite 3
];
// itterate the list and draw each sprite one at a time.
function renderSprites (spriteList) {
var i,len,s;
len = spriteList.length;
for (i = 0; i < len; i++) {
s = spriteList[i];
ctx.drawImage(s.image, s.x, s.y);
}
}
Animating it all
The last thing is you need to sync it all up with the display hardware so that it runs at the maximum frame rate possible and does not create artifacts such as shearing, or flickering. To do this you use requestAnimationFrame
which is similar to setTimeout
but you do not supply the timing the browser takes care of that.
You will need a main loop function that you provide to requestAnimationFrame
to call when the browser is ready to draw the next frame. In this function you first clear the screen, do the game logic, draw all the sprites, and then request the next frame (though you can request the next frame at any stage within the main loop).
function mainLoop(time){ // requestAnimationFrame adds the argument (time).
// This is the time in milliseconds.
// clear the screen
ctx.drawImage(backgroundImage,0,0,width,height);
// do game logic here
renderSprites(mySprites); // draw the sprites
// now request the next frame and do it all again.
requestAnimationFrame(mainLoop);
}
// start the animation by requesting the first frame.
requestAnimationFrame(mainLoop);
This will run at 60fps (frames per second) and can easly handle over 100 sprites (on all but the most basic device)
Upvotes: 2