RaphaelJs is an awesome library for vectorial drawing on a website, specially suited for interactive graphics. In a recent project I created a RaphaelJs interactive map for spanish provinces which you can test here:
Or fork here:
The process of creating such a map from an SVG file requires some processing and tweaking over the SVG source:
- Extracting SVG path strings and creating a JSON object for RaphaelJs
I wrote a simple ruby script to parse the SVG file, extract points and build final paths from them. As my source file had mixed paths, polilynes and polygons, I had to normalize them as paths to simplify later steps. You can find the script here:
I discovered later that there are online services designed to do this job like http://readysetraphael.com/
- Tweaking and joining some paths.
There are provinces in Spain composed on more than one territory, for example those composed of islands. In order to unify events detection for province I concatenated all the province's territories on a single path string per province. You can do this because first operation on each string is a "cursor movement", so Raphael will then render exactly the same but with a single Path object.
This is how looks like my paths file after extracting and tweaking, I also added some convenience fields to each path, a number and a name:
- Loading and rendering paths
Once reached this point things become more straightforward, just need to initialize a Raphael Paper object and iterate over paths drawing and adding some event listeners to them.
- Optionally you can fit the map in the container div adding the paths to a Raphaël set and then centering RaphaelJs view on its bounding box with Paper.setViewBox(...). (Then I realized this wasn't the best idea, see the update below)
Here is the full loader which renders and centers the map:
Update: Some people noticed serious performance issues with the map on Firefox and IE and after some investigation I discovered the bottleneck were at calculations of the map bounding box. As this data is always the same, I've replaced this calculation for precalculated values obtaining significant improvements in performance.