Html5 Tutorial : Canvas
-
Static images in a browser are supported since a long time using
<img> - What about dynamic graphics? There is no native support for that.
Current solutions are:
- Using plugins such as Flash, Silverlight, JavaFX
- VML (Vector Markup Language) only works in IE
-
HTML5 comes with the
<canvas>element which provides a JavaScript API for 2D drawing (from basics shapes to complex paths) in the browser - The Canvas element is part of the HTML5 specification but the Canvas 2D API itself has its own specification
- There is one main alternative to Canvas that you often hear about: SVG (Scalable Vector Graphics)
- Both Canvas and SVG allow graphic manipulation in the browser but it is two different techniques
Depending on the kind of graphics application you want to do, you want to consider the following characteristics:
Table 1. Canvas VS. SVG
Canvas
SVG
Advantages
- High performance graphics
- Pixel-level manipulation
- Constant performance depending on the resolution used
- Canvas drawing surface can be saved as an image file
- Vector-based, scalable to any resolution
- Good support for animations
- DOM manipulated elements
Drawbacks
- No API for animation, You have to redraw every time
- Pixel-manipulation: impossible for shape you create to respond to events
- Not scalable
- Not suited for user interfaces
- Works with the DOM so with a lot of elements it gets slower
- Not suited for gaming applications
When the canvas is not supported in the browser, the only fallback we have is what we can nest inside the
<canvas>element:<canvas> Text which is displayed if your browser does not support the canvas element... </canvas>
We can insert text string and images in a canvas but:
- There is no way to provide alternative text for images used in a canvas
- Other thing is that a text in a canvas is just a collection of pixels there is no way to copy paste the text displayed or access it in the DOM.
- Accessibility in canvas element so far just needs more work
To use the canvas element in a web page, we would do the following:
<canvas width="533px" height="300px" id="mycanvas"></canvas>
![[Note]](../images/note.png)
Note This is all you have to do in HTML to use a canvas. Now, if you want to access your canvas and draw on it, you have to use JavaScript.
- All drawing operations on a canvas happen in in the canvas’s context: its 2D context.
Use JavaScript to get the canvas’s context:
var ctx = document.getElementById("mycanvas").getContext("2d");- Now that we obtained the context we will be able to perform drawing methods on it.
Before getting into drawing operations and transformations, let us see how coordinates works on a canvas:
![[Note]](../images/note.png)
Note Coordinates on a canvas are expressed in pixels
Canvas supports only one basic shape: Rectangle
![[Note]](../images/note.png)
Note We are going to see how to draw more things than rectangles using paths later.
Filled rectangle:
var ctx=document.getElementById("mycanvas").getContext('2d');
ctx.fillRect(50,50,100,200); 
Stroked rectangle:
var ctx=document.getElementById("mycanvas").getContext('2d'); ctx.strokeRect(50,50,100,200);
- To draw shapes that are more complex than rectangles, we need to use paths.
- Think of a path as a collection of pixels going from a starting point to an ending point.
- A path can also be composed of subpaths.
Four methods are used when dealing with paths:
-
beginPath(): To start a new path -
closePath(): To close the current path -
stroke(): To stroke the path fill(): To fill the path![[Note]](../images/note.png)
Note When we will draw on the canvas, the default color is black. We can change that by using CSS colors with the two following context properties:
fillStyleandstrokeStyle. For instancectx.fillStyle='rgb(255,0,0)';would define the filling color as red.
-
Consider these two main methods to draw straight lines:
-
moveTo(x,y): Starting point of the line we want to draw. Think of this method as lifting the "pencil" to the specified coordinate. -
lineTo(x,y): Think of this method as drawing the path from the previous specified point to this one.
-
Here is how you would draw a path using three lines:
var ctx=document.getElementById("mycanvas").getContext('2d'); ctx.beginPath(); ctx.moveTo(0,0); ctx.lineTo(50,50); ctx.lineTo(100,0); ctx.lineTo(150,50); ctx.lineTo(200,0); ctx.lineTo(250,50); ctx.stroke();
To draw a circle or an arc, we are going to use the
arc(x, y, radius, startAngle, endAngle)method:-
xandybeing the coordinates of the center of the circle/arc in pixels -
radiusbeing the radius of your circle/arc in pixel -
startAnglebeing the starting angle of the circle/arc in radians -
endAnglebeing the ending angle of the circle/arc in radians
-
An example of how to draw a filled circle would be:
var ctx=document.getElementById("mycanvas").getContext('2d'); ctx.beginPath(); ctx.arc(265,150,75,0,Math.PI*2);
ctx.fill(); 
Here for instance, this will represent a full circle. Again, we have the choice to either draw a filled circle or a stroked circle.
We have seen how to draw shapes and lines made of paths.
- Drawing text is still drawing a path
- Like other shapes we have just discussed, we can have a filled text or stroked text
Let us see how it works:
var ctx=document.getElementById("mycanvas").getContext('2d'); ctx.beginPath(); ctx.textAlign="center";
ctx.font="italic 50px verdana";
ctx.fillText("Hello World!", 265, 150); 
To draw an image on a canvas, we have three methods available:
-
drawImage(image, dx, dy): draws the specifiedimageon the canvas at coordinates (dx,dy) without resizing the image -
drawImage(image, dx, dy, dw, dh): draws the specifiedimageon the canvas at coordinates (dx,dy) with the widthdwand the heightdh -
drawImage(image, sx, sy, sw, sh, dx, dy, dw, dh): Here we have the ability to select a rectangle region on the image. This selected region has its top-left corner located at (sx,sy), a widthswand a heightsh. This selected region of the image will be drawn on the canvas at the top-left corner coordinate (dx,dy) with a widthdwand a heightdh
-
Let us see an example of that. I want to just select the head of this wonderful leopard (in reality: 346px by 400px):
To do that, I could write the following code:
<!DOCTYPE html> <html lang="en"> <head> <meta charset=utf-8 /> <title>HTML5 Example: Canvas</title> <script> function drawOnCanvas() { var ctx=document.getElementById("mycanvas").getContext('2d'); var image=new Image(); image.src="leopard.png"; image.onload=function() { ctx.drawImage(image,140,0,206,183,0,0,206,183); } } window.addEventListener('load', drawOnCanvas, true); </script> </head> <body> <canvas width="346px" height="400px" id="mycanvas"></canvas> </body> </html>
- It is possible to get the pixels data from a canvas
You can imagine the different kind of web application you can create:
- Image filters
- Facial recognition application
- Etc…
context.getImageData(sx,sy,sw,sh)gets the image data of a selected region and returns aImageDataobject-
(
sx,sy) being the top-left coordinate of the selected region -
swandshbeing the width and the height of the selected region
-
(
-
The
ImageDataobject contains thewidth, theheightand thedataproperties. The
dataproperty is aCanvasPixelArraycontaining pixels informationsEach pixel is composed of four channels: the red, blue, green and the alpha transparency channel
[r1,g1,b1,a1,r2,g2,b2,...,a2,rN,gN,bN,aN]
![[Warning]](../images/warning.png)
Warning data.lengthwill not give you the number of pixels since the array has four channels for each pixel!data.length/4will give you the number of pixels
This is, for instance, how we would create a green color filter for our previous leopard:
<!DOCTYPE html> <html lang="en"> <head> <meta charset=utf-8 /> <title>HTML5 Example: Canvas</title> <script> function drawOnCanvas() { var canvas=document.getElementById("mycanvas"); var ctx=canvas.getContext('2d'); var image=new Image(); image.src="leopard.png"; image.onload=function() { ctx.drawImage(image,0,0);
var pixels=ctx.getImageData(0,0,canvas.width,canvas.height);
for (var i = 0, n = pixels.data.length; i < n; i += 4){
pixels.data[i+0] = 0;
pixels.data[i+1] = 255 - pixels.data[i+1];
pixels.data[i+2] = 0;
}
ctx.putImageData(pixels,0,0);
}
}
window.addEventListener('load', drawOnCanvas, true);
</script>
<style type="text/css">
#mycanvas {
border-style:solid;
}
</style>
</head>
<body>
<canvas width="346px" height="400px" id="mycanvas"></canvas>
</body>
</html>We have to draw the image on the canvas so we can get the image data later Here we get the image data from the whole canvas area Red channel Green channel Blue channel We have to put the pixels back in the canvas if we want to see the result by using
putImageData
-
Before we dive into tranformations, we are going to discuss two important methods:
save()andrestore() These two methods are used to save and restore the context’s state
- The state of the canvas contains the current style and transformations applied
The canvas maintain a stack of states:
-
Calling
save()pushes the current state on the top of the stack -
Calling
restore()takes out the top state of the stack to use it
![[Note]](../images/note.png)
Note Using
save()andrestore()will save you a lot of headaches and lines of code.-
Calling
- There are a lot of transformations you can apply on your canvas: translation, rotation, scaling, etc…
-
The
translate(x,y)method moves the canvas and its origin to a specified point in the canvas. This point will become the new origin (0,0) Below is an example showing that, we will first draw an horizontal line and then draw it again using a translation:
<script> function drawOnCanvas() { var canvas=document.getElementById("mycanvas"); var ctx=canvas.getContext('2d'); ctx.save();
ctx.strokeStyle='rgb(51,153,255)';
ctx.translate(0,100);
drawLines(ctx);
ctx.restore();
drawLines(ctx);
}
function drawLines(context) {
context.beginPath();
context.moveTo(0,0);
context.lineTo(50,50);
context.lineTo(100,0);
context.lineTo(150,50);
context.lineTo(200,0);
context.lineTo(250,50);
context.stroke();
}
window.addEventListener('load', drawOnCanvas, true);
</script>This saves the current context Calling the translatemethod moves the canvas and its origin to the new specified pointThis function draws the same path (The blue stroked path is the one draw with the translation. The black stroked path is the one drawn after calling restore, there is no translation for this one)This restores the previous saved state
The
rotate(angle)method performs a clockwise rotation of the canvas around its origin (0,0) with ananglein radians![[Note]](../images/note.png)
Note To move the center of the rotation, you would perform a translation of the origin before
We can easily use the previous example and apply a rotation instead of a translation this time:
<script> function drawOnCanvas() { var canvas=document.getElementById("mycanvas"); var ctx=canvas.getContext('2d'); ctx.save(); ctx.strokeStyle='rgb(51,153,255)'; ctx.rotate(Math.PI/4);
drawLines(ctx);
ctx.restore();
drawLines(ctx);
}
function drawLines(context) {
context.beginPath();
context.moveTo(0,0);
context.lineTo(50,50);
context.lineTo(100,0);
context.lineTo(150,50);
context.lineTo(200,0);
context.lineTo(250,50);
context.stroke();
}
window.addEventListener('load', drawOnCanvas, true);
</script>
The
scale(x,y)method modify the units of our canvas-
For instance calling
scale(1,2)means that 1 pixel on theyaxis would correspond to 2 pixel on the canvas
-
For instance calling
Let us modify the scaling and then draw a circle and see how oval the circle will be:
var ctx=document.getElementById("mycanvas").getContext('2d'); ctx.save(); ctx.scale(1,0.5);
ctx.beginPath();
ctx.arc(200,100,50,0,Math.PI*2);
ctx.stroke();
Firefox 3.5+, Safari 4.0+, Chrome 6.0+ and Opera 10.5+ support Canvas
![[Note]](../images/note.png)
Note Canvas is also supported in Firefox 3.0 except for drawing text.
![[Note]](../images/note.png)
Note Canvas can be supported in Internet Explorer using a third-party JavaScript library called
explorercanvas. You can then use<!--[if IE]>...<![endif]-->to load the library when needed.
- Cite 2 advantages and 2 drawbacks of using canvas
- Cite 2 examples of canvas’s lack of accessibility
The following code will draw a black rectangle on the screen:
var canvas=document.getElementById("mycanvas"); canvas.fillRect(50,50,100,200);- True
- False
This gives you the number of pixels in your canvas:
var pixels=ctx.getImageData(0,0,canvas.width,canvas.height); var pixels_nbr=pixels.data.length;
- True
- False









