The question that I have is with context.beginPath() and context.closePath(). The code below will draw a circle in an arc around the screen until it disappears followed by a small dot which I would comment out because it is a .jpg which I do not know how to include.
My question is exactly what does the beginPath() do and also the closePath() do?
If I comment them out I get a wild result other than what I am expecting. I have looked on the internet but I have not seen the results like this.
Code with a question:
function drawTheBall() {
context.fillStyle = "#00AB0F"; //sets the color of the ball
context.beginPath();
context.arc(ball.x,ball.y,10,0,Math.PI*2,true); //draws the ball
context.closePath();
context.fill();
}
Working code below
HTML-Javascript
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>CH5EX10: Moving In Simple Geometric Spiral </title>
<script src="modernizr.js"></script>
<script type="text/javascript">
window.addEventListener('load', eventWindowLoaded, false);
function eventWindowLoaded() {
canvasApp();
}
function canvasSupport () {
return Modernizr.canvas;
}
function canvasApp() {
var radiusInc = 2;
var circle = {centerX:250, centerY:250, radius:2, angle:0, radiusInc:2}
var ball = {x:0, y:0,speed:.1};
var points = new Array();
theCanvas = document.getElementById('canvasOne');
context = theCanvas.getContext('2d');
var pointImage = new Image();
pointImage.src = "point.png"; <-- Comment this line out
if (!canvasSupport()) {
return;
}
function erraseCanvas() {
context.clearRect(0,0,theCanvas.width,theCanvas.height);
}
function drawPathPoints() {
//Draw points to illustrate path
points.push({x:ball.x,y:ball.y});
for (var i= 0; i< points.length; i++) {
context.drawImage(pointImage, points[i].x, points[i].y,1,1);
}
}
function drawTheBall() {
context.fillStyle = "#00AB0F"; //sets the color of the ball
context.beginPath();
context.arc(ball.x,ball.y,10,0,Math.PI*2,true); //draws the ball
context.closePath();
context.fill();
}
function buildBall() {
ball.x = circle.centerX + Math.cos(circle.angle) * circle.radius;
ball.y = circle.centerY + Math.sin(circle.angle) * circle.radius;
circle.angle += ball.speed;
circle.radius += radiusInc;
}
function drawScreen () {
erraseCanvas();
buildBall();
drawPathPoints();
drawTheBall();
}
function gameLoop() {
window.setTimeout(gameLoop, 20);
drawScreen()
}
gameLoop();
}
</script>
</head>
<body>
<div style="position: absolute; top: 50px; left: 50px;">
<canvas id="canvasOne" width="500" height="500">
Your browser does not support the HTML 5 Canvas.
</canvas>
</div>
</body>
</html>
beginPath()
beginPath() clears the current internal path object and its sub-paths, which accumulates path operations such as line, rect, arc, arcTo and so on, regardless of if they are filled or stroked.
closePath()
closePath() connects the current path, or sub-path, position with the first point on that path created either with beginPath() or moveTo() if that was used. The latter creates a sub-path on the current main path and only this sub-path gets closed.
Some methods do a closePath() implicit and temporary for you such as fill() and clip() which means it's not needed for those calls. In any case, it must be called before a stroke() (or fill(), if you chose to use that) is called.
One can perhaps understand this method better if one think of it as "closing the loop" rather than ending or closing the path [object] which it doesn't.
BeginPath will start a new path, unlike moveTo which will begin a new subpath
Close path will close the path. it probably isn't needed unless you want stroking to stroke the entire path without a gap
Close Path:
//An Open Box
ctx.moveTo(0 , 0);
ctx.lineTo(0 , 100);
ctx.lineTo(100, 100);
ctx.lineTo(100, 0);
ctx.stroke();
ctx.translate(150, 0);
//A closed box
ctx.moveTo(0 , 0);
ctx.lineTo(0 , 100);
ctx.lineTo(100, 100);
ctx.lineTo(100, 0);
ctx.closePath();
ctx.stroke();
Related
I'm working on a HTML5 Canvas project and have some text drawn on the screen. Right now, it appears and just stay there, but what I need is for it to disappear after a few seconds so that every time it's called it's not just new text being drawn on top of the old text.
I tried clearRect() but that completely clears the entire rectangle and removes some of my background too, which I don't want.
Is there a way to do this?
I'm drawing the text with this basic function:
function drawText() {
ctx.font = "30px Arial";
ctx.fillText("Please wait...", 575, 130);
}
<!DOCTYPE HTML>
<html>
<head>
<style>
body {
margin: 0px;
padding: 0px;
}
</style>
</head>
<body>
<button onclick="showTheText()">Click to show text</button>
<canvas id="myCanvas" width="578" height="200"></canvas>
<script>
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
function showTheText() {
var myText = {
text: 'Hello World',
x: 0,
y: 75,
fill: 1
};
drawText(myText, context);
// wait one second before starting animation
setTimeout(function() {
animate(myText, canvas, context);
}, 1000);
}
function drawText(myText, context) {
context.font="30px Arial";
context.fillStyle="rgb(0, 0, 0, " + myText.fill + ")";
context.fillText(myText.text, myText.x, myText.y);
}
function animate(myText, canvas, context) {
// clear
context.clearRect(0, 0, canvas.width, canvas.height);
// !!!!!!!! redraw your background !!!!!!!!
// then redraw your text with new opacity
myText.fill -= .1;
drawText(myText, context);
// request new frame
if (myText.fill > -.1) {
setTimeout(function() {
animate(myText, canvas, context);
}, 2000 / 60);
}
}
</script>
</body>
</html>
Hope this can help you. What it does it immediately draws the text (and the rest of your background, you didn't provide it), then sets up a recursive timeout that will clear the rect, redraw your background, decrement the amount of opacity to apply to the text's fill, and redraw the text as well. You can slow it down by changing the time of the last setTimeout.
I adapted it from this example: https://www.html5canvastutorials.com/advanced/html5-canvas-animation-stage/
you can create a simple function to delete ,
you will need some values. For example, font height. width of character ... etc ,
for example in this case , you can use the following function , With few modifications :
function removeText(x,y,txt_length,font_height,char_width,ctx) {
ctx.clearRect(x, y-font_height ,char_width*txt_length,font_height);
}
and this function for write your string :
function drawText(x,y,text,ctx) {
ctx.font = "30px Arial";
ctx.fillText(text,x,y);
}
The same parameters x and y are passed to the functions and txt_length = text.length;
Once you've drawn text to canvas, it's no longer text - it's just a bunch of pixels! Since those pixels overwrite what is already there, there's no way to delete just the text.
Generally what you can do is re-draw the entire scene without the text, if you want to get rid of it.
You could also try re-drawing the text in the same position using the background color, which would remove the text, but this only works if the text is on a solid background.
To achieve expected use below option of fillStyle in clearText function
Create another function clearText with fillStyle white color with same text and x , y coordinates
Call clearText function from the drawText
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
function drawText() {
clearText()
ctx.font = "30px Arial";
ctx.fillStyle = "black";
ctx.fillText("Please wait...", 575, 130);
}
function clearText() {
ctx.font = "30px Arial";
ctx.fillStyle = "white";
ctx.fillText("Please wait...", 575, 130);
}
<button onclick="drawText()">draw text</button><br>
<canvas id="myCanvas" width="800" height="800"
style="border:1px solid #d3d3d3;">
Your browser does not support the canvas element.
</canvas>
code sample - https://codepen.io/nagasai/pen/oqOXxz
im using a canvas to visualize a small game of mine.
Basicly i have two objects that represent space ships, each of them has a "Location" array which holds the ships current x/y.
According to these arrays, i drawImage on the canvas (totalw/h is 300/300 fyi).
Now, for the difficult part.
i want to draw animations (gunfire) on that canvas. basicly from ship1 x/y to ship2 x/y.
For the animation function itself, im passing an effects object that holds 3 Arrays, shooter.location[x, y], target.location[x, y] and a third array that holds where the EFFECT is currently at [x, y].
this.animateEffects = function(effects){
var shooter = effects.shooter;
var target = effects.target;
var current = effects.current;
var canvas = document.getElementById("effects");
var context = canvas.getContext("2d");
context.clearRect(0, 0, canvas.width, canvas.height);
context.beginPath();
context.fillStyle = "red";
context.arc(current[0], current[1], 5, 0, 2*Math.PI);
effects.current[0]++
effects.current[1]++
context.fill();
if (current == target){
console.log("ding");
this.end()
}
}
My "problem" is that im, if possible at all, looking for a smart way to determine (for each frame) if effects[x, y] should go ++ or -- or a combination of the two, depending on where the "moving" ships are located at (at the time, the shooting started).
Any advise or hints are appreciated.
You can fire a bullet from shooter to target using linear interpolation.
Calculate the difference in the original X & Y positions of the shooter and target.
// save the starting position of the bullet (== shooter's original position)
// (these original X & Y are needed in the linear interpolation formula)
bulletOriginalX=shooter.x;
bulletOriginalY=shooter.y;
// calc the delta-X & delta-Y of the shooter & target positions
// (these deltas are needed in the linear interpolation formula)
dx=target.x-shooter.x;
dy=target.y-shooter.y;
Move the bullet towards the target using the interpolation formula
// where percent == the percent you want the bullet to be between
// it's starting & ending positions
// (between starting shooter & starting target positions)
currentBulletX=bulletOriginalX+dx*percent;
currentBulletY=bulletOriginalY+dy*percent;
Here's an example:
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;
shooter={x:50,y:50};
target={x:100,y:100};
effect={x:50,y:50,dx:0,dy:0,pct:0,speedPct:0.25};
draw();
fire();
$('#test').click(function(){
moveEffect();
draw();
});
function fire(){
effect.x=shooter.x;
effect.y=shooter.y;
effect.dx=target.x-shooter.x;
effect.dy=target.y-shooter.y;
effect.pct=0;
}
function moveEffect(){
effect.pct+=effect.speedPct;
}
function draw(){
ctx.clearRect(0,0,cw,ch);
ctx.beginPath();
ctx.arc(shooter.x,shooter.y,15,0,Math.PI*2);
ctx.closePath();
ctx.strokeStyle='green';
ctx.stroke();
ctx.beginPath();
ctx.arc(target.x,target.y,15,0,Math.PI*2);
ctx.closePath();
ctx.strokeStyle='red';
ctx.stroke();
if(effect.pct>1){return;}
var x=effect.x+effect.dx*effect.pct;
var y=effect.y+effect.dy*effect.pct;
ctx.beginPath();
ctx.arc(x,y,3,0,Math.PI*2);
ctx.closePath();
ctx.fillStyle='black';
ctx.fill();
}
body{ background-color: ivory; padding:10px; }
#canvas{border:1px solid red;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<button id=test>Animate 1 frame</button>
<br><canvas id="canvas" width=300 height=300></canvas>
I have the following code to draw shapes (mainly used for rectangles) but the HTML5 drawing functions seem to draw borders with their thickness centered on the lines specified. I would like to have a border outside the surface of the shape and I'm at a loss.
Path.prototype.trace = function(elem, closePath) {
sd.context.beginPath();
sd.context.moveTo(this.getStretchedX(0, elem.width), this.getStretchedY(0, elem.height));
sd.context.lineCap = "square";
for(var i=1; i<this.points.length; ++i) {
sd.context.lineTo(this.getStretchedX(i, elem.width), this.getStretchedY(i, elem.height));
}
if(closePath) {
sd.context.lineTo(this.getStretchedX(0, elem.width), this.getStretchedY(0, elem.height));
}
}
getStrechedX and getStretchedY return the coordinates of the nth vertex once the shape is applied to a set element width, height and offset position.
Thanks to Ken Fyrstenberg's answer I've got it working for a rectangle, but this solution can sadly not apply to other shapes.
http://jsfiddle.net/0zq9mrch/
Here I drew two "wide" borders, one subtracting half the lineWidth to every position, another one adding. It doesn't work (as expected) because it's only going to put the thick lines above and to the left in one case, under and to the right in another - not "outside" the shape. You can also see a white area around the slope.
I tried working out how I could get the vertices to manually draw the path for the thick border (using fill() instead of stroke()).
But it turns out I still end up with the same problem: how to programatically determine if an edge is inside or outside. This would require some trigonometry and a heavy algorithm. For the purpose of my current work, this is too much trouble. I wanted to use this to draw a map of a building. The room walls need to be drawn outside the given dimensions, but I'll stick to standalone sloped walls for now.
Solution
You can solve this by drawing two lines:
First line with line thickness as intended
Second line contracted with 50% of the outer line width
To contract, add 50% to x and y, subtract line-width (or 2x 50%) from width and height.
Example
var ctx = document.querySelector("canvas").getContext("2d");
var lineWidth = 20;
var lw50 = lineWidth * 0.5;
// outer line
ctx.lineWidth = lineWidth; // intended line width
ctx.strokeStyle = "#975"; // color for main line
ctx.strokeRect(40, 40, 100, 100); // full line
// inner line
ctx.lineWidth = 2; // inner line width
ctx.strokeStyle = "#000"; // color for inner line
ctx.strokeRect(40 + lw50, 40 + lw50, 100 - lineWidth, 100 - lineWidth);
<canvas></canvas>
Complex shapes
For more complex shapes you will have to calculate the path manually. This is a little bit more complex and perhaps too broad for SO. You have to consider things like tangents, angle at bends, intersections and so forth.
One way to "cheat" is to:
draw the main line at full thickness to canvas
then use reuse the path as a clipping mask
change composite mode to destination-atop
draw the shape offset in various direction
restore clipping
change color and reuse path again for the main line.
The offset value below will determine the thickness of the inner line while the directions will determine resolution.
var ctx = document.querySelector("canvas").getContext("2d");
var lineWidth = 20;
var offset = 0.5; // line "thickness"
var directions = 8; // increase to increase details
var angleStep = 2 * Math.PI / 8;
// shape
ctx.lineWidth = lineWidth; // intended line width
ctx.strokeStyle = "#000"; // color for inner line
ctx.moveTo(50, 100); // some random shape
ctx.lineTo(100, 20);
ctx.lineTo(200, 100);
ctx.lineTo(300, 100);
ctx.lineTo(200, 200);
ctx.lineTo(50, 100);
ctx.closePath();
ctx.stroke();
ctx.save()
ctx.clip(); // set as clipping mask
ctx.globalCompositeOperation = "destination-atop"; // draws "behind" existing drawings
for(var a = 0; a < Math.PI * 2; a += angleStep) {
ctx.setTransform(1,0,0,1, offset * Math.cos(a), offset * Math.sin(a));
ctx.drawImage(ctx.canvas, 0, 0);
}
ctx.restore(); // removes clipping, comp. mode, transforms
// set new color and redraw same path as previous
ctx.strokeStyle = "#975"; // color for inner line
ctx.stroke();
<canvas height=250></canvas>
I'm late to the party, but here's an alternate way to "outside stroke" a complex path.
It uses a PathObject to simplify the process of creating the outside stroke.
The PathObject saves all the commands and arguments used to define your complex path.
This PathObject can also replay the commands--and can thereby redefine/redraw the saved path.
The PathObject class is re-usable. You can use it to save any path (simple or complex) that you need to redraw.
Html5 Canvas will soon have its own Path2D object built into the context, but my example below has a cross-browser polyfill that can be used until the Path2D object is implemented.
An illustration of a cloud with a silver lining applied using an outside stroke.
"Here's how it's done..."
Create a PathObject that can save all the commands and arguments used to define your complex path. This PathObject can also replay the commands--and can thereby redefine the saved path. Html5 Canvas will soon have its own Path2D object built into the context, but my example below is a cross-browser polyfill that can be used until the Path2D object is implemented.
Save a complex path using the PathObject.
Play the path commands on the main canvas and fill/stroke as desired.
Play the path commands on a temporary in-memory canvas.
On the temporary canvas:
Set a context.lineWidth of twice your desired outside stroke width and do the stroke.
Set globalCompositeOperation='destination-out' and fill. This will cause the inside of the complex path to be cleared and made transparent.
Draw the temporary canvas onto the main canvas. This causes your existing complex path on the main canvas to get the "outside stroke" from the in-memory canvas.
Here's example code and a Demo:
function log(){console.log.apply(console,arguments);}
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var canvas1=document.getElementById("canvas1");
var ctx1=canvas1.getContext("2d");
// A "class" that remembers (and can replay) all the
// commands & arguments used to define a context path
var PathObject=( function(){
// Path-related context methods that don't return a value
var methods = ['arc','beginPath','bezierCurveTo','clip','closePath',
'lineTo','moveTo','quadraticCurveTo','rect','restore','rotate',
'save','scale','setTransform','transform','translate','arcTo'];
var commands=[];
var args=[];
function PathObject(){
// add methods plus logging
for (var i=0;i<methods.length;i++){
var m = methods[i];
this[m] = (function(m){
return function () {
if(m=='beginPath'){
commands.length=0;
args.length=0;
}
commands.push(m);
args.push(arguments);
return(this);
};}(m));
}
};
// define/redefine the path by issuing all the saved
// path commands to the specified context
PathObject.prototype.definePath=function(context){
for(var i=0;i<commands.length;i++){
context[commands[i]].apply(context, args[i]);
}
}
//
PathObject.prototype.show=function(){
for(var i=0;i<commands.length;i++){
log(commands[i],args[i]);
}
}
//
return(PathObject);
})();
var x=75;
var y=100;
var scale=0.50;
// define a cloud path
var path=new PathObject()
.beginPath()
.save()
.translate(x,y)
.scale(scale,scale)
.moveTo(0, 0)
.bezierCurveTo(-40, 20, -40, 70, 60, 70)
.bezierCurveTo(80, 100, 150, 100, 170, 70)
.bezierCurveTo(250, 70, 250, 40, 220, 20)
.bezierCurveTo(260, -40, 200, -50, 170, -30)
.bezierCurveTo(150, -75, 80, -60, 80, -30)
.bezierCurveTo(30, -75, -20, -60, 0, 0)
.restore();
// fill the blue sky on the main canvas
ctx.fillStyle='skyblue';
ctx.fillRect(0,0,canvas.width,canvas.height);
// draw the cloud on the main canvas
path.definePath(ctx);
ctx.fillStyle='white';
ctx.fill();
ctx.strokeStyle='black';
ctx.lineWidth=2;
ctx.stroke();
// draw the cloud's silver lining on the temp canvas
path.definePath(ctx1);
ctx1.lineWidth=20;
ctx1.strokeStyle='silver';
ctx1.stroke();
ctx1.globalCompositeOperation='destination-out';
ctx1.fill();
// draw the silver lining onto the main canvas
ctx.drawImage(canvas1,0,0);
body{ background-color: ivory; }
canvas{border:1px solid red;}
<h4>Main canvas with original white cloud + small black stroke<br>The "outside silver lining" is from the temp canvas</h4>
<canvas id="canvas" width=300 height=300></canvas>
<h4>Temporary canvas used to create the "outside stroke"</h4>
<canvas id="canvas1" width=300 height=300></canvas>
im using a canvas to visualize a small game of mine.
Basicly i have two objects that represent space ships, each of them has a "Location" array which holds the ships current x/y.
According to these arrays, i drawImage on the canvas (totalw/h is 300/300 fyi).
Now, for the difficult part.
i want to draw animations (gunfire) on that canvas. basicly from ship1 x/y to ship2 x/y.
For the animation function itself, im passing an effects object that holds 3 Arrays, shooter.location[x, y], target.location[x, y] and a third array that holds where the EFFECT is currently at [x, y].
this.animateEffects = function(effects){
var shooter = effects.shooter;
var target = effects.target;
var current = effects.current;
var canvas = document.getElementById("effects");
var context = canvas.getContext("2d");
context.clearRect(0, 0, canvas.width, canvas.height);
context.beginPath();
context.fillStyle = "red";
context.arc(current[0], current[1], 5, 0, 2*Math.PI);
effects.current[0]++
effects.current[1]++
context.fill();
if (current == target){
console.log("ding");
this.end()
}
}
My "problem" is that im, if possible at all, looking for a smart way to determine (for each frame) if effects[x, y] should go ++ or -- or a combination of the two, depending on where the "moving" ships are located at (at the time, the shooting started).
Any advise or hints are appreciated.
You can fire a bullet from shooter to target using linear interpolation.
Calculate the difference in the original X & Y positions of the shooter and target.
// save the starting position of the bullet (== shooter's original position)
// (these original X & Y are needed in the linear interpolation formula)
bulletOriginalX=shooter.x;
bulletOriginalY=shooter.y;
// calc the delta-X & delta-Y of the shooter & target positions
// (these deltas are needed in the linear interpolation formula)
dx=target.x-shooter.x;
dy=target.y-shooter.y;
Move the bullet towards the target using the interpolation formula
// where percent == the percent you want the bullet to be between
// it's starting & ending positions
// (between starting shooter & starting target positions)
currentBulletX=bulletOriginalX+dx*percent;
currentBulletY=bulletOriginalY+dy*percent;
Here's an example:
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;
shooter={x:50,y:50};
target={x:100,y:100};
effect={x:50,y:50,dx:0,dy:0,pct:0,speedPct:0.25};
draw();
fire();
$('#test').click(function(){
moveEffect();
draw();
});
function fire(){
effect.x=shooter.x;
effect.y=shooter.y;
effect.dx=target.x-shooter.x;
effect.dy=target.y-shooter.y;
effect.pct=0;
}
function moveEffect(){
effect.pct+=effect.speedPct;
}
function draw(){
ctx.clearRect(0,0,cw,ch);
ctx.beginPath();
ctx.arc(shooter.x,shooter.y,15,0,Math.PI*2);
ctx.closePath();
ctx.strokeStyle='green';
ctx.stroke();
ctx.beginPath();
ctx.arc(target.x,target.y,15,0,Math.PI*2);
ctx.closePath();
ctx.strokeStyle='red';
ctx.stroke();
if(effect.pct>1){return;}
var x=effect.x+effect.dx*effect.pct;
var y=effect.y+effect.dy*effect.pct;
ctx.beginPath();
ctx.arc(x,y,3,0,Math.PI*2);
ctx.closePath();
ctx.fillStyle='black';
ctx.fill();
}
body{ background-color: ivory; padding:10px; }
#canvas{border:1px solid red;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<button id=test>Animate 1 frame</button>
<br><canvas id="canvas" width=300 height=300></canvas>
I am currently writing a simple snake game.
http://jsfiddle.net/jhGq4/3/
I started with drawing the grid for the background
function fill_grid() {
ctx.beginPath();
var row_no = w/cw;
var col_no = h/cw;
for (var i=0;i<row_no;i++)
{
for (var j=0;j<col_no;j++)
{
ctx.rect(i*cw, j*cw, (i+1)*cw, (j+1)*cw);
ctx.fillStyle = 'black';
ctx.fill();
ctx.lineWidth = 1;
ctx.strokeStyle = '#135d80';
ctx.stroke();
}
}
}
It works great but when i paint the snake, the position gets wrong and the length is doubled. I tried to console.log the x position of my snake but they are correct.
function paint_cell(x, y)
{
console.log(x*cw);
console.log((x+1)*cw);
ctx.fillStyle = '#fff799';
ctx.fillRect(x*cw, y*cw, (x+1)*cw, (y+1)*cw);
ctx.lineWidth = 1;
ctx.strokeStyle = '#135d80';
ctx.strokeRect(x*cw, y*cw, (x+1)*cw, (y+1)*cw);
}
***Because someone wants to learn how to make a snake game,
this is my final solution for this game.
http://jsfiddle.net/wd9z9/
You can also visit my site to play:
use WSAD to play.
http://www.catoyeung.com/snake2/single.php
:D
I tested this alternative init function:
function init()
{
fill_grid();
// create_snake1();
// paint_snake1();
paint_cell(5, 5)
}
Which paints a square starting at coords (5,5), but of size 6x6.
I believe you are misusing the fillRect() method. Use
ctx.fillRect(x*cw, y*cw, cw, cw);
Instead of
ctx.fillRect(x*cw, y*cw, (x+1)*cw, (y+1)*cw);
the same probably applies to strokeRect.
Incidentally, I was looking at your grid-fill function. You fill i*j adjacent squares, which works, but you really only need i vertical lines and j horizontal ones - which is a lot less processing. Run a quicker loop with fewer calculations:
function fill_grid() {
ctx.beginPath();
ctx.fillStyle = 'black';
ctx.fillRect(0,0,w,h);
for (var i=0;i<=h;i+=cw)
{
ctx.moveTo(0,i);
ctx.lineTo(w,i);
ctx.moveTo(i,0);
ctx.lineTo(i,h);
}
ctx.stroke();
}
I would also only define line width and stroke colour once, as you initialise the canvas. You may not need to worry about this of course. But this kind of care can make a difference if you refresh the grid often to animate your snakes.