Last Updated: February 25, 2016
· javier_toledo
Seriousmeh square

Creating an interactive SVG map

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

  • 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.

Say Thanks