The <canvas>
element can be used to draw graphics via scripting in JavaScript. For example, it can be used to draw graphs, make photo compositions, create animations or even do real-time video processing or rendering. Canvas provicdes resolution-dependent bitmap canvas, which can be used for rendering images on the fly.
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.
You can get started with Modernizr at Using Modernizr, Polyfills, YepNope.
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<body> | |
<canvas id="myCanvas" width="578" height="200"></canvas> | |
</body> |
Then add the Javascript initializer, which gets the document and provides a drawing context. https://gist.github.com/nextechu/9860774
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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.
References
For more information, see No Browser Left Behind: An HTML5 Adoption Strategy.
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
Sample Code
Sample code is available in the DevDays GitHub repository. See https://github.com/devdays/html5-tutorials