SVGCanvas is a JavaScript implimentation of most of the Canvas drawing API which creates SVG grapics elements instead of drawing to a pixel buffer. I wanted a way of scripting the creation of SVG graphics without always explicitly managing the DOM tree. Since Canvas is becomming a de facto web standard and the two interfaces are similar (e.g. linear and radial gradients of the same form) I took advantage of the API.

Canvas is a pixel-based representation like a paint program. You can draw shapes over each other and they will modify the pixels. SVG is more like a drawing program where shapes are always there even if they get covered up.

Canvas is a stack-based API where you set the color and line style, move to a spot, draw some lines, set another color, draw more lines, etc. Almost all graphical libraries impliment this becuase in many situations it's more convenient and efficient than passing the parameters with each call. SVG is a tree representation where you can group objects and apply fill color, for example, to the whole group that get applied for every member that doens't explicitly specify their own fill color. Some things are cleaner to do in one model or the other. See Canvas and SVG slides by Robert O'Callahan at mozilla.org for a good overview about why the web needs both.

It was easiest to get SVGPlot to efficiently generate clean SVG code using a combination of DOM tree manipulation and Canvas calls. Why would you want this?

When wouldn't you use this?

Live Demos

Browse Code in SVN Repository

Related Work


PostScript was a vector drawing state-machine-based language, PDF is a subset without the programming language pieces (conditionals and loops). Canvas is a drawing API inspired by PS and PDF. SVG is a scenegraph representation. It's like the difference between OpenGL and Open Inventor. All drawing of windows and widets in NeXT was done used PostScript, and in OS X using PDF. The advantage was that the same code that is drawing to the window can be used to draw to the printer without any translation.

Canvas, though simple, is quite powerful, supporting transparency, gradients, clipping, blending, bezeir curves, and others that Win32/GDI and QuickDraw2D, and Java's AWT do not. Except for transparency, these features come from PostScript.

State-Machine / Stack-Based / immediate-mode Scenegraph / retained mode
2D PostScript
Quartz 2D / QuickDraw 2D on OS X
Java AWT java.awt.Graphics2D
Windows Win32/GDI
3D OpenGL
Open Inventor/ Performer / Coin3D
OpenGL++ / Cosmo 3D / Fahrenheit

Sometimes you want direct access to the pixels. In photo manipulation, 3D per-pixel lighting and shading, non-linear transformations, displaying image or video, a smoke or fire effect, filters, or interval graphing techniques. Dealing with a 2D array of pixels is more efficient than drawing a rectangle for each pixel using vector-graphics techniques. Some of these are addressed in the SVG filters -- you can have your drop shadow and the advantage of SVG. The other advantage is being able to both read and write the pixel array.

Overview of Canvas API

Overview of my Canvas Implementation using SVG

There is a single object SVGCanvas which acts like Canvas's 2D context that you get from getContext("2d"). Maybe I should have called it SVGCanvas2dContext to keep my options open for 3D, but X3DCanvas is probably a better route.

There were some decisions to be made regarding trading off speed to create the SVG, speed to render the SVG, generating clean factorized SVG. What happens when you draw, transform, draw, transform, draw, etc.

SVGCanvas keeps the current state and a stack of saved states. The state includes things like the fill style and transformation, but not the path. An SVG element is only written to the SVG when you do a fill(), stroke() or clip() or things like fillRect() that call one of these.

Gradients, clipping paths, markers, patterns, and other objects that you define and use many times are created by standard Canvas methods or a Canvas inspired SVG-only one.

Overview of SVG Extensions

Since I want to be able to use this as an easy way to draw into an SVG rather than just a pure Canvas implimentation, there are several SVG specific features.