HTML5 Canvas Example
With HTML5 support emerging, I have decided to investigate the drawing capabilities. In the tutorial I will focus on drawing on the new element called a "canvas". I created an example icon in Photoshop and will reproduce it by drawing on a canvas with JavaScript.
Browser Capability
At the time of this article HTML5 is not yet standard and not fully supported by the major browsers. Despite my attempts to keep my example consistent between browsers, there were some aspects I was unable to overcome. Let's take a look:
Browser consistency added a lot of extra complexity and code. To better understand the basics of html5 canvas let's take a more simple approach. Simplier also means less compatibility:
Simple Example Implementation
We shrug off the browser capability issues for now (hopefully the future will bring full support in all browsers) so we can take a much simpler look at how this example was created.
Markup
First let's take a look at the markup:
<canvas id="canvasId" width="165" height="145"></canvas>
Now we have a blank canvas. Not very useful on its own, but in comes JavaScript.
Script
The canvas element will provide an area on which we will use JavaScript to place our drawing. You don't draw on the canvas, just like you wouldn't draw on your table. You draw on something on the table. That 'something' is the context.
var context = document.getElementById("canvasId").getContext("2d");
The method getContext with the parameter "2d" gives access to the canvas context. Now we can start drawing! Let's create a triangle:
var width = 125; // Triangle Width var height = 105; // Triangle Height var padding = 20; // Draw a path context.beginPath(); context.moveTo(padding + width/2, padding); // Top Corner context.lineTo(padding + width, height + padding); // Bottom Right context.lineTo(padding, height + padding); // Bottom Left context.closePath(); // Fill the path context.fillStyle = "#ffc821"; context.fill();
Our triangle looks a little flat. Instead of a solid color, let's fill it with a linear gradient. First create the gradient using context's method createLinearGradient. The gradient's method addColorStop specifies the gradient's colors.
// Create fill gradient var gradient = context.createLinearGradient(0, 0, 0, height); gradient.addColorStop(0, "#ffc821"); gradient.addColorStop(1, "#faf100"); // Fill the path context.fillStyle = gradient; context.fill();
Now to add a shadow by setting a couple of properties on context: shadowBlur and shadowColor. Note: Make sure you specify these properties before filling.
// Create fill gradient //... // Add a shadow around the object context.shadowBlur = 10; context.shadowColor = "black"; // Fill the path // ...
A horizon gradient is added going from transparent, immediately to a color then fading back to the background color.
// Add a horizon reflection with a gradient to transparent gradient = context.createLinearGradient(0,padding,0,padding+height); gradient.addColorStop(0.5, "transparent"); gradient.addColorStop(0.5, "#dcaa09"); gradient.addColorStop(1, "#faf100"); // Fill the path context.fillStyle = gradient; context.fill();
Add the black stroke outline:
// Stroke the inner outline context.lineWidth = 5; context.lineJoin = "round"; context.strokeStyle = "#333"; context.stroke();
Next we utilize another stroke with the background color to avoid drawing the rounded corners by hand.
context.lineWidth = 20; context.lineJoin = "round"; context.strokeStyle = gradient; context.stroke();
Add the exclamation point using context's fillText method. Don't forget the try / catch to stop Internet Explorer 8.0 from going to error town.
context.textAlign = "center"; context.textBaseline = "middle"; context.font = "bold 60px 'Times New Roman', Times, serif"; context.fillStyle = gradient; try{ context.fillText("!", canvasWidth/2, padding + height/1.5); }catch(ex){}
There you have it! Not exactly the same as our starting point, not supported by all browsers, but a good example of what html5 canvas has to offer.
Code for Simple Example
Before using this code, remember the limitation of this simple example:
Markup
<!DOCTYPE html> <html> <head> <title>HTML5 Canvas Example</title> <script type="text/javascript" src="simpleExample.js"></script> </head> <body> <canvas id="canvasId" width="165" height="145"></canvas> </body> </html>
Script
var context = document.getElementById('canvasId').getContext("2d"); // Dimensions of the triangle var width = 125; var height = 100; var padding = 20; // Create a triangluar path context.beginPath(); context.moveTo(padding + width/2, padding); context.lineTo(padding + width, height + padding); context.lineTo(padding, height + padding); context.closePath(); // Create fill gradient var gradient = context.createLinearGradient(0,0,0,height); gradient.addColorStop(0, primaryColor); gradient.addColorStop(1, secondaryColor); // Add a shadow around the object context.shadowBlur = 10; context.shadowColor = "black"; // Stroke the outer outline context.lineWidth = lineWidth * 2; context.lineJoin = "round"; context.strokeStyle = gradient; context.stroke(); // Turn off the shadow, or all future fills will have shadows context.shadowColor = "transparent"; // Fill the path context.fillStyle = gradient; context.fill(); // Add a horizon reflection with a gradient to transparent gradient=context.createLinearGradient(0,padding,0,padding+height); gradient.addColorStop(0, "transparent"); gradient.addColorStop(0.5, "transparent"); gradient.addColorStop(0.5, tertiaryColor); gradient.addColorStop(1, secondaryColor); context.fillStyle = gradient; context.fill(); // Stroke the inner outline context.lineWidth = lineWidth; context.lineJoin = "round"; context.strokeStyle = "#333"; context.stroke(); // Draw the text exclamation point context.textAlign = "center"; context.textBaseline = "middle"; context.font = "bold 60px 'Times New Roman', Times, serif"; context.fillStyle = "#333"; try{ context.fillText("!", padding + width/2, padding + height/1.5); }catch(ex){}
Cross-Browser Example
The cross-browser example requires more complicated code (especially to support Internet Explorer 8). After all that there are still browser compatibility issues:
To achieve a more cross-browser friendly version, I use a few tricks to handle the differences in shadows, including using bezier and quadratic curves. You can download the source for both examples below.
Download Source
- Download Simple Example HTML: simpleExample.html
- Download Simple Example JavaScript: simpleExample.js
- Download Cross-Browser Example: crossBrowserExample.zip