Skip to: Navigation | Content | Sidebar | Footer


Weblog Entry

Illustrator to HTML5's Canvas

January 14, 2010

I’ve spent a bit of time playing around with HTML5’s canvas element lately. It’s a fun new toy and has a lot of potential to be useful. But the biggest headache I’m finding so far is the lack of authoring tools.

SVG has been around for ages, whereas Canvas is still relatively new. (Mozilla’s Vladimir Vukićević has a good overview presentation of the differences between the two, and when and where to use each.) SVG support is built into plenty of graphic editing tools; Canvas support is so far sadly lacking, although Matt May pointed me to this YouTube video that shows off the upcoming Canvas support Adobe’s CS5 suite will have, whenever it becomes available.

In the meantime, most of the Canvas demos we’ve seen thus far have mostly featured simple primitive shapes like lines and ellipses for good reason: it’s too hard to build up a reasonably complex vector image by manually plotting bezier curves.

Over the past few days I’ve tried out various ways to get around this problem. I came up with two methods of taking vector shapes out of Illustrator and rendering them with Canvas, both involving an intermediate step as SVG first.

So to start, from Illustrator (or any other vector editing application capable of doing so) export your artwork to SVG. You’ll find the SVG option in the Save As / Save a Copy dialog, and I’ve found the SVG profile you choose doesn’t really make much of a difference (though for the sake of argument I’ve been using 1.1).

We’ll use this happy little cloud image as our reference file:

1) Manually

This method is only theoretical so if you’re looking for the actual how-to, skip ahead to #2. I figure it might be worth writing this up anyway because, even though I couldn’t get it working, perhaps it’ll provide enough of a starting point for someone else to pick up where I left off and build a proper converter.

SVG and Canvas are both essentially vector drawing tools; Canvas is more pixel-oriented, but you are certainly able to plot lines and curves mathematically. Canvas is also limited to fewer primitive shapes, but there are obvious parallels between the two.

I spent a bit of time looking into the bezier commands in particular. In SVG, to plot a bezier curve, you do something like this:

  <path d="C x1,y1 x2,y2 x,y" />

In Canvas, it’s this instead:

  ctx.bezierCurveTo(x1,y1, x2,y2, x,y);

Different syntax, but the same basic components: you’re drawing a line from the current pen position to the x, y value, and before that you have two additional points (x1, y1 and x2, y2) that set your handles. (More SVG path commands, Canvas path methods.) It’s worth noting that SVG is more forgiving about commas; each coordinate must be separated by a comma for the Canvas method, but they’re strictly optional in the SVG example. This is relevant because Illustrator’s SVG export seems to be wildly inconsistent about when and how many commas each command uses.

Given the similarities, I thought it might be fairly straightforward to manually tweak the SVG output into Canvas drawing functions. M becomes moveTo, C becomes bezierCurveTo, and so forth.

  <path d="
    M 62.58, 31.96
    c -0.711,0 -1.811,0.062 -3.181,0.165
    c -0.566 -6.309 -5.862 -11.255 -12.318 -11.255
    c -2.363,0 -4.564,0.675 -6.442,1.824 "/>

Becomes:

  ctx.moveTo(62.58, 31.96);
  ctx.bezierCurveTo(-0.711,0,-1.811,0.062,-3.181,0.165);
  ctx.bezierCurveTo(-0.566,-6.309,-5.862,-11.255,-12.318,-11.255);
  ctx.bezierCurveTo(-2.363,0,-4.564,0.675,-6.442,1.824);

This did not work. I suspect the absolute vs. relative coordinate difference between SVG’s c and C commands tripped me up, but after a half hour or so of poking around this was all I had to show for it:

Still, even if I’d have managed to get it right, I’d rather not have to manually massage my SVG output every time I want a new Canvas drawing. Which leads me to method #2.

2) Automatically

One of the main reasons I bothered to attempt a manual conversion in the first place was because after an extensive search it appeared that people are mostly interested in converting Canvas to SVG. There are very few articles and tools that cover going the other way, which is what we’re after. Maybe I didn’t come up with exactly the right search term, but I was finding so little I almost gave up entirely.

Then after one last shot in the dark, I managed to stumble across SVGToCanvas, a Java library that promised to do exactly what it sounds like, with a few disclaimers and a major caveat:

  • You need Java 6. Otherwise known as 1.6, this comes installed with Mac OS X Snow Leopard but previous versions will need to upgrade. I believe this is the download necessary for Leopard, if you’re on an even older version you’re on your own. No idea what the Windows situation is, but this might be a good place to start.
  • You need to run it on the command line. I know this will freak out some designers, but really, it’s not terribly difficult.
  • You mainly get outlines for now. This would be the big ugly caveat. Sometimes you get colour and gradients, sometimes you get mixed-up colour and gradients, mostly you don’t. Plan to re-add them manually. Hopefully this will work better in a future version of the library, but still, having outlines is a solid start.

Still with me? Great, go grab the JAR file and drop it on your hard drive somewhere easy to find. For now, probably best to drop it in the same folder with the SVG files you’re going to convert.

Now, load up the terminal, and find your way to the same directory. Here’s a quick command line primer that ought to get you going. The cd, ls, and pwd commands in particular are the ones you need.

(If you need a bit more help than that: put the SVG and JAR files in a folder on your Desktop called ‘canvas’. When you open up the terminal, type this minus quotes: ‘cd ~/Desktop/canvas’. Hit return. You’re good, keep reading.)

Run the converter with the following command:

  java -jar svg2canvas.jar -o cloud.html cloud.svg

From left to right: we’re invoking Java with the SVGToCanvas library, then by -o cloud.html we’re specifying the output will be written to cloud.html, otherwise it just displays the output in the terminal (which can be handy if you’d like to just copy and paste without managing temporary files). Then finally at the end, cloud.svg is the input SVG file that we had previously generated from Illustrator.

That generates an HTML file which contains a canvas element and the Javascript necessary to render the cloud:

In this case it worked, though it added a stroke. When it’s just the outline, you can restore the colour by manually tweaking the code. Add a fillStyle method before the draw, and a fill after:

  ctx.fillStyle(#4a6481);

  ... (drawing commands here) ..

  ctx.fill();

Not too difficult for simple shapes. I’d hate to have to manually re-add the subtle gradients for more complicated illustrations, but it’s nice to know the outline conversion is fairly robust:

Figure: SVG original on the left, the converted Canvas version on the right.

One more thing: I’d recommend flattening the vector art as much as possible. Join shapes that can be joined, expand effects and compound paths and masks, and generally clean up the artwork to as few points as possible. Smaller file sizes, more chance of success upon conversion.

So there you go. It’s still a fairly painful way to get your vector work into a canvas, but until we get some better tools or built-in support for our existing tools, it’s one way to fill the gap.


January 14, 20h

I was trying to search for a method to do this earlier today but I gave up. I’m so happy that you found this! Thank you!

2
Anders says:
January 14, 23h

I haven’t used it that specific functionality myself (it seems to be disabled in the trial software), but Opacity has the ability to export to Canvas (Opacity calls this a factory). http://likethought.com/opacity/

January 15, 01h

I already tried some svg-figures with canvas dave, but your small “tutorial” gave me some inspiration for antoher figure. Thx for publishing!

January 15, 07h

nice write up. I wonder how well canvas will catch on given the amount of time it takes to draw something with javascript.

I’d be interested to see how far it can go in replacing some of the more basic web-based flash games… like, i dunno, tetris or something.

January 15, 13h

@Anders - I gave it a shot, and *was* able to get it to work in the trial. I had to draw the item using the Opacity drawing tools as the SVG import seems to render it like a bitmap. I was able to make a cloud-like shape, but didn’t quite grok how to make negative spaces like the eyes and mouth. Anyway, it seems Opacity might be worth a second look for this type of thing.

January 16, 03h

There’s a whole host of canvas demos (both primitive and complicated) on http://www.canvasdemos.com

Hopefully we’ll begin to see some proper authoring tools appear on the scene soon, Adobe CS5 for one.

KS says:
January 18, 08h

Hey Dave, it should be noted that this technology was demoed at what Adobe calls a “Sneak”, which means that this is technology that they’re playing around with and has no guarantee of ever seeing the light of day. They’re just showing what “could be.”

I did a write-up about this a few months ago which includes a link to the full disclaimer.

http://kevinsuttle.com/how-adobe-made-the-flash-platform-beyond-future-proof

January 18, 15h

Hi, have you looked into doing a straight conversion? PostScript and the .AI format are surprisingly readable, if you’re comfortable with numbers.

The keyword on the sneakpeek video is “FXG”… it’s a tool-neutral representation, already supported in the Creative Suite tools. You don’t need to wait for Adobe to do anything more to enable it… FXG format is already there.

jd/adobe

9
Jeff says:
January 22, 16h

Seems like a major shortcoming of canvas that it is so verbose and time-consuming.

andrew says:
January 25, 04h

I have to agree 100% with the previous guy’s comments re: verbosity.

I too have played around with the canvas tag and found that for even relatively simple graphics there seems to be a disproportionate amount of coding required.

andrew says:
January 26, 18h

Further to my last post, why doesn’t someone round here set up a sort of html canvas garden? You know, a bit like that CSS garden thing that some Canadian bloke set up a few years ago.

Carla says:
February 17, 14h

That will open up some really interesting design possibilities, but the pessimistic side of me thinks it will be years before you could use it as a standard design element without having to have a second design for older browsers.

February 23, 09h

There is a chance that Inkscape, the open-source vector drawing program, will soon support exporting to Canvas commands, but in the meantime, it looks like there are other options. See the discussion at:

http://www.inkscapeforum.com/viewtopic.php?f=28&t=3421

Sam says:
March 16, 11h

Thanks for the interesting write up and link to Matt’s video on youtube. I have been playing around with the canvas element over the last month and have been slightly let down by the amount of code it takes to create a simple illustration.

15
Rick says:
March 23, 13h

Another approach, using Illustrator to author the graphic:
Skip SVG altogether.
AI can be scripted, with an Adobe extension to JavaScript (Extend Script). When executing such a script, it has document object access to the object structure of the current document. In theory, a conversion script could be written that traverses the internal tree and emits canvas code to a file.

Eva says:
March 26, 12h

Nice tutorial Dave! Your predictions are right! I’ve been wondering about Canvas-to-SVG for a long time :P I also think it will be better if adobe suite 5 does support canvas. Even though canvas looks like it’s too much work.
BTW, it doesn’t work on IE. What a shocker :P