Undoubtedly, the canvas element in HTML5 is the feature that most developers will want to use to develop truly rich web applications – without needing to install browser plug-ins like Adobe’s Flash player. Canvas was born at a time when client richness is at the forefront of developers’ minds. Modern browsers like Chrome, Firefox, and Internet Explorer 9 and 10 all support it. But what exactly is the canvas element in HTML5? How can you use it to create rich web applications? If you’re unfamiliar with HTML5, before diving into this article you might like to read Yes, You Can Use HTML5 Today! and HTML5 and Even Fancier Forms.
What’s the Canvas Element For?
Officially a canvas is “a resolution-dependent bitmap canvas which can be used for rendering graphs, game graphics, or other visual images on the fly”. In layman’s terms, the canvas is a new element in HTML5, which allows you to draw graphics using JavaScript. It can be used to render text, images, graphs, rectangles, lines, gradients and other effects dynamically. Drawing on the canvas is via the canvas 2D API. This API contains a plethora of functions that give you the power to draw pretty much anything you like on the canvas. Currently, the canvas supports a 2D surface, not 3D. So what does a canvas look like? Not much. See for yourself.<canvas id=”myCanvas” style=”width:300px; height:300px”></canvas>
The code above will render a canvas in the browser, but because the canvas is empty, you won’t see anything. Let’s add a border so you can see more clearly. The image below shows the canvas with a black border.![blank canvas](https://uploads.sitepoint.com/wp-content/uploads/2011/08/fig11.png)
![canvas coordinates](https://uploads.sitepoint.com/wp-content/uploads/2011/08/fig21.png)
Clarifying the SVG – Canvas Relationship
It’s important to understand the differences between SVG and canvas elements. SVG is an XML based vector graphics format. You can add styles to it with CSS and add dynamic behavior to it using the SVG DOM. The canvas allows you to draw graphics and shapes through JavaScript. It too can be styled and you can add dynamic behavior to it. Here are some reasons to use the canvas over SVG.- the canvas is faster at drawing complex graphics
- you can save images off the canvas whereas you can’t using SVG
- everything in the canvas is a pixel.
- it’s resolution independent so it can scale for different screen resolutions
- it’s xml, so targeting different elements is a breeze
- it’s good at complex animations
Canvas and Hardware Acceleration
Using canvas is simply the best way to learn about hardware acceleration on the web. In earlier versions of browsers, graphics rendering – like most compute intensive tasks – was handled by the CPU, the central processing unit. Modern browsers have been innovating in this area by shifting graphic-intensive tasks to the GPU, the graphics processing unit, to render the graphics and text on a web page using Direct2D and DirectWrite. The allocation of these tasks to the GPU cores not only accelerates the graphics processing but also eases the load on the CPU while it takes care of the serial tasks more efficiently. JavaScript has also been accused of being a processing hog. A good example of dealing with this is IE9’s JavaScript engine, Chakra, which takes advantage of multi-processor cores to background compile JavaScript into machine code for faster processing. In both cases, the end result is accelerated performance. I mention this here because if you put accelerated graphics processing together with accelerated Javascript processing, you’ve created an ideal environment for getting the most out of HTML5 canvas. When you send drawing commands to the canvas, the browser sends them directly to the graphics hardware without further development on your part. The hardware acceleration works incredibly fast to deliver real time animations and interactive graphics, without slowing down the surrounding user experience you’re delivering. You can test many different browsers and their support of hardware acceleration here. There is a liberation here for the creative developer, knowing that the visual experiences you can put into code will be translated and rendered as intended. All the following ways of working with canvas deliver an enhanced, intensified and more delightful experience when viewed through a hardware accelerated browser.Canvas 2D API
The canvas 2D API is an object that allows you to draw and manipulate images and graphics on a canvas element. To reference the context of the canvas, you call getContext, which is a method on the canvas element. It has one parameter, which currently is 2d. Here’s the snippet of code for referencing the context.var myCanvas = document.getElementById(“myCanvas”); var context = myCanvas.getContext(“2d”);
Each canvas has its own context, so if your page contains multiple canvas elements you must have a reference to each individual context you want to work with. Aside from getContext, there are plenty of other functions at your disposal in the canvas 2D API. Some of the notable ones are outlined below. Transformation Functions- scale – allows you to scale the current context.
- rotate – allows you to rotate the x and y coordinates of the current context.
- save – allows you to save the current state of the context.
- restore – allows you to restore the state of the context from a previously saved state.
- font – gets or sets the font for the current context.
- fillText – renders filled text to the current canvas.
- measureText – measures the current width of the specified text.
Shapes & Colors
There’s an entire group of properties and functions devoted to drawing shapes. Let’s begin with rectangles. Here are the related functions available to draw rectangles.- fillRect(x, y, w, h) – draws the given rectangle onto the canvas, using the current fill style
- strokeRect(x, y, w, h) – draws the box that outlines the given rectangle onto the canvas, using the current stroke style
- clearRect(x, y, w, h) – clears all pixels on the canvas in the given rectangle to transparent black
var canvas = document.getElementById(“myCanvas”); var context = canvas.getContext(“2d”); context.fillRect(5, 5, 145, 145);
This code will render a black rectangle, starting at 5 pixels from the top, 5 pixels from the right, and 145 pixels in width and height. The image below displays the rectangle in the canvas.![black rectangle](https://uploads.sitepoint.com/wp-content/uploads/2011/08/fig31.png)
context.fillRect(5, 5, 145, 145); context.fillStyle = “rgb(0, 162, 232)”; context.fillRect(40, 55, 145, 145); context.fillStyle = “rgba(255, 0, 0, 0.2)”; context.fillRect(75, 105, 145, 145);
Here’s the result.![three rectangles](https://uploads.sitepoint.com/wp-content/uploads/2011/08/fig41.png)
- arc(x, y, radius, startAngle, endAngle, anticlockwise) – points to the subpath such that the arc described by the circumference of the circle described by the arguments, starting at the given start angle and ending at the given end angle, going in the given direction, is added to the path
context.beginPath(); context.fillStyle = “rgb(0, 0, 0)”; context.arc(123, 93, 70, 0, 2 * Math.PI, true); context.fill();
Because arc adds points to the subpath, you must called beginPath first then call fill afterwards. This fills in the subpaths with the current fillStyle. The image below displays the result.![circle](https://uploads.sitepoint.com/wp-content/uploads/2011/08/fig51.png)
context.beginPath(); context.strokeStyle = “rgb(0, 0, 0)”; context.arc(123, 93, 70, 0, 2 * Math.PI, true); context.stroke();
Circles don’t have to be 360 degrees. To alter the shape, change the start and end radius.context.beginPath(); context.strokeStyle = “rgb(0, 0, 0)”; context.arc(123, 93, 70, 0, 0.5 * Math.PI, true); context.stroke();
Here’s the semi circle.![semicircle](https://uploads.sitepoint.com/wp-content/uploads/2011/08/fig61.png)
- bezierCurveTo (cp1x, cp1y, cp2x, cp2y, x, y) – adds the given point to the current path, connected to the previous one by a cubic Bézier curve with the given control points
context.lineWidth = 20; context.beginPath(); context.moveTo(5, 50); context.bezierCurveTo(30, 30, 130, 530, 200, 100); context.stroke();
The image below is what’s drawn in the canvas.![Bezier curve](https://uploads.sitepoint.com/wp-content/uploads/2011/08/fig71.png)
// face
context.beginPath();
context.lineWidth = 10;
context.strokeStyle = “rgb(0, 0, 0)”;
context.arc(200, 233, 150, 0, 2 * Math.PI, true);
context.stroke();
// color face
context.beginPath();
context.fillStyle = “rgba(80, 100, 80, 0.4)”;
context.arc(200, 233, 150, 0, 2 * Math.PI, true);
context.fill();
// right eye
context.lineWidth = 20;
context.beginPath();
context.moveTo(230, 130);
context.bezierCurveTo(230, 130, 230, 130, 240, 200);
context.stroke();
// left eye
context.beginPath();
context.moveTo(170, 130);
context.bezierCurveTo(170, 130, 170, 130, 160, 200);
context.stroke();
// upper lip
context.beginPath();
context.moveTo(100, 230);
context.bezierCurveTo(100, 230, 200, 380, 300, 230);
context.stroke();
// lower lip
context.beginPath();
context.moveTo(100, 235);
context.bezierCurveTo(105, 270, 200, 480, 300, 232);
context.stroke();
![smiley face](https://uploads.sitepoint.com/wp-content/uploads/2011/08/fig81.png)
var a = 1;
for (j = 0; j < 100; j++) {
var r = 255, g = 0, b = 0;
for (i = 0; i < 150; i++) {
// Yellow
if (i < 25) g += 10.2;
// Green
else if (i >= 25 && i < 50) r -= 10.2;
// Blue
else if (i >= 50 && i < 75) {
g -= 10.2;
b += 10.2;
}
// Purple
else if (i >= 75 && i < 100) r += 10.2;
// Red
else b -= 10.2;
context.fillStyle = “rgba(” + Math.floor(r) + “,” +
Math.floor(g) + “,” + Math.floor(b) + “,” + a + “)”;
context.fillRect(3 * i, 5 * j, 3, 5); } a -= 0.01; }
![gradients](https://uploads.sitepoint.com/wp-content/uploads/2011/08/fig91.png)
- addColorStop(offset, color) – adds a color stop with the given color to the gradient at the given offset. 0.0 is the offset at one end of the gradient, 1.0 is the offset at the opposite end
- createLinearGradient(x0, y0, x1, y1) – returns a CanvasGradient object that represents a linear gradient that paints along the line given by the coordinates
- createRadialGradient(x0, y0, r0, x1, y1, r1) – returns a CanvasGradient object that represents a radial gradient that paints along the cone given by the circles represented by the coordinates
var gradient = context.createLinearGradient(0, 0,0, 145);
gradient.addColorStop(0, “#00ABEB”);
gradient.addColorStop(0.5, “yellow”);
gradient.addColorStop(0.8, “green”);
gradient.addColorStop(1, “white”);
context.fillStyle = gradient;
context.fillRect(5, 5, 145, 145);
![linear gradients](https://uploads.sitepoint.com/wp-content/uploads/2011/08/fig101.png)
Lines, Text & Shadows
When you’re drawing lines, think of paths. Each canvas has a path. Defining a path is like drawing a line. Any line is possible. Just like writing, you need to define a path, and then fill the path in. Here are some of the related properties and functions for drawing lines.- lineWidth [ = value ] – returns the current line width. Can be set to change the line width
- lineCap [ = value ] – returns the current line cap style. Can be set to change the line cap style. The possible line cap styles are butt, round, and square
- lineJoin [ = value ] – returns the current line join style. Can be set to change the line join style. The possible line join styles are bevel, round, and miter
for (i = 15; i > 0; i–) { context.strokeStyle = “blue”; context.lineWidth = i; context.beginPath(); context.moveTo(55, 15 + (15 – i) * 24); context.lineTo(335, 15 + (15 – i) * 24); context.stroke(); }
The result is below.![lines](https://uploads.sitepoint.com/wp-content/uploads/2011/08/fig111.png)
context.lineCap = “round”;
Doing that to the example draws the rounded lines.![rounded lines](https://uploads.sitepoint.com/wp-content/uploads/2011/08/fig12.png)
- font [ = value ] – returns the current font settings. Can be set, to change the font. The syntax is the same as for the CSS ‘font’ property
- textAlign [ = value ] – returns the current text alignment settings. Can be set, to change the alignment. The possible values are start, end, left, right, and center
- textBaseline [ = value ] – returns the current baseline alignment settings. Can be set, to change the baseline alignment
- fillText(text, x, y [, maxWidth ] ) – fills the text at the given position
- strokeText(text, x, y [, maxWidth ] ) – strokes the text at the given position
context.font = ’24px “Tahoma”‘; context.fillText(“Hello World!”, 0, 0);
Here’s the result.![hello world](https://uploads.sitepoint.com/wp-content/uploads/2011/08/fig13.png)
context.fillStyle = “rgba(0, 0, 0, 0.2)”;
And the result.![hello world transparent](https://uploads.sitepoint.com/wp-content/uploads/2011/08/fig14.png)
context.shadowOffsetX = 5; context.shadowOffsetY = 5; context.shadowBlur = 5; context.shadowColor = “rgba(0, 0, 0, 1)”;
![hello world shadow](https://uploads.sitepoint.com/wp-content/uploads/2011/08/fig15.png)
Images & Video
Well, when you’re working with the canvas, it’s possible to work with images and videos too. The obvious question is why not just use a standard <img> element? Well the big advantage is your image can be part of a much bigger and complex image thanks to all the wizardry you can create with the canvas element. There’s one main function for working with images and videos, and that’s drawImage. The following piece of code references the sheep image and draws that on the canvas.var image = document.getElementById(“mySheep”); context.drawImage(image, 10, 10, 128, 128);
<img id=”mySheep” src=”sheep.png” style=”display:none;” />
That code draws the sheep on the canvas.![sheep](https://uploads.sitepoint.com/wp-content/uploads/2011/08/fig16.png)
<canvas id=”myCanvas”> </canvas> <video id=”myVideo” controls loop> <source src=”video.webm” type=”video/webm”> <source src=”video.ogg” type=”video/ogg”> <source src=”video.mp4″ type=”video/mp4″> </video>
Not much is happening here. The video will play inside the video tag, but I’m going draw the video on the canvas and position the video centrally on the canvas. The result is awesome. Here’s the code.var canvas = function () {
return {
draw: function () {
var video = document.getElementById(“myVideo”);
var canvas = document.getElementById(“myCanvas”);
var context = canvas.getContext(“2d”);
var width = Math.floor(canvas.clientWidth / 100);
var height = Math.floor(canvas.clientHeight / 100);
canvas.width = width; canvas.height = height;
video.play();
context.drawImage(video, 0, 0, width, height);
},
init: function () {
setInterval(canvas.draw, 16);
}
}
} ();
Transformations & Animations
Transformations and animations are possible with the canvas element. Here are some of the related properties and functions for performing transformations.- scale(x, y) – changes the transformation matrix to apply a scaling transformation with the given characteristics
- rotate(angle) – changes the transformation matrix to apply a rotation transformation with the given characteristics
- translate(x, y) – changes the transformation matrix to apply a translation transformation with the given characteristics
- transform(m11, m12, m21, m22, dx, dy) – changes the transformation matrix to apply the matrix given by the arguments
- setTransform(m11, m12, m21, m22, dx, dy) – changes the transformation matrix to the matrix given by the arguments.
var can = function () {
var canvas;
var context;
return {
draw: function () {
var r = Math.floor(Math.random() * 255) + 70;
var g = Math.floor(Math.random() * 255) + 70;
var b = Math.floor(Math.random() * 255) + 70;
var s = ‘rgba(‘ + r + ‘,’ + g + ‘,’ + b + ‘, 0.5)’;
context.rotate(0.2 * Math.PI);
context.fillStyle = s;
context.fillRect(10, 0, 150, 50);
},
init: function () {
canvas = document.getElementById(“myCanvas”);
context = canvas.getContext(“2d”);
context.translate(200, 250);
setInterval(can.draw, 250);
}
}
} ();
window.onload = can.init;
![spinning wheel](https://uploads.sitepoint.com/wp-content/uploads/2011/08/fig17.png)
var can = function () {
var canvas;
var context;
var x = 0;
var y = 0;
function currectX() {
return x = x + 1;
}
function currectY() {
return y = y + 1;
}
return {
draw: function () {
var r = Math.floor(Math.random() * 255) + 70;
var g = Math.floor(Math.random() * 255) + 70;
var b = Math.floor(Math.random() * 255) + 70;
var s = ‘rgba(‘ + r + ‘,’ + g + ‘,’ + b + ‘, 0.5)’;
context.fillStyle = s;
context.scale(1.2,1.2);
context.fillRect(currectX(), currectY(), 5, 5);
},
init: function () {
canvas = document.getElementById(“myCanvas”);
context = canvas.getContext(“2d”);
context.translate(0, 0);
setInterval(can.draw, 1000);
}
}
} ();
window.onload = can.init;
![squares](https://uploads.sitepoint.com/wp-content/uploads/2011/08/fig18.png)
Working with the Mouse
As you may have guessed, working with the mouse is also possible. Just like any element on a webpage, you can return the x and y coordinates of the mouse by querying the pageX and pageY properties of the element. To track the mouse over a canvas, here’s the snippet of code.var canvas = document.getElementById(“myCanvas”);
var context = canvas.getContext(“2d”);
canvas.onmousemove = function (e) {
var x = e.pageX – this.offsetLeft;
var y = e.pageY – this.offsetTop;
var div = document.getElementById(“coords”);
div.innerHTML = “x: ” + x + ” y: ” + y;
};
var canvas = document.getElementById(“myCanvas”);
var context = canvas.getContext(“2d”);
context.fillCircle = function (x, y, radius, fillColor) {
this.fillStyle = fillColor;
this.beginPath();
this.moveTo(x, y);
this.arc(x, y, radius, 0, Math.PI * 2, false);
this.fill();
};
context.clearTo = function (fillColor) {
context.fillStyle = fillColor;
context.fillRect(0, 0, canvas.width, canvas.height);
};
context.clearTo(“#ddd”);
canvas.onmousemove = function (e) {
if (!canvas.isDrawing) return;
var x = e.pageX – this.offsetLeft;
var y = e.pageY – this.offsetTop;
var div = document.getElementById(“coords”);
div.innerHTML = “x: ” + x + ” y: ” + y;
var radius = 10;
var fillColor = ‘#ff0000’;
context.fillCircle(x, y, radius, fillColor);
};
canvas.onmousedown = function (e) {
canvas.isDrawing = true;
};
canvas.onmouseup = function (e) {
canvas.isDrawing = false;
};
- HTML5 Canvas Developer Guide on MSDN
- Hardware Accelerated Paintball Canvas Demo
- How to Choose Between Canvas and SVG to Create Web Graphics
Frequently Asked Questions (FAQs) about HTML5 Canvas
How can I increase the resolution of my HTML5 canvas?
Increasing the resolution of your HTML5 canvas involves adjusting the width and height properties of the canvas. You can do this by setting the width and height attributes of the canvas element in your HTML code. However, remember that this will only change the size of the canvas, not the actual resolution. To increase the resolution, you need to scale the context of the canvas using the scale() method. This method takes two parameters: the scale factor for the x-axis and the y-axis. For example, context.scale(2,2) will double the resolution of your canvas.
What is the purpose of the HTML5 canvas element?
The HTML5 canvas element is used to draw graphics on a web page. It provides a space where you can draw shapes, text, images, and other graphics using JavaScript. The canvas element is only a container for graphics, it doesn’t have drawing abilities of its own. All the drawing must be done with JavaScript.
How can I draw shapes using HTML5 canvas?
Drawing shapes on an HTML5 canvas involves using specific methods provided by the canvas API. For instance, to draw a rectangle, you can use the fillRect() or strokeRect() methods. These methods take four parameters: the x and y coordinates of the top-left corner of the rectangle, and the width and height of the rectangle. To draw a circle, you can use the arc() method, which takes six parameters: the x and y coordinates of the center of the circle, the radius, the start angle, the end angle, and a boolean value indicating whether the arc should be drawn counterclockwise.
How can I add text to my HTML5 canvas?
Adding text to an HTML5 canvas involves using the fillText() or strokeText() methods. These methods take three parameters: the text string, and the x and y coordinates where the text should be drawn. You can also use the font property to specify the font size and family, and the textAlign and textBaseline properties to align the text.
How can I draw images on my HTML5 canvas?
Drawing images on an HTML5 canvas involves using the drawImage() method. This method can take three, five, or nine parameters, depending on whether you want to draw the entire image or a portion of it, and whether you want to scale the image or not. The simplest way to use this method is to pass it the image object and the x and y coordinates where the image should be drawn.
How can I clear my HTML5 canvas?
Clearing an HTML5 canvas involves using the clearRect() method. This method takes four parameters: the x and y coordinates of the top-left corner of the rectangle to clear, and the width and height of the rectangle. To clear the entire canvas, you can pass it the coordinates (0,0) and the width and height of the canvas.
How can I save and restore the state of my HTML5 canvas?
Saving and restoring the state of an HTML5 canvas involves using the save() and restore() methods. The save() method saves the current state of the canvas, including the transformations, the clipping region, and the values of the properties. The restore() method restores the most recently saved state.
How can I apply transformations to my HTML5 canvas?
Applying transformations to an HTML5 canvas involves using methods like translate(), rotate(), and scale(). The translate() method moves the canvas and its origin to a new location. The rotate() method rotates the canvas around the current origin. The scale() method scales the canvas units by x horizontally and by y vertically.
How can I create animations with my HTML5 canvas?
Creating animations with an HTML5 canvas involves changing the drawings on the canvas over time. This can be done by using a loop that repeatedly clears the canvas and redraws the shapes in new positions. The most common way to create such a loop is to use the requestAnimationFrame() method, which tells the browser to execute a specified function before the next repaint.
How can I handle events on my HTML5 canvas?
Handling events on an HTML5 canvas involves adding event listeners to the canvas element. These listeners can respond to events like mouse clicks, mouse movements, and key presses. The event object passed to the event handler function contains information about the event, such as the position of the mouse or the key that was pressed.
Malcolm Sheridan is a Microsoft awarded MVP in ASP.NET, ASPInsider, Telerik Insider and a regular presenter at conferences and user groups throughout Australia and New Zealand. Follow him on twitter @malcolmsheridan.