Canvas 2D Web Apps/HTML Web Apps
This chapter discusses the basic structure of a HTML web page that uses a single canvas element for rendering. The discussion includes the most important commands for rendering. Readers are assumed to be familiar with JavaScript (or ECMAScript).
An Example
editThe following HTML code uses a canvas element to draw some text and an image from Wikimedia Commons. You should use your favorite text editor to create a new file, copy and paste the code into it, and then save the file on your computer (preferably with the file extension “.html”). Then open the file with your favorite web browser. (Alternatively, it is also available online.) It should show the text "Hello, world!" on top of an HTML5 icon on top of a light blue background. Below we discuss the example in detail.
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8">
<script>
var myImage = new Image();
function init() {
myImage.onload = update; // call update when image is loaded
myImage.src = "http://upload.wikimedia.org/wikipedia/" +
"commons/thumb/2/25/HTML5_Shiny_Icon.svg/" +
"200px-HTML5_Shiny_Icon.svg.png";
}
function update() {
// get canvas and context
var myCanvas = document.getElementById("mycanvas");
var myContext = myCanvas.getContext("2d");
// set canvas size to window size
myCanvas.width = window.innerWidth;
myCanvas.height = window.innerHeight;
// clear context to transparent black
myContext.clearRect(0, 0, myCanvas.width, myCanvas.height);
// render in front-to-back order
myContext.globalCompositeOperation = "destination-over";
// write some text in black
myContext.fillStyle = "#000000";
myContext.font = "bold 48px Helvetica, sans-serif";
myContext.textAlign = "center";
myContext.textBaseline = "middle";
myContext.fillText("Hello, world!", 170, 60);
// draw the image (behind the text)
myContext.drawImage(myImage, 10, 20, 50, 51);
// fill the background of the canvas with light blue
myContext.fillStyle = "#C0C0FF";
myContext.fillRect(0, 0, myCanvas.width, myCanvas.height);
}
</script>
</head>
<body bgcolor="#000000" onload="init()" onresize="update()">
<canvas width="400" height="300" id="mycanvas"
style="position:absolute; left:0px; top:0px; "></canvas>
</body>
</html>
Debugging
editIf your web browser doesn't display the web page correctly, you should try to debug the web page using the web browser's developer tools and the list of error messages. Unfortunately, it depends on the browser how to open these tools; thus, you have to consult your web browser's documentation.
If you change the code, remember to save it before you reload the page in the web browser. Some browsers, however, might use a cached version instead of the new version with your changes. The safest way to deal with this problem is to save the new version under a new name and open this new file in the web browser.
Discussion
editIn this section, all the code of the example will be discussed in detail. The code starts with some HTML text:
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8">
...
This is just standard HTML code to start a web page. The meta
tag was included to avoid warnings about an unspecified character set.
The following part is the script
element with the JavaScript code, which we skip for now. The last part is again HTML code:
...
</head>
<body bgcolor="#000000" onload="init()" onresize="update()">
<canvas width="400" height="300" id="mycanvas"
style="position:absolute; left:0px; top:0px; "></canvas>
</body>
</html>
The body
tag specifies the content of the web page. The attribute bgcolor="#000000"
sets the background color to black (in case it is ever visible). The attribute onload="init()"
specifies that the web browser should execute the init
function (which we discuss below) once the web page has been loaded. onresize="update()"
specifies that the update
function (which we also discuss below) should be called whenever the browser window is resized.
In this web page, there is only a single canvas
element in the body of the web page. The attributes width
and height
specify the width and height of the canvas element in CSS pixels (which might be different from physical device pixels; for example, a CSS pixel usually corresponds to 2×2 device pixels on the retina display of some iOS devices). However, the size of the canvas element can be changed in the JavaScript code as discussed below. The attribute id="mycanvas"
specifies an ID for the canvas element such that it can be identified in the JavaScript code. (This is particularly useful if there are multiple canvas elements.) Finally, style="position:absolute; left:0px; top:0px; "
places the left, top corner of the canvas at the left, top corner of the web page without any margin, which is important if we want the canvas to fill the whole browser window.
In this example, the canvas
element is empty, i.e. nothing is specified between <canvas>
and </canvas>
. If there were any HTML elements between these tags, they would be displayed if rendering into the canvas
element is not supported by the web browser.
The script
element defines all the JavaScript code for this web page. The first part defines a global variable myImage
, which is initialized to a new, empty image, and the function init
, which is called by the web browser once the body of the web page has been loaded (see above):
...
<script>
var myImage = new Image();
function init() {
myImage.onload = update; // call update when image is loaded
myImage.src = "http://upload.wikimedia.org/wikipedia/" +
"commons/thumb/2/25/HTML5_Shiny_Icon.svg/" +
"200px-HTML5_Shiny_Icon.svg.png";
}
...
The line myImage.onload = update
specifies that the function update
(see below) should be called once the image has been loaded. The next line myImage.src = "http://...";
specifies the URL address from where the image should be loaded. The string can also specify the path name of an image file relative to the location of the HTML file.
The second function is called update
as it updates the contents of the canvas element.
...
function update() {
// get canvas and context
var myCanvas = document.getElementById("mycanvas");
var myContext = myCanvas.getContext("2d");
// set canvas size to window size
myCanvas.width = window.innerWidth;
myCanvas.height = window.innerHeight;
// clear context to transparent black
myContext.clearRect(0, 0, myCanvas.width, myCanvas.height);
// render in front-to-back order
myContext.globalCompositeOperation = "destination-over";
// write some text in black
myContext.fillStyle = "#000000";
myContext.font = "bold 48px Helvetica, sans-serif";
myContext.textAlign = "center";
myContext.textBaseline = "middle";
myContext.fillText("Hello, world!", 170, 60);
// draw the image (behind the text)
myContext.drawImage(myImage, 10, 20, 50, 51);
// fill the background of the canvas with light blue
myContext.fillStyle = "#C0C0FF";
myContext.fillRect(0, 0, myCanvas.width, myCanvas.height);
}
</script>
...
First, the canvas element is retrieved with document.getElementByID("mycanvas")
(see above for the definition of the ID of the canvas element) and assigned to the variable myCanvas
. For this canvas, a “canvas 2D context” is retrieved with myCanvas.getContext("2d")
and assigned to the variable myContext
. All the rendering functions discussed in this wikibook use the 2D context.
The size of the 2D context is specified by the corresponding canvas. In this example, the lines myCanvas.width = window.innerWidth;
and myCanvas.height = window.innerHeight;
set the size of the canvas (and therefore of the 2D context) to the size of the browser window. Since the update
function is called whenever the browser window is resized (see the discussion of the body
element above), the canvas and its context are always set to the size of the browser window.
The line myContext.clearRect(0, 0, myCanvas.width, myCanvas.height);
clears the whole context to transparent black. (Changing the size of the canvas will usually also clear the context; thus, this line is often not necessary.)
The line myContext.globalCompositeOperation = "destination-over";
specifies the composite operation that is appropriate for rendering in front-to-back order; i.e., the front-most element (the one that occludes all other elements) is rendered first, then the element that occludes all but the front-most element, etc. Thus, the background has to be rendered last. This is the same order that is used for traditional reverse glass painting. Front-to-back rendering is somewhat unusual in computer graphics but we use it in this wikibook because it is consistent with the way in which we process mouse and touch events.
The line myContext.fillStyle = "#000000";
specifies that the following commands should use black as fill color. myContext.font = "bold 48px Helvetica, sans-serif";
specifies that the following commands should use a bold Helvetica font of size 48 pixels or the default sans-serif font if Helvetica is not available. The lines myContext.textAlign = "center";
and myContext.textBaseline = "middle";
set the vertical and horizontal alignment to centering; i.e., text will be centered around a specified anchor point. The line myContext.fillText("Hello, world!", 170, 60);
then writes the string "Hello, world!"
with the center at x coordinate 170 and y coordinate 60 (the origin of the coordinate system is in the top, left corner of the canvas) using the font and fill color that have been specified in the previous lines.
The next line myContext.drawImage(myImage, 10, 20, 50, 51);
draws the image myImage
with its top, left corner at the x coordinate 10 and the y coordinate 20 and rescales it to a width of 50 pixels and a height of 51 pixels. If the last two arguments are skipped (i.e. for myContext.drawImage(myImage, 10, 20);
), the original width and height of myImage
would be used; thus, the image wouldn't be rescaled.
Similarly to one of the previous lines, myContext.fillStyle = "#C0C0FF";
specifies a fill color; in this case it is light blue. (The red and green intensity is specified by C0, which is the hexadecimal code for the value 192, and the blue intensity is specified by FF, which is the hexadecimal code for the value 255, which is the maximum intensity.) The line myContext.fillRect(0, 0, myCanvas.width, myCanvas.height);
draws a filled rectangle with the top, left corner at x coordinate 0 and y coordinate 0 (which is the top, left corner of the canvas) of width myCanvas.width
and height myCanvas.height
. Thus, the rectangle covers the whole canvas.
This concludes the discussion of the example. In order to get familiar with the code and the functions, you are strongly encouraged to play with it; for example, by changing colors and fonts, changing positions and sizes, replacing the image or adding additional images, rectangles, or text, etc.
More about Rendering
editThere are many more functions for rendering in a 2D context of the canvas element. They are all specified in the document “HTML Canvas 2D Context” by the World Wide Web Consortium (W3C). However, we are not going to discuss more of these functions in this wikibook for two reasons:
- For most prototypes of interactive web pages and web apps, the discussed functions are sufficient.
- If the final version of a web page or web app is designed by a professional web designer, he or she will usually prefer to create graphical elements as bitmap images, which can be rendered with the
drawImage
function as discussed above.
Obviously, there are cases in which more rendering functions are useful and readers are encouraged to read the specification of the 2D context by the W3C in those cases.