One of these mornings, in need of generating images with “copyable” text with Node, I had the chance to play around with RaphaelJS.
Where to start?
The idea is very simple, as raphael is basically just a simple API to draw SVGs on a canvas, and it does that on a browser / DOM — here you can see a map of Australia, from one of their examples:
The problem is, how do you generate those images in a simple way from the server? There is no notion of DOM and window until you really deliver your response to the client, right?
A simple approach
It all starts from one docker container that runs (sorry :-P) IO.js:
1 2 3 4 5 6 7 |
|
At this point, you need to do simply create an index.js
that will run our server and npm install
2 dependencies,
raphael and
jsdom.
Now, jsdom will be taking care of creating a virtual browser window and environment for raphael which, as soon as you require it, will be trying to access some global objects that are only available on a browser:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
|
Now, the code is ghetto as hell, and that’s the way it’s supposed to be in a sample post like this one — you will definitely ned to address a couple things if you want to do more complex things:
- now raphael “draws” a global window object, while you
should probably initialize a global window and a “local”
one and assign a new, local one to a new instance of
raphael on every request (note the
setWindow
method)1 - in general, it would be nice to split responsibilities around rather than having a one-file thingy
- you definitely want to render more than “Some text” :)
This would probably be a good place to start to create a dev-friendly interface:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
|
(note that this example assumes you handle errors on your own and have been used to promise libraries such as Q or Bluebird)
To wrap up
So yeah, it’s definitely simple to start generating SVGs from the server through Raphael, though the approach is quite hackish — and, to be honest, you might find even more gotchas since it’s running on a virtual DOM / window.
But, at the same time, this gives you an idea on how feasible something like this can be — for example, do you know those badges you see in a lot of github repos? They come from shields.io, that empowers a similar approach, although it’s simpler but more structured (they generated SVGs from templates, which I think it’s a pretty solid and robust idea).
In one of the next posts I am actually planning to show a simple way to roll your own badge generator out. Not that you should, but it’s definitely nice to see how these things work :)
- The ideal solution would be to inject the window to Raphael, but I dont think that’s currently possible, see: https://github.com/DmitryBaranovskiy/raphael/blob/master/raphael.js#L400 but correct me if I’m wrong ↩