Author: Mihai Şucan (ROBO Design)
New web technologies are gaining support across browsers, with bridging solutions becoming available for those that don't, eg. Raphaël for SVG, and ExCanvas for Canvas. Even Internet Explorer has started to flirt with SVG, so we could see wider support in the future! This however causes a new problem to rear its ugly head - it has become harder to decide which technology is best for a new project.
HTML5 Canvas and SVG are both web technologies that allow you to create rich graphics inside the browser, but they are fundamentally different. In this article we explore those differences, giving you the knowledge needed to use SVG and Canvas effectively and appropriately.
Contents:
If you wish to experiment more with the code presented here, you can download the examples provided in this article.
SVG is an XML-based vector graphics format. SVG content can be
static, dynamic, interactive and animated - it is very flexible. You can
also style SVG with CSS and add
dynamic behaviour to it using the SVG DOM. And of course, because the text inside SVG exists in
a file, it is relatively accessible too. You can also include SVG content
inside standard (X)HTML using object
.
Here is an example of a circle drawn with SVG - it includes a radial gradient and a simple zoom in/out animation:
<svg version="1.1"
width="320" height="320"
xmlns="http://www.w3.org/2000/svg">
<defs>
<radialGradient id="circleGrad">
<stop offset="0%" stop-color="rgb(255, 255, 0)" />
<stop offset="100%" stop-color="rgb( 0, 255, 0)" />
</radialGradient>
</defs>
<ellipse fill="url(#circleGrad)" stroke="#000" cx="50%"
cy="50%" rx="50%" ry="50%">
<animate attributeName="rx" values="0%;50%;0%" dur="2s"
repeatCount="indefinite" />
<animate attributeName="ry" values="0%;50%;0%" dur="2s"
repeatCount="indefinite" />
</ellipse>
</svg>
Note that the animation only plays in Opera and Webkit-based web browsers.
With SVG you can do a lot more than simple vector graphics and animations. You can develop highly interactive web applications with scripting, advanced animation events, filters, and almost anything you want. To learn more about SVG, read the "SVG: Evolution, Not Revolution" article series.
The HTML5
Canvas specification is a versatile JavaScript API allowing us to code
programmatic drawing operations. Canvas, by itself, allows you to define
a canvas
context object (manifesting as
a <canvas>
element on your HTML page), which can then be
drawn inside. To do the actual drawing, you have different options:
The former is more established and is available in all the modern web browsers (with the notable exception being Microsoft Internet Explorer), while the latter is in the early process of being defined, having only a handful of experimental implementations.
We are just going to look at the 2D context of Canvas, as it is more widely supported. This context provides you with a simple yet powerful API for performing quick drawing operation, on a 2D bitmap surface. There is no file format, and you can only draw using script. You do not have any DOM nodes for the shapes you draw - it is all on the surface, as pixels. This means that you can concentrate on your drawing without performance penalties as the complexity of the image increases.
Here is the same animated circle drawn with Canvas:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Canvas animation example</title>
<script type="text/javascript"><!--
window.addEventListener('load', function () {
// Get the canvas element.
var canvas = document.getElementById('myCanvas'),
w = 4,
h = 4,
zoompx = 6,
step = 'zoomin';
if (!canvas || !canvas.getContext) {
return;
}
// Get the canvas 2d context.
var ctx = canvas.getContext('2d');
if (!ctx) {
return;
}
var K = 4*((Math.SQRT2-1)/3);
setInterval(function () {
if (step == 'zoomin') {
w += zoompx;
h += zoompx;
} else if (step == 'zoomout') {
w -= zoompx;
h -= zoompx;
}
if (w > canvas.width) {
w = canvas.width;
step = 'zoomout';
} else if (w < 4) {
w = 4;
step = 'zoomin';
}
if (h > canvas.height) {
h = canvas.height;
step = 'zoomout';
} else if (h < 4) {
h = 4;
step = 'zoomin';
}
// Create the radial gradient: x0, y0, r0, x1, y1, r1.
// That's the start circle (x0,y0) coordinates and r0 radius,
// followed by the end circle (x1,y1) coordinates and r1 radius.
var gradient = ctx.createRadialGradient(
Math.round(w/2), Math.round(h/2), 0, Math.round(w/2), Math.round(h/2),
Math.round(Math.min(w, h)/2));
gradient.addColorStop(0, "#ff0");
gradient.addColorStop(1, "#0f0");
// Use the gradient for the fillStyle.
ctx.fillStyle = gradient;
// Ellipse radius and center.
var cx = w/2,
cy = h/2,
// Ellipse radius*Kappa, for the Bézier curve control points
rx = cx*K,
ry = cy*K;
ctx.setTransform(1, 0, 0, 1, 0, 0);
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.setTransform(1, 0, 0, 1, Math.round((canvas.width - w) / 2),
Math.round((canvas.height - h) / 2));
ctx.beginPath();
// startX, startY
ctx.moveTo(cx, 0);
// Control points: cp1x, cp1y, cp2x, cp2y, destx, desty
// go clockwise: top-middle, right-middle, bottom-middle, then left-middle
ctx.bezierCurveTo(cx + rx, 0, w, cy - ry, w, cy);
ctx.bezierCurveTo(w, cy + ry, cx + rx, h, cx, h);
ctx.bezierCurveTo(cx - rx, h, 0, cy + ry, 0, cy);
ctx.bezierCurveTo(0, cy - ry, cx - rx, 0, cx, 0);
ctx.fill();
ctx.stroke();
ctx.closePath();
}, 20);
}, false);
// --></script>
</head>
<body>
<p><canvas id="myCanvas" width="320" height="320">Your browser does not have
support for Canvas.</p>
</body>
</html>
The 2D context has no animation-related features - you just perform the drawing operations how and when you want. In this case, the circle is rendered inside a function invoked every few milliseconds.
Inside the Canvas surface you can perform pixel-manipulation operations
like image filters. You can insert images like .PNGs
or
.JPGs
, or anything else the web browser can load. The Canvas
output can also be exported/saved in common image formats.
To learn more about Canvas basics, read the Canvas primer.
The Canvas example provided here is not a good use-case for Canvas because you can achieve the same effect with a lot less code in SVG, as shown in the previous section. The SVG version is also a lot easier to understand and manage. For Canvas-based animations we need to use timers, to manually draw each frame, while SVG makes things a lot easier with its support for declarative animations.
A better use-case for Canvas is the display of dynamic information, such as interactive graphs and image analysis. For example, here is a demo that calculates and displays an image histogram using the Canvas 2D context API:
The image histogram example code loads an image with the img
element, then counts all the pixels in the image with the Canvas 2D context
API. The pixels are counted for each channel in the user-selected color
space (RGB, HSV or CMYK). Once the image has been analyzed, a second
Canvas element is used to draw the image histogram based on the data
gathered.
Where does the Canvas 3D context fit in? With the 3D context you can draw 3D objects, textures and shaders, and incorporate animation. You can make 3D games (think Quake) and 3D modeling tools (think about product visualization - a car, furniture, etc.) The web browser draws the scene using hardware acceleration, if it is available.
The tables below give you an overview of the advantages and disadvantages of SVG and Canvas.
Canvas | SVG |
---|---|
|
|
Canvas | SVG |
---|---|
|
|
Note: If accessibility is a concern, HTML might be better suited than SVG, being that it has more tools available for enabling and testing accessibility. In any case you should make sure you add ARIA attributes to your HTML/SVG markup to greatly improve the accessibility of your web application.
Each technology has its own uses - it is not like one can abandon Canvas in favor of SVG, or vice-versa.
You should use Canvas for:
You should use SVG for:
In short, you should use both technologies. In a game you might want to render raster graphics dynamically using Canvas, then animate them with SVG. In an image editor you might want to render both vector and raster graphics.
When should you not use these technologies? There are pure HTML + CSS-based solutions for things like rounded corners, transitions, drop shadows and transparency. You should also consider a JavaScript library such as jQuery UI. Ask yourself if you really need SVG or Canvas at all, or if you can make your project only with pure HTML + CSS. SVG is a mostly presentational markup, and SVG experts are a lot less common than HTML junkies. HTML is a lot more common, more cross-browser compatible, and it has richer non-presentational semantics. Choosing SVG over HTML + CSS purely for presentational merits may not be the best choice.
In this article we have explored the differences between two seemingly similar web technologies, SVG and HTML5 Canvas. Each technology has its strengths and weaknesses, therefore you should make sure they are used appropriately. Often, combining them inside a single web application can yield good results.
Good luck developing the next killer web application!
There is another great article available that explores the differences between Canvas and SVG - check out "A Bit of SVG and Canvas" by Divya Manian.