Canvas Cookbook - Sample Chapter
Canvas Cookbook - Sample Chapter
Canvas Cookbook - Sample Chapter
ee
Canvas Cookbook
The recipes are simple yet creative and build on each other. At every step, the book inspires the reader
to develop his/her own recipes. From basic to advanced, every aspect of Canvas API has been covered
to guide readers to develop their own application, presentation, or game.
it to animate shapes
Grasp the knowledge required to create
Canvas Cookbook
With the growing popularity of HTML5 Canvas, this book offers tailored recipes to help you develop
portable applications, presentations, and games.
Sa
pl
e
and videos
and problems
problems efficiently
real-world problems
$ 44.99 US
28.99 UK
P U B L I S H I N G
Canvas Cookbook
Over 80 simple but creative and structured recipes to explore
the capabilities of HTML5 Canvas
P U B L I S H I N G
Preface
The world of gaming is very competitive, and day by day the technology is evolving and
making things easier for users. HTML5 is a recent standard, which is flexible, interactive,
and portable. It is supported by most browsers. This makes HTML5 a good language for
developing applications with a wider reach.
The Canvas element in HTML5 is quite interesting as it allows programmers to render
whatever they can imagine. Canvas allows users to draw 2D and 3D objects and render
animation. HTML5 Canvas is therefore a suitable technology for developing applications
and games for a variety of devices.
However, without a scripting language, HTML5 Canvas, is of limited use. A scripting language
such as JavaScript is necessary to make use of HTML5 Canvas and is at the heart of any
application or game.
Any application without style is an ordinary application that will not catch the eye of a user.
Styling is important when it comes to developing applications commercially. It adds richness
to the application. CSS helps developers do this.
This book is all about the usage of HTML5 Canvas, JavaScript, and CSS in the development
of various recipes. The book starts with basic drawings on Canvas, graduates to animation
and 3D rendering, and culminates with the development of games that can run on different
devices. The recipes in each chapter are simple and crisp. The last few chapters exhibit the
usage of third-party libraries such as Three.js and Phaser.js.
All recipes are supported with a precise explanation to inspire the reader to develop his or
her own recipes.
Preface
Drawing rectangles
Drawing triangles
Drawing circles
Drawing gradients
Drawing an ellipse
Demonstrating compositions
Drawing a mouse
Introduction
In this chapter, we will learn how to draw rectangles, triangles, circles, ellipses, and custom
shapes. Also, we will learn to fill gradients, translation, rotation, and scaling to be applied on
these shapes.
The recipe structure will be a bit different in this chapter. We will have the JavaScript code in
a separate file and this file will be embedded in the HTML code at run-time. In the previous
chapter, the complete recipe was in a single file (.html file). However, in this chapter, a single
recipe will comprise two different files:
An HTML file
A JavaScript file
39
Drawing rectangles
There are three different functions in the canvas API to draw rectangles. They are:
rect(xPos,yPos,width,height)
fillRect(xPos,yPos,width,height)
strokeRect(xPos,yPos,width,height)
Let's see these all together in a single recipe. So here is the output of our first recipe:
How to do it
The output that shows three different rectangles, uses a call to three different functions,
which are explained further. The recipe is as follows.
An HTML file that includes the canvas element:
<html>
<head>
<title>Rectangles</title>
<script src="Rectangles.js"></script>
</head>
<body onload="init()" bgcolor="#FFFFCC">
<canvas id="canvas" width="250" height="200" style="border:2px solid
blue;" >
your browser does not support canvas
</canvas>
<H1>Rectangles</H1>
</body>
</html>
40
Chapter 2
The JavaScript file as mentioned in the <script> tag in the previously given code:
function init()
{
var canvas = document.getElementById("canvas");
if(canvas.getContext)
{
// Color of drawing, fillStyle is this color
var ctx = canvas.getContext("2d");
// Draw a square(rectangle with same sides)
// from top left corner x,y, width, height
ctx.strokeStyle="purple"
ctx.rect(10,10,70,50);
ctx.fillStyle="lightgreen";
ctx.fill();
ctx.stroke();
//draw another rectangle
ctx.fillStyle="crimson";
ctx.fillRect (50,25, 100,100);
//draw yet another
ctx.strokeStyle="blue";
ctx.lineWidth=10;
ctx.strokeRect(100,60,80,130);
}
}
How it works...
This is what you can observe in the output of the recipe:
The top-most blue bordered rectangle is drawn using the strokeRect() function
The second red colored rectangle is drawn using the fillRect() function
The first green colored rectangle is drawn using the rect() and fill() functions
The property fillStyle decides the color for filling the rectangle. The strokeStyle
property decides the color of the border.
41
Description
Width
Height
Drawing triangles
There is no direct function to draw a triangle using the canvas API. But we do have the other,
simpler functions that, together, allow us to draw different shapes. A triangle is a combination
of three joined lines. Let's see this in our new example. The output is quite simple and looks
like this:
42
Chapter 2
How to do it
The triangle is drawn by calling two basic functions, namely moveTo() and lineTo(). Here
is the recipe.
The HTML file:
<html>
<head>
<title>triangles</title>
<script src="triangles.js"></script>
</head>
<body onload="init()">
<canvas id="MyCanvasArea" width="200" height="200" style="border:2px
solid blue;" >
your browser does not support canvas
</canvas>
<H1>Triangle</H1>
</body>
</html>
43
How it works...
The init() function calls the drawTriangle() method. The parameters passed for drawing
the triangle are the X position, Y position, the width and height of the triangle, and the color for
filling the triangle. The triangle drawing starts by calling the beginPath() function and ends
on the call of the endPath() function. The moveTo() function takes you to the position from
where you want to draw the triangle. Then, using the width and height, a line is drawn using
the simple lineTo() function. Another line is drawn from there. The closePath() function
completes the triangle by joining the last coordinate with the first one. The fillStyle
property and fill() method does the job of filling the triangle with a color.
There's more...
Try the following:
Instead of filling the triangle, only draw the triangle with boundaries. Use
strokeStyle and stroke() before closePath().
Place the stroke() method call after closePath() and check the output.
Drawing circles
Again, there is no direct function to draw a circle. It should be drawn using the function for
drawing an arc. We saw a drawing of a circle in the previous chapter through the example
of drawing arc2. The output of the circle recipe looks like this:
44
Chapter 2
How to do it
The recipe is very simple. It calls the drawCircle() function in a loop to draw multiple
circles as you see here. The recipe is as follows.
The HTML code:
<html>
<head>
<title>circles</title>
<script src="circles.js"></script>
</head>
<body onload="init()">
<canvas id="MyCanvasArea" width="300" height="300" style="border:2px
solid blue;" >
your browser does not support canvas
</canvas>
<h1>Circles</h1>
</body>
</html>
How it works...
The init() function calls the drawCircle() function, which in turn calls the arc() function
with the necessary parameters to draw an arc from 0 degrees to 360 degrees, which completes
a circle. Since the start and end angle to be passed in the arc() method must be in radians,
the degrees are converted to radians. The formula used is: radian = degree * /180. The border
color and fill style are also specified.
The x and y coordinates and the radius value are specified in the for loop. The loop runs six
times, drawing six circles at different positions and of different sizes. In every iteration, the
value of x, y, and r changes (namely, the position and radius).
There's more...
Try the following:
Drawing gradients
Here we implement some effects. Applying a gradient is quite a colorful activity. The output of
our recipe demonstrating gradients looks like this:
46
Chapter 2
How to do it
The recipe uses four new methods, namely createRadialGradient(),
createLinearGradient(), addColorStop(), and rgb(). The recipe is as follows.
The HTML code:
<html>
<head>
<title>Gradients</title>
<script src="gradients.js"></script>
</head>
<body onload="init()">
<canvas id="MyCanvasArea" width="500" height="200" style="border:2px
solid blue;" >
your browser does not support canvas</canvas>
<h1>Radial and Linear Gradient</h1>
</body>
</html>
How it works...
The new methods and their purpose are listed in the following table:
Function
addColorStop(offset,color)
createLinearGradient(xPos1,yP
os1,xPos2,yPos2)
Description
This method can be called for a gradient to add
the color and the value of offset (between 0 and 1)
to indicate the percentage of color to be applied in
the area specified for the gradient.
This function allows the creation of the area in
which the gradient can be applied. The area can
be created by specifying the coordinates.
Note: If x1 and x2 are the same then the vertical
gradient can be applied. If y1 and y2 are the
same, a horizontal gradient can be applied.
createRadialGradient(x1,y1,r1
,x2,y2,r2)
rgb(value_for_red,value_for_
green,value_for_blue)
48
Chapter 2
Radial gradient
Observe the first rectangle in the output, and you will understand that at the center of the circle
there is a bluish shade. The next concentric circle has an orange shade, and towards the outer
side of the circle you will observe a greenish shade. This is because of the following snippet:
radGrad.addColorStop(0,'rgb(110,120, 255)');//bluish shade
radGrad.addColorStop(0.5,'rgb(255,155,20)');//orange shade
radGrad.addColorStop(1,'rgb(0, 255,220)');//green shade
But then, what is radGrad? radGrad is the radial gradient created using the arguments
specifying the centers of two circles (starting and ending) and their radius. radGrad is
created by calling the createRadialGradient() function.
Linear gradient
The linear gradient is created by calling the createLinearGradient() function. The
function allows specifying the starting coordinate and the ending coordinate. This defines
a rectangular portion where the gradient is applied. Any drawing in this area will be filled
with the gradient colors available in that area. If the drawing is drawn beyond the gradient
area, then the color towards that end of the gradient will be applied to the drawing. You will
definitely understand this paragraph when you see our next recipe.
In the current recipe there are two types of gradient, namely horizontal and vertical.
The following code applies the horizontal gradient:
var linGrad1 = ctx.createLinearGradient(220,0,320,0);
linGrad1.addColorStop(0,'rgb(255,0,0)');//red
linGrad1.addColorStop(0.5,'rgb(0,255,0)');//green
linGrad1.addColorStop(1,'rgb(0,0,255)');//blue
Observe the coordinates. The y1 and y2 values are the same. It means that the gradient is
along the x axis, the width being 100(320-220). So the red, green, and blue colors are
applied in this region. Now, a rectangle with an x coordinate between 220 and 320 is drawn
on the canvas, and can be filled with the gradient specified previously. This is done by the
following code in our recipe:
ctx.fillStyle = linGrad1;
ctx.fillRect(220,10,100, 100);
Note that the coordinates of the rectangle starting from 220, 10 are inside
the region specified in the gradient linGrad1.
Technically, the vertical gradient is not much different from the horizontal gradient. Here, the
x values of both the coordinates specified in the createLinearGradient() function are
the same, while the y values differ, specifying the region along the y axis.
49
There's more...
Try the following:
For the radial gradient, change the value of y2 (y value of the center coordinates of
the second circle) to 50
How to do it
The recipe is given as follows.
The HTML code:
<html>
<head>
<title>Clouds</title>
<script src="clouds.js"></script>
</head>
<body onload="init()">
<canvas id="MyCanvasArea" width="800" height="300" style="border:2px
solid blue;" >
your browser does not support canvas</canvas>
<h1>Cloudy Sky</h1>
</body>
</html>
50
Chapter 2
The JavaScript code:
var can;
var ctx;
var color;
function init()
{
can=document.getElementById("MyCanvasArea");
ctx=can.getContext("2d");
//set the gradient
color=ctx.createLinearGradient(0, 0, can.width, can.height);
color.addColorStop(0,'white');
color.addColorStop(0.5,'grey');
color.addColorStop(1,'black');
//draw the first cloud
var xfactor=0;
drawCloud(xfactor);
//draw the second cloud
xfactor=150;
drawCloud(xfactor);
//draw third cloud
xfactor=xfactor+150;
drawCloud(xfactor);
//draw the fourth cloud
xfactor=xfactor+150;
drawCloud(xfactor);
//draw the fourth cloud
xfactor=xfactor+150;
drawCloud(xfactor);
//rectangle to just show the gradient
ctx.rect(0,150,can.width,130);
ctx.fill();
}
function drawCloud(xfactor)
{
ctx.beginPath();
51
How it works...
The function drawCloud() is called multiple times in the code. The xfactor variable is
changed to shift the cloud along the x axis.
Translation means changing the position of the origin (0,0) of the context
Scaling means changing the size of the drawing along the x axis and/or along
the y axis
All three techniques are demonstrated in our new recipe whose output looks like this:
52
Chapter 2
How to do it
The following code does the job.
The HTML code:
<html>
<head>
<title>Translate, rotate and scale</title>
<script src="TRS.js"></script>
</head>
<body onload="drawTRS();">
<table border="1" align="center" bgcolor="lightyellow">
<caption><b>Translation, Rotation and Scaling</b></caption>
<tr>
<td><canvas id="can0" width="300" height="200"></canvas><br/>
<b><label id="lbl0"></label></b>
</td>
<td><canvas id="can1" width="300" height="200"></canvas><br/>
<b><label id="lbl1"></label></b>
</td>
<td><canvas id="can2" width="300" height="200"></canvas><br/>
<b><label id="lbl2"></label></b>
</td>
</tr>
</table>
</body>
</html>
53
How it works...
There are three different functions to do these three tasks of translation, rotation, and scaling:
The rotation happens by calling the rotate (angle) function. The angle has to be in
radians. Calls to this function shift the origin in an angular direction, depending on
the value. In our recipe, the angle is 20 degrees and the shift is clockwise.
Just imagine pressing both of your palms on a sheet of paper and moving your hands
in a clockwise direction by a small angle. Thus, the paper will also change its angle.
There's more...
Try the following:
54
Chapter 2
Drawing an ellipse
Drawing an ellipse is just an implementation of translation and scaling. The output is
quite simple:
How to do it
The recipe goes like this.
The HTML code:
<!DOCTYPE HTML>
<html>
<head>
</head>
<body onload="init()">
<canvas id="myCanvas" width="578" height="200" style="border:3px solid
blue"></canvas>
<script src="ellipse.js">
</script>
</body>
</html>
How it works...
Observe that the translate() and scale() functions are used to do this drawing. First,
the origin is shifted by using the translate() function. Later, the scaling is applied. And
then a circle is drawn using the arc() function.
56
Chapter 2
How to do it
The recipe for the previous output goes like this.
The HTML code:
<html>
<head>
<title>Canvas Save And Restore</title>
<script src="CanvasSaveRestore.js"></script>
</head>
<body onload="CanvasSaveRestore()">
<canvas id="MyCanvasArea" width="500" height="200" style="border:2px
solid blue;" >
your browser does not support canvas
</canvas>
<h1>Canvas Save And Restore</h1>
</body>
</html>
57
How it works...
The first rectangle is drawn using certain styles and effects. This state of canvas is stored in
the stack at position 1 (refer to the output). Then the other rectangle is drawn with different
settings and this state is saved at position 2, which is above 1. The same happens with the
third triangle. The saving of state happens using the save() method.
While restoring the state of canvas from the stack, whatever is on the top of the stack is
removed and used. So the state at position 3 on the stack is used to draw the next rectangle.
The next rectangle then uses the state at position 2, as the state at position 3 has already been
removed and used. Finally, the state stored at position 1 is used to draw the last rectangle.
58
Chapter 2
Demonstrating composites
Composite operations allow you to change how the new content is drawn on an HTML5
<canvas> element. New things appear over whatever has already been drawn. By changing
the global composite operation, you can draw new shapes behind existing ones, perform
boolean operations, and do some other neat things.
The two main components in a compositing operation are the destination and the source.
The destination is what is already on the canvas, and the source is what is getting drawn
onto the canvas.
The following is a description for each possible composite operation available with the
HTML5 Canvas API, where the text Be happy represents the source (S), and the green
rectangle represents the destination (D). To further develop your understanding of composite
operations, it helps to look at the corresponding operation while reading each description:
Operation
Description
source-atop (S atop D)
source-in (S in D)
source-out (S out D)
destination-atop (S atop D)
destination-in (S in D)
destination-out (S out D)
destination-over (S over D)
59
Description
lighter (S plus D)
xor (S xor D)
copy (D is ignored)
destination + source
destination-over
source + destination
source-in
destination-in
source-out
source destination
destination-out
destination source
source-atop
destination-atop
lighter
darker
xor
source ^ destination
copy
source
60
Chapter 2
How to do it
The recipe goes like this.
The HTML code:
<html>
<head>
<title>Composites</title>
<script src="composites.js"></script>
</head>
<body onload="drawComposites();">
<table border="1" align="center" bgcolor="lightyellow">
<caption><b>Composites with Shapes</b></caption>
<tr>
<td><canvas id="can0" width="200" height="100"></canvas><br/>
<b><label id="lbl0"></label></b>
</td>
<td><canvas id="can1" width="200" height="100"></canvas><br/>
<b><label id="lbl1"></label></b>
</td>
<td><canvas id="can2" width="200" height="100"></canvas><br/>
<b><label id="lbl2"></label></b>
</td>
</tr>
<tr>
<td><canvas id="can3" width="200" height="100"></canvas><br/>
<b><label id="lbl3"></label></b>
</td>
<td><canvas id="can4" width="200" height="100"></canvas><br/>
<b><label id="lbl4"></label></b>
</td>
<td><canvas id="can5" width="200" height="100"></canvas><br/>
<b><label id="lbl5"></label></b>
</td>
</tr>
61
62
Chapter 2
ctx.fillStyle="blue";
ctx.font="40px ComicSans";
ctx.fillText("Be Happy",20,60);
}
}
How it works...
The HTML code contains a table of four rows and three columns, thereby producing 12 cells
(0 to 11). There is a canvas and label element in each of the cells (within the <TD> tag). These
elements are captured in the JavaScript code in a loop that iterates for every composition
type. The types are mentioned in the array, and the globalCompositeOperation property
is assigned with the composite type before drawing the source.
Drawing a mouse
This recipe is an implementation of multiple functions demonstrated so far. The output looks
like this:
How to do it
The recipe is as follows.
The HTML code:
<html>
<head>
<title>Mouse</title>
<script src="mouse.js"></script>
</head>
63
64
Chapter 2
ctx.strokeStyle = borderColor;
ctx.fillStyle
= fillColor;
ctx.lineWidth
= borderwidth;
ctx.beginPath();
ctx.arc(xPos, yPos, radius, startAngle, endAngle, false);
ctx.fill();
ctx.stroke();
}
function drawArc(ctx,xPos,yPos,radius,startAngle,endAngle,
anticlockwise,lineColor, fillColor){
var startAngle = startAngle * (Math.PI/180);
var endAngle
= endAngle
* (Math.PI/180);
var radius = radius;
ctx.strokeStyle = lineColor;
ctx.fillStyle
= fillColor;
ctx.lineWidth
= 2;
ctx.beginPath();
ctx.arc(xPos,yPos,radius,startAngle,endAngle,anticlockwise);
ctx.fill();
ctx.stroke();
}
function drawTriangle(ctx, x, y,Width,Height,color){
ctx.beginPath();
ctx.moveTo(x, y);
ctx.lineTo(x + Width / 2, y + Height);
ctx.lineTo(x - Width / 2, y + Height);
ctx.closePath();
ctx.fillStyle = color;
ctx.fill();
}
function drawBezierCurve(ctx,xstart,ystart,xctrl1,yctrl1,xctrl2,yctrl2
,xend,yend,color){
ctx.strokeStyle=color;
ctx.lineWidth=4;
ctx.beginPath();
ctx.moveTo(xstart,ystart);
ctx.bezierCurveTo(xctrl1,yctrl1,xctrl2,yctrl2,xend,yend);
ctx.stroke();
}
65
How it works...
The previous recipe follows these steps:
1. The different shapes to be sent behind the larger ellipse are drawn first.
2. Then the translation and scaling is applied so that ellipses can be drawn.
3. The state is restored and then the remaining shapes are drawn above the
larger ellipse.
Observe that the coordinates used before translation and scaling differ from those used after
the effects.
66
www.PacktPub.com
Stay Connected: