Why implement vector graphics on Canvas when you could use SVG?
EDIT: Seems to be answered in the FAQ: "We have decided to use the Canvas object as the main backend for now because it is faster than SVG and allows us to implement and optimize our own Scene Graph / Document Object Model. We will be offering SVG (and hopefully PDF) importing and exporting in the future."
But it seems hard to believe that doing vector->bitmap rasterization in JavaScript is going to be faster than using the browser's SVG implementation (written in C++).
There's no reason that a Canvas implementation would be doing rasterization in JavaScript; the Canvas API is like Postscript or the Cairo API, and javascript will only be calling high-level functions such as specifying gradient or Bezier curve parameters.
I don't think SVG is particularly suited to animation, as it would require manipulating multiple DOM elements. This tends to be quite slow compared to redrawing the canvas.
SVG is hardware accelerated in IE9 and coming to Chrome as well. When that happens I doubt there will be much of a difference performance wise. Canvas and SVG will serve different ends. Doing something like GUI in Canvas would be an incredible pain, whereas doing it in SVG (using raphael.js) is a breeze. Canvas is better for games.
The alternative is keeping your own "DOM" of vector objects in a JavaScript-based scene graph. Why would this be more efficient than manipulating the DOM?
The problem with SVG was that it wasn't really designed as much as it was dreamed. And it was also dreamed up in the middle of the whole "all data must be shoe-horned into XML" collective nightmare, which makes it less than ideal as a scene graph.
It was also abandoned as soon as Adobe acquired Macromedia, and thus Flash, meaning that there was no longer any reason for Adobe to push for a Flash alternative. There have never really been any good implementations, and it seems as though the spec wasn't written by anybody who'd have to eventually write an implementation.
For many many years the web browser implementations have been buggy and incomplete, and it was always difficult for me to figure out what I could and couldn't use on which browsers and which operating systems. I don't have any specific complaints other than a myriad of tiny tiny headaches that I've left in the past. A lot of them revolved around text APIs and especially the DOM interfaces. I ran into far fewer bugs and inconsistencies when just using static XML.
From what I can tell the browser implementations are getting much better. It has been very odd that browsers have been shipping half-broken implementations for years, and the specification was released in 2003, a full eight years ago.
I think that the failure to implement SVG can largely be traced back to the extreme breadth and complexity of the specification. It's much easier to read through the specification for OpenGL or Postscript than it was to make it through the SVG specification, though I admit that a procedural API is almost necessarily simpler and easier than a stateful scene graph that includes a procedural API on top of it. Maybe SVG Tiny and Mobile mitigate the problem, but those came far too late to make a difference, and SVG 1.1 certainly wasn't deprecated in favor of a smaller and more implementable set of functionality.
In ay case, I'm not going to be guinea pig for SVG again. I may pick it up when others have proven that it has several interoperable implementation on separate OSs, but I still consider it one of the bigger time-sucks and poor architectural decisions I've made. /rant
Thanks for writing that up. I've gotten more interested in SVG ever since Protovis's successor d3 adopted an approach of writing SVG directly. d3's has some impressive demos built on top of SVG in an impressively small amount of code: http://mbostock.github.com/d3/
I do think it's unfortunate that lots of W3C standards like SVG were well-positioned to be very widely used, but ended up being so big, complicated, and not informed by actual implementations. I've ranted about this before: http://news.ycombinator.com/item?id=2521885
Regarding vector graphics performance, there's a weird way to use SVG that is sometimes much faster than Canvas: use string concatenation to build up a huge blob of SVG markup and then splat it into the browser all at once by setting innerHTML on an SVG element. We rely on this trick for UI performance in our web app. In fact, we do it on every scroll and/or mousemove. The amount of computation you can get away with in JS without noticeably slowing down the renderer is nothing short of astonishing.
Given how clunky SVG can be, it's surprising that this technique works so well. I believe the performance gain comes from batching everything you want to render into a single ginormous round trip between JS and native code. With Canvas, you don't have that option, so you have to cross the grand canyon with every call. The equivalent in SVG would be making a series of tweaks to the SVG DOM, and that's even slower. Much better to rebuild the entire DOM yourself in text and overwrite the old one.
As a bonus, you can take the same approach in IE using VML. Though the markup is different, the SVG and VML models are close to isomorphic - not close enough to abstract over without an annoying impedance mismatch, but much closer than either is to Canvas. Thus this technique affords a good way to get graphics performance out of both the modern browsers (SVG) and the pre-9 IEs (VML) for as long as the latter are around.
That approach you describe to building an SVG tree is a common performance optimization when manipulating the DOM for HTML as well. I'd be curious to hear if you've tried a) using a DocumentFragment, b) detaching the node using removeNode, manipulating, then adding it back, and c) simply working with a node (createNode) and then adding it in after manipulations are done. The basic idea is that working with the live DOM is slow, while working with detached nodes is fast. Note that I haven't really tried this stuff out that much. Maybe I'll work up a little benchmark over the weekend or something.
I'm pretty sure Paul Irish's talk [1, 2] is where I read about this.
Yes, using innerHTML to bypass the HTML DOM is the poster child for this kind of thing.
We've tried all the alternative techniques you mention (with HTML DOMs, that is - I don't think any of them work with SVG) and had disappointing results.
I haven't used Paper.js, but I've used Raphaël and the main differences I see right now is that Paper uses Canvas, while Raphaël simulates/uses SVG. As a result, Paper should be more practical for making dynamic content that uses user input or is "very dynamic".
Raphaël on the other hand, provides a simple system for making relatively "static" vector images with very good support for a lot of browsers (IE6 support, even). If you need user input, I think I would've tested out Paper and most likely ended up with that.
So basically: Raphaël for vector images that may be scaled and simple, dynamic images. Paper for animations and e.g. games.
Paper.js admits to not supporting IE < 8 (bottom of http://paperjs.org/about/). Other browser support is not even listed. I guess this means that it's not usable for most serious end-user apps now.
I'd say that not supporting browsers below IE8 (or even IE8 itself) is reasonable for many projects. I just looked at the stats for a few of our sites and total IE browser share is around 4–7% on them.
If you have a similar situation on your site/application, I think it's perfectly reasonable not to support anything other than modern browsers, but you have to look at your own stats.
default smoothing example uses 52% - 62% CPU at run time on my macbook pro i7 duo core 2.66GHz laptop. Bouncing ball uses 100% on average. Pretty cool script! it makes a good example what today's browser is capable of.
Yeah but you are really comparing two different things here (regardless of IE support). If we just compare svg (raphael) and canvas (paper), we see SVG is not as recommended for animation whereas canvas is.
Raphael has put a lot of effort into a very robust DOM-based animation implementation, and at least in their examples and my experience their animation has worked beautifully.
Anyone happen to know where I can find general information on implementing something like this? http://paperjs.org/examples/chain/ I'm interested in implementing this mechanic in Flash (for a game). I looked through the source code and it seems like a lot of code just to get to the point. Hoping to find something more basic that I can port over.
I think you got something wrong there. The source code for chain (accessible by pressing the "source" button on the top right corner of the page) is just 35 lines long and only does the chain/snake effect.
Yes, it's 35 lines. But that's not including the source. Such as the definitions for Point(), which is a couple 100 lines of code, not including its dependencies. I want to port it over to Flash, which is in ActionScript not JavaScript.
proce55ing is great for what it is / does, but there's a large gap between that and building functional games and animations, which isn't addressed by their screen graph model (nor this one). At issue, and missing, are parent-child relationships in which transformations and mouse events can be factored or transmitted up or down a display chain in the screen graph. To my knowledge, the only existing library that does this on Canvas is StrikeDisplay (strikedisplay.blogspot.com). In general, the ability to do that doesn't impinge on the ability to use native canvas vector functions in any way; but it simplifies the mixture of vector and raster images for animation, and acts as a better tool to let coders focus on the game they're trying to build rather than the intricacies of the canvas processing -- or to step it up, the raster and/or vector transformations -- behind something like:
var a = new Sprite();
var b = new Sprite();
a.addChild(b);
b.x = 100;
a.rotation = 45;
Which ideally should rotate both a and b by 45 degrees clockwise, with b offset in the rotation around a's axis by 100 px.
hm. EaselJS has evolved since I last saw it. The parent-child relationships look good. +1. -1 is Grant got the same idea I had about two years ago after seeing my code, and has gone through 3.2 major revisions to still arrive at a relatively inferior product with 10x as much code. (yeah, I wrote strikedisplay =) Not only that, he's the loon who's responsible for Flash 5 being a completely unusable product because of his insanely horrible side panel components and his greed in pushing them through with Adobe. Oh yeah, I also insulted him about the project panel which led him to rip off my work from StrikeDisplay.
All that aside, it does appear that in the newest version Grant has finally caught up to almost where my code was about a year ago, and since I haven't maintained the project for almost two years, that's saying a lot =) Great work Grant! If I had a serious HTML5 project, I'd just loooove to use your code for it =\ hah. Although I'm sure if one of those arises I could write something better in a few hours.
The trouble is, right now there is still nothing to be gained from writing something on a Canvas. It's too slow to play on an iphone, and there's no point in using it on a desktop when you can use Flash. And now anybody can release a game in html5 w/o any coding whatsoever, guaranteed. Grant: We are both pissing on the same lamppost in hopes of adding a tiny pile of sodium to it. Who gives a fck. Seriously, God Bless, just "rule the universe in HTML5". I only wrote my code a couple years ago to prove it was slower than the same thing in Flash. You want to make a life's work out of it? 3.2 major revs? Go ahead man.
EDIT: Seems to be answered in the FAQ: "We have decided to use the Canvas object as the main backend for now because it is faster than SVG and allows us to implement and optimize our own Scene Graph / Document Object Model. We will be offering SVG (and hopefully PDF) importing and exporting in the future."
But it seems hard to believe that doing vector->bitmap rasterization in JavaScript is going to be faster than using the browser's SVG implementation (written in C++).