This article is the second in a series of four
- Introduction to karma.js
- This article,Comparing HTML 5 Canvas and SVG
- Digging into Inkscape
- JavaScript and SVG
In “Introduction to karma.js” I gave an overview of how the library works. In this article, I want to give an overview of the relative merits of HTML 5 <canvas> and SVG in the context of creating your application. In the next article, I will walk you through the creation of a geography lesson using karma.js. You will need google chrome or Firefox > 3.5 and the following libraries:
- karma.js
- jquery-1.3.2.js
- jquery.svg.js
- jquery.svgdom.js
You can grab them all here
This tutorial will require a basic understanding of css selectors, jQuery, and the SVG editing application inkscape. karma.js works fine without jQuery but this tutorial makes relies on both jQuery and the jQuery plugin jQuery SVG. If you use chromium, make sure you have web-inspector installed. If you are a Firefoxer, you will need Firebug.
Your Weapons, <audio>, <video>, <canvas>, and <svg>
The success of the Karma Project is contingent upon the good browser support for HTML 5 and SVG. We have seen amazing advances in web technology over the course of the last 12 months, so Karma’s prospects look good! Using SVG for web applications is not well-established, in part because SVG is very complicated specification and in part because until recently SVG has gotten very little love from the Browser vendors.
Twilight SVG: The Standard that Came Back from the Dead
SVG’s stagnation changed in a big way when Google put serious development resources behind it. One of those resources is Brad Neuberg, whom they hired in spring 2009 to evangelize for SVG and other web technologies. There is now a lot of momentum behind SVG.
HTML 5 <canvas> has a nice, simple API and it is fast. Fellow uber-nerds should be excited by the nascent WebGL specification and upcoming GPU acceleration. SVG is quite slow compared to canvas but that shouldn’t be an argument against it. Canvas is faster because it doesn’t have to save its own state. For a number of applications like this tutorial, it would take you much longer to write the same program using straight canvas and would be much harder to maintain. Further, the speed benefits may be negligible in the scope of the larger application. to roughly paraphrase Brad Neuberg, when your graphics need to maintain their state, use SVG. When your graphics don’t need to maintain their own state and are doing performance-sensitive operations, use canvas.
I particularly like the workflows that SVG enables. With SVG, you can first create your images in inkscape, then embed them in your document, then manipulate the image with your code. With canvas, you have to manually write the code to draw the image entirely with javascript code and then frequently redraw large portions of it.
Let’s walk through drawing a circle and then moving it horizontally across the screen using <canvas> and then SVG
<canvas> Example
1. Create the element in your html, make sure you set the width and height in your markup. Your image will become incredibly distorted if you try to set the dimensions using css. I can’t remember exactly why.
<canvas id="myCanvas" width="800px" height="600px"></canvas>
2. Tell Karma about it
var k = Karma({
canvas : [
{ name : "myCircle", domId: "myCircle" }
]
});
3.
k.canvas.myCircle.fillStyle('#000000').beginPath()
.arc(100,100,50,0,Math.PI*2,true).closePath().fill();
var MAX_X = 600;
var myX = 30;
var timerId = setInterval(function() {
if (myX < MAX_X){
k.canvas.myCircle.clear();
myX = myX + 20;
k.canvas.myCircle.fillStyle('#000000').beginPath()
.arc(myX,100,50,0,Math.PI*2,true).closePath().fill();
} else {
//stop the animation
clearInterval(timerId);
}
}, 100);
Please note that the above example uses the Karma API heavily, which is just wraps around the HTML 5 API to save you boatloads of typing.
SVG example
1. Draw the circle using inkscape. I precisely choose whatever color I want with having to actually understand hexadecimal color codes.
2. Give the circle element the id=”svgCircle” by right-clicking on the circle and choosing Object properties
3. embed in the html using the object tag
<object id="myCircle" data="assets/svg/circle.svg" type="image/svg+xml" width="800px" height="600px"> </object>
4. Tell Karma about it
var k = Karma({
svg : [
{ name : "myCircle", domId: "myCircle" }
]
});
5. Move it! Using the translate transformation
$('#svgCircle', k.svg.myCircle.root).animate({svgTransform:'translate(400,0)'}, 5000);
What I like about SVG is that it feels very “webby.” That is, I can manipulate the SVG DOM (Document Object Model) much the same way that I can manipulate the HTML DOM. I can also manipulate the presentation using the same css file I use for my HTML.
I must make an important caveat, SVG’s created in inkscape often do not behave in the browser as you expect them to. I suspect this is because heretofore inkscape has been primarily used to create images for non-browser contexts. That said, I believe that the inkscape team are very interested in making inkscape an integral part of the web development toolset.
I had the pleasure of meeting Josh Andler and Jon Cruz from the Inkscape team at last summer’s Google Summer of Code conference. Both were very enthusiastic about better integrating inkscape with the web workflow.
SVG and CSS
One of the great benefits of using SVG is that you can use the same css file as you do for your HTML document. To use an external css file in your SVG, you need to link it in just above the first <svg> tag.
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <?xml-stylesheet href="../../css/lesson.css" type="text/css"?> <svg ......
When you use the same css file for both your HTML and SVG documents, you need to make sure your element Id’s are unique across all of them. I found it helpful to prefix my svg element Id’s with “svg.” In an application with multiple svg images embedded, I may consider prefixing each SVG element Id with “svg” followed by a short identifier for that particular image, for example “svgAlienQuestion” or “svgShipWing.”
jQuery and SVG
jQuery is a little Javascript library that has taken the webdev world by storm. The jQuery library itself is quite small and almost entirely focuses on DOM manipulation. In this regard it reminds me of the UNIX philosophy “Do one thing and do it well.” jQuery SVG is a plugin that allows you to manipulate SVG documents in much the same way you use jQuery to manipulate the HTML DOM. Pay special attention to the word “document.” Each SVG image embedded in your HTML is a separate document with its own DOM. You need to pass jQuery SVG root element for your target document so that jQuery SVG know which DOM to use.
// In this example you have 3 SVG images embedded in your HTML
// alien, ship, and map. All 3 have been passed to the Karma in the Karma({ svg : [ . . . block
//To change the text inside the alien SVG
$('#question', k.svg.alien.root).text('Some new Text!');
//To add and event listener to the left wing of the ship
$('#leftWing', k.svg.ship.root).bind('click', function() { ....
//hide a mountain on the map
$('#mountainEverest', k.svg.map.root).css('display', 'none');
jQuery SVG makes SVG manipulation very intuitive to those already familiar with jQuery. One drawback to jQuery SVG is that it is not a well-supported tool. Author Keith Wood has done us all a tremendous favor by writing but as yet there isn’t a larger support community around it. I myself patched the .css() method just last weekend to work on Firefox > 3.5 and Chromium. I did not thoroughly test it and I highly doubt that the .css() method will work on Internet Explorer. SVG lovers, if you really want to see SVG adoption take off, I can’t recommend a better place to put your efforts than jQuery SVG.
You can get my patched version of jQuery SVG here and the original at Keith Wood’s site.
The Vampire’s Dilemma
Since SVG is a Vampire Specification, only recently back from the dead, documentation and examples in the HTML context are relatively scarce. Frequently, the most complete documents are the API specifications from the W3C. It is both frustrating and bewildering to work from the W3C specs as you never quite know if X browser has implemented that spec and to what degree of fidelity.
I have also found a lot more browser bugs and inconsistencies using SVG as compared to <canvas>. One glaring bug/feature, depending on how you look at it, is that chromium will not load an SVG document if its display property is set to ‘none’. Firefox will load an SVG with its display set to ‘none’. It took me a number of hours to figure out this inconsistency as it isn’t documented anywhere that I could find. No, I haven’t filed a bug on this yet but I seriously intend to. I swear on my dead pet hamster’s grave.
There is also a well-known glaring gap in the SVG 1.1 API. SVG’s <text> element does not support line wrapping for text. You have break your text manually into <textspan> elements in order to keep it from overflowing bounds of your <text> element. Luckily, there is a clever hack to get around this problem.
Thanks to Mark Finkle for this fix.
<text>
<foreignObject
id="textHack">
<xhtml:body>
<xhtml:div
id="alienQuestion"
style="font-size:20px">Some Old Text</xhtml:div>
</xhtml:body>
</foreignObject>
</text>
To change out the text in the above block, I simply use a css selector and jQuery’s text() method:
$('foreignObject #alienQuestion', k.svg.alien.root).text("Some New Text!");
That may look like a lot of boilerplate text but consider the alternative. Using <canvas> you would have have to redraw the entire canvas area in order to change text embedded in your drawing. That is a considerable waste of computational resources.
That’s it for this installment, stay tuned for Part III, where I will walk you through the creation of a geography lesson.
For further reading, I highly recommend the following resources:
- How jQuery works
- Getting started with jQuery
- The tutorials under the Help menu within the Inkscape application. They are far more comprehensive than anything I have found online,
- Mark Pilgrim’s freakin’ awesome Dive into HTML 5
- The reference guide for jQuery SVG
- Brad Neuberg’s awesome video introduction to HTML 5
- If you’ve got the time, the comprehensive SVG Primer by David Dailey



Nice writeup!
Comment by Brad Neuberg — December 17, 2009 @ 5:42 am
Great tutorial, keep up the great work!
Comment by KChristophD — December 17, 2009 @ 11:05 am
[...] Comparing HTML 5 Canvas and SVG [...]
Pingback by Tutorial III: Digging into Inkscape « Karma Project Learn.Teach.Everything — December 18, 2009 @ 3:34 am
[...] This article,Comparing HTML 5 Canvas and SVG [...]
Pingback by Tutorial IV: The Adventure Continues – JavaScript and SVG « Karma Project Learn.Teach.Everything — December 18, 2009 @ 3:36 am
[...] This article,Comparing HTML 5 Canvas and SVG [...]
Pingback by Karma version 0.2 Released « Karma Project Learn.Teach.Everything — December 20, 2009 @ 4:23 pm
“With canvas, you have to manually write the code to draw the image entirely with javascript code and then frequently redraw large portions of it.“
Not entirely true. Opacity (http://likethought.com/opacity/) has the ability to export a javascript function to draw a vector image in a canvas. While SVG support is much more widespread, it is at least possible to use the same kind of workflow for canvas based animation.
Comment by Paul — December 23, 2009 @ 7:29 am
tks Paul,
What advantage do you gain by drawing a vector image in canvas? Is it faster overrall? Have you used this approach?
Comment by bryanwb — December 23, 2009 @ 10:40 am