Let's take a look at how we can draw graphics on our Canvas Element.
On the right you see the finished dog. To create this we write a function that will draw it in parts. We may want to draw more dogs that are each a different color, and we may want to put them in different places on the canvas. To do that, we will set up some parameters that will allow us to pass three variables to the function.
To begin, we will set up our colors. As you will recall in an earlier post, these colors are all set up so that the first byte of each pixel is a unique value. Also none of them have a zero in the first byte. This will be important later when we start racing our dogs and we want to know which one is the winner.
We make sure that these variables are defined outside of all functions. That will make them global variables, which means every function can use them.
var canvasLeft = 120;
var myRed = "#FE0000"; //red - first value is 254
var myBlue = "#0200DD"; //blue - first value is 2
var myYellow = "#FCFF00"; //yellow - first value is 252
var myMagenta = "#660066"; //magenta - first value is 253
var myOrange = "#FF6600"; //orange is - first value is 255
var myGreen = "#06FF00"; //green is - first value is 6
var myBrown = "#993300"; //brown is - first value is 153
var myBackground = "#007777"; //background -- first value is 0
Now we are ready to create the function. Here is how we are going to call it:
drawDog(myGreen, canvasLeft + 20, 10);
We choose anyone of our colors. Next we tell the function how far to the right we want to draw. This is our X reference and it will always be linked to the variable canvasLeft. This means that we can change one value and shift all of our graphics left or right on the screen. The Y value is always linked to 0, the top of our canvas. These two coordinates form the X,Y location for the graphic. All the pieces will be relative to them when we start drawing.
Here is how we would define the function:
function drawDog(thisColor, dogX, dogY){ ....}
You can put the following sections into your own script and test them out, or you might simply copy the whole thing that is listed at the bottom and then use Firebug to step through the script and see how each part comes together.
Let's start with the dog's tail. The graphic is created by starting and ending a path. We draw a simple line. We set the width of the line as 3 pixels. The tail of the dog will be black, no matter what color the body is. We just a moveTo and a lineTo to create the graphic. The first determines where we start and draws no line. The second draws the line to the end point. Notice that as you step through the code, the line does not appear until the final line ctx.stroke(); is executed.
// draw tail
ctx.beginPath();
ctx.lineWidth = 3;
ctx.strokeStyle = 'black';
ctx.moveTo(dogX + 5,dogY+32);
ctx.lineTo(dogX-10,dogY + 25);
ctx.closePath();
ctx.stroke();
To create the body, we will draw three rectangles. Now we will switch to the color that was passed into the function. We do that with ctx.fillStyle = thisColor;
Each of the three rectangles are referenced to the dogX and dogY coordinates that we passed to the function along with the color. The values used in the rectangle refer to these four parts: (location X, location Y, width, height). So the first two values are the location of the the upper left corner of the rectangle. The last two values define it's size.
As you step through the code, you will see, again, that nothing appears until the final line: ctx.fill();
// draw body
ctx.fillStyle = thisColor;
ctx.beginPath();
ctx.rect(dogX+8,dogY + 30,24,16);
ctx.rect (dogX,dogY + 35, 10, 25);
ctx.rect (dogX + 30,dogY + 35, 10, 25);
ctx.fill();
Now we will round out the two ends of the dog. The reason we put the tail in first, is so that we can cover the doggy end with this semi-circle and make it look like it was shaped exactly to match the curve.
We will use ctx.arc() to draw two semicircles. They look like northern hemispheres cut off below the equator. We lay them onto of the body so it only looks like a quarter circle, but it was easier to use the same code twice. The only thing that changes is the X coordinate.
ctx.arc(dogX + 8, dogY + 38, 8, 0, 2*Math.PI, true);
ctx.arc(dogX + 32, dogY + 38, 8, 0, 2*Math.PI, true);
ctx.closePath();
ctx.fill();
That arc stuff can look confusing. The first two values are the X, Y location of the center of a circle. You have to watch out for that when putting them together with rectangles. Rectangles are referenced from their corner, circles from the middle!
The third value is the radius of the circle: 8 pixels.
The next two determine beginning and ending points of the arc. Here's an image from w3schools.com that explains it all.
The last value, true, simply determines whether we are drawing clockwise or counter-clockwise.
ctx.arc(dogX + 8, dogY + 38, 8, 0, 2*Math.PI, true);
ctx.arc(dogX + 32, dogY + 38, 8, 0, 2*Math.PI, true);
ctx.closePath();
ctx.fill();
To do the dog's head, we will add another full circle a smaller half circle. Then we dress it up with a black nose, eye and ear.
// draw head
ctx.beginPath();
ctx.arc(dogX + 36, dogY + 22, 8, 0, 2*Math.PI, true);
ctx.closePath();
ctx.fill();
ctx.beginPath();
ctx.arc(dogX + 40, dogY + 22, 8, 0, Math.PI, false);
ctx.closePath();
ctx.fill();
// draw nose
ctx.fillStyle = 'black';
ctx.beginPath();
ctx.rect(dogX +46,dogY +22,3,3);
ctx.closePath();
ctx.fill();
// draw eye
ctx.beginPath();
ctx.rect(dogX +40,dogY +20,3,3);
ctx.closePath();
ctx.fill();
// draw ear
ctx.beginPath();
ctx.arc(dogX + 30, dogY + 18, 4, Math.PI, 0.2 *Math.PI, false);
ctx.closePath();
ctx.fill();
You can copy and paste the whole code below into your editor and experiment the script. You will see that I have moved the code from earlier that cleared our canvas into it's own function and set it up so we can pass a color to it as well. This will allow you to try different background colors and do some creative messing around. If you play with the background, remember that the first byte will need to be 00 for our animation needs later.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="generator" content="CoffeeCup HTML Editor (www.coffeecup.com)">
<meta name="description" content="">
<meta name="keywords" content="">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="viewport" content="width=device-width; initial-scale=1.0; user-scalable=1;">
<title>Dog Race</title>
<style>body{color:#FFFFFF}</style>
<script type="text/javascript">
var canvasLeft = 120;
var myRed = "#FE0000"; //red - first value is 254
var myBlue = "#0200DD"; //blue - first value is 2
var myYellow = "#FCFF00"; //yellow - first value is 252
var myMagenta = "#660066"; //magenta - first value is 253
var myOrange = "#FF6600"; //orange is - first value is 255
var myGreen = "#06FF00"; //green is - first value is 6
var myBrown = "#993300"; //brown is - first value is 153
var myBackground = "#007777"; //background -- first value is 0
function canvasDogRaces(){
// Get the canvas element.
canvas = document.getElementById("myCanvas");
// Make sure you got it.
if (canvas.getContext){
ctx = canvas.getContext("2d");
clearCanvas(myBackground);
drawDog(myGreen, canvasLeft + 20, 10);
drawDog(myYellow, canvasLeft + 20, 70);
drawDog(myBrown, canvasLeft + 20, 130);
drawDog(myRed, canvasLeft + 20, 190);
drawDog(myBlue, canvasLeft + 20, 250);
drawDog(myMagenta, canvasLeft + 20, 310);
}else{
alert("Your browser does not\n support 'Canvas'");
}
}
function drawDog(thisColor,dogX,dogY){
// draw tail
ctx.beginPath();
ctx.lineWidth = 3;
ctx.strokeStyle = 'black';
ctx.moveTo(dogX + 5,dogY+32);
ctx.lineTo(dogX-10,dogY + 25);
ctx.closePath();
ctx.stroke();
// draw body
ctx.fillStyle = thisColor;
ctx.beginPath();
ctx.rect(dogX+8,dogY + 30,24,16);
ctx.rect (dogX,dogY + 35, 10, 25);
ctx.rect (dogX + 30,dogY + 35, 10, 25);
ctx.fill();
ctx.arc(dogX + 8, dogY + 38, 8, 0, 2*Math.PI, true);
ctx.arc(dogX + 32, dogY + 38, 8, 0, 2*Math.PI, true);
ctx.closePath();
ctx.fill();
// draw head
ctx.beginPath();
ctx.arc(dogX + 36, dogY + 22, 8, 0, 2*Math.PI, true);
ctx.closePath();
ctx.fill();
ctx.beginPath();
ctx.arc(dogX + 40, dogY + 22, 8, 0, Math.PI, false);
ctx.closePath();
ctx.fill();
// draw nose
ctx.fillStyle = 'black';
ctx.beginPath();
ctx.rect(dogX +46,dogY +22,3,3);
ctx.closePath();
ctx.fill();
// draw eye
ctx.beginPath();
ctx.rect(dogX +40,dogY +20,3,3);
ctx.closePath();
ctx.fill();
// draw ear
ctx.beginPath();
ctx.arc(dogX + 30, dogY + 18, 4, Math.PI, 0.2 *Math.PI, false);
ctx.closePath();
ctx.fill();
}
function clearCanvas(thisColor){
ctx.fillStyle = thisColor;
ctx.rect(canvasLeft,0,600,400);
ctx.fill();
}
</script>
</head>
<body onload="canvasDogRaces()" bgcolor="#339999">
<h3>
<div id="rowOne_text">Welcome to the Races</div>
<div id="rowTwo_text">Pick Your Dog</div>
</h3>
<canvas id="myCanvas" width="840" height="400" ;">
</canvas>
</body>
</html>
No comments:
Post a Comment