Getting Started on Line-of-Business HTML5 App – Part 5 Drawing on Canvas
In this next section, I want to be able to provide a map of my business location. Because not all browsers support Canvas, I’ll use Modernizr to help out. Modernizr will let me know if Canvas is supported, and if not it will allow me to call a polyfill.
But first, let’s draw something.
I can do this using <canvas> tag in HTML5. The HTML5 Canvas element is an HTML tag similar to the <div> , <a> , or <table> tag, with the exception that its contents are rendered with JavaScript.
Canvas is a simple graphics API that draws pixels and nothing more. Hence, there's no way to change an existing drawing or react to events, such as a click, on a particular part of your drawing. You can respond to button events and then update the Canvas image by redrawing it.
Do this in three steps:
- Place the canvas tag somewhere inside your HTML
- Create an initializer JavaScript function that accesses the canvas tag once the page loads
- Draw on the HTML5 Canvas API.
But not all browsers support Canvas. Use Modernizr to check for canvas browser support, then load a polyfill when canvas is not supported by the browser.
Canvas Tag
Start by placing a canvas tag in your HTML, giving the canvas a width and height that represents the drawing surface.
<body>
<canvas id="myCanvas" width="578" height="200"></canvas>
</body>
And then add the Javascript initializer, which gets the document and provides a context.
<!DOCTYPE HTML>
<html>
<head>
<script>
window.onload = function() {
var canvas = document.getElementById("myCanvas");
var context = canvas.getContext("2d");
// Write on the canvas here
context.moveTo(100, 150);
context.lineTo(450, 50);
context.lineWidth = 15;
context.stroke();
};
</script>
</head>
<body>
<canvas id="myCanvas" width="578" height="200"></canvas>
</body>
</html>
The result is a line drawn on the canvas:
The Grid
You use JavaScript to draw on the canvas. The origin (at coordinate (0,0)) is in the upper left with the values increasing to the right and down. Normally 1 unit in the grid corresponds to 1 pixel on the canvas.
For example, you can draw a rectangle that if filled with the background color, clear the center, and then draw another inside it.
context.fillRect(25,25,100,100);
context.clearRect(45,45,60,60);
context.strokeRect(50,50,50,50);
Canvas supports a single shape, a rectangle. All other shapes must be created by combining one or more paths.
Paths
The first step to create a path is calling the beginPath
method. Internally, paths are stored as a list of sub-paths (lines, arcs, etc) which together form a shape. Every time this method is called, the list is reset and we can start drawing new shapes.
context.beginPath();
context.lineWidth = 10;
context.fillStyle = "blue";
context.arc(305, 135, 10, 0, 360);
context.fill();
context.stroke();
context.closePath();
Save and Restore State
The canvas drawing state is basically a snapshot of all the styles and transformations that have been applied. You can save and restore the state.
Canvas states are stored on a stack. Every time the save
method is called, the current drawing state is pushed onto the stack. A drawing state consists of
- The transformations that have been applied, such as translate, rotate and scale.
- The values of
strokeStyle
,fillStyle
,globalAlpha
,lineWidth
,lineCap
,lineJoin
,miterLimit
,shadowOffsetX
,shadowOffsetY
,shadowBlur
,shadowColor
,globalCompositeOperation
properties. - The current clipping path, which we'll see in the next section.
You can call the save
method as many times as you like.
Every time the restore
method is called, the last saved state is returned from the stack and all saved settings are restored.
In this case, I am rotating the canvas to add rotated text.
// save off the state of the context before rotating text
context.save();
// rotate the context to draw at an angle
// the rotation is in radians
var degrees = 55;
context.rotate(degrees * 0.01745);
context.fillText("Main St", 150, -165);
// restore the context
context.restore();
save and restore also applies to transforms where you can stretch, scale, and transform your drawing.
And as you keep drawing, you can do this kind of thing:
Detecting Canvas
Not all browsers support canvas.
Use Modernizr to detect whether canvas is supported and if the browser is not supported, you can use a polyfill.
According to the Modernizr Web site, a polyfill is “a JavaScript shim that replicates the standard API for older browsers.” “Standard API” refers to a given HTML5 technology or feature, like canvas. “JavaScript shim” implies that you can dynamically load JavaScript code or libraries that mimic those APIs in browsers that don’t support them.
Get a JavaScript library called excanvas, which adds canvas support at the API level to Internet Explorer 6, Internet Explorer 7 and Internet Explorer 8. You can download excanvas from bit.ly/bSgyNR.
Then you can use feature detection to do the right thing using the canvas.
Modernizr.load({
test: Modernizr.canvas,
nope: '../Scripts/excanvas.js',
complete: function () {
Modernizr.load('Scripts/yourdrawing.js');
}
}]);
Modernizr tests whether or not the browser can display a canvas natively in the test parameter, and then loads the excanvas polyfill if it does not. Then, the code loads the drawing in JavaScript in Scripts/yourdrawing.js.
For more information, see No Browser Left Behind: An HTML5 Adoption Strategy.
Also, see the previous post in this series about Modernizr.
For More Information About Canvas
For more information, see :
- Using HTML5 Canvas for Data Visualization in MSDN Magazine.
- The Developer’s Guide to HTML5 Canvas
- How To Choose Between SVG and Canvas
- How To Create 3D Graphics Using Canvas
Next Up
We’ll see how jQuery is designed to make it easier to navigate a document, select DOM elements, create animations, handle events, and develop Ajax applications.
Bruce D. KyleISV Developer Evangelist | Microsoft Corporation