Chris

Lee

Content

Copywriting

Design

How to Make an Interactive SVG Map


November 6, 2019

When you see an interactive map like this one, you probably think it’s super complicated to build.

The actual idea, though, is quite simple.

There are several layers:

  1. A static image of a map.
  2. An overlaid layer of invisible lines.
  3. Shapes that appear when you hover over them (optional).
  4. Pop-ups that appear when you interact (optional).

The static image of a map is self-explanatory: that’s what we see, and what gives the map meaning.

The overlaid layer of invisible lines lets you interact with the map: if everything is configured properly, they are overlaid exactly onto the map borders. This means the map detects which state, country, or territory you are hovering over or clicking.

The shapes that appear when you hover over them are a way to make the map interactive. Hover over a state and it changes colour, although obviously that’s not the static image changing colour. It’s a polygon the exact same size and shape as the state below it that appears temporarily.

The pop-ups that appear when you interact are another way to make the map interactive. Click a state and a box can pop up with information about the state. Again, in real terms, the static map image doesn’t change, but for the human user, the map as a whole appears more interactive.

Here’s how to make one.

Step 1: Find a suitable SVG image

SVG stands for ‘scalable vector graphic’. This type of image can scale to any size and never lose resolution.

Wikicommons is a good place to look because they’re all in the creative commons, and therefore free to use. I typed “US map SVG” into the search box and tons popped up. Be careful of historic maps: these can pop up in search results but they’re obviously out of date.

Open the search result, then save the file. Make sure you’re saving the raw SVG rather than a PNG version of it. You can tell by the format in the Save dialogue box:

Double-check SVG is selected. If the option isn’t there you’re trying to download the wrong file, so head back and look for an option that says ‘Download original file’ or similar.

Step 2: Open Adobe Illustrator

Illustrator is a program you can use to manipulate SVG files.

I’m using a free trial, and the stakes are high for this blog post! Hopefully Illustrator doesn’t crash, or I’m f*cked.

Step 3: Open your SVG file

This step is nice and easy. Just open the file.

Step 4: Make any edits

This is where you can change the SVG file to suit your needs.

If you’re versed with Illustrator you can change the paths, although the main draw of downloading an existing SVG file is that this work is done for you.

One thing I recommend doing is removing any text from the map, as well as any labelling lines.

This is because each line and shape is referred to in the source code by a string of coordinates, so the more elaborate a shape, the more coordinates will be required to draw it.

In this format, state names represent a huge amount of code, and will make the final product unwieldy:

There are 367 lines of code without state names, 2356 with them.

Also, check out the file size comparison below:

To remove things, just select them with the mouse and hit delete. You can hold shift to select multiple things at the same time, too:

Step 5: Save your file as an SVG

Save the tweaked version of the SVG file you originally downloaded. Make sure you keep the SVG format, as shown below:

Then, you’ll want to hit the SVG code button in the dialogue box that pops up:

This will spit out some raw code looking a bit like this:

And we’re going to feed this code into ReadySteadyRaphael…

Step 6: Convert your code to Raphael-friendly format

ReadSteadyRaphael is a site that rejigs SVG code to be compatible with raphael.js, a popular Javascript library for creating and styling SVG maps.

You need to copy the contents of the file that Illustrator just gave you into the site, then copy the resulting code into a new file. This will be the Javascript file that your map is built upon, so give it a clear and memorable name.

Mine is called map.js.

Save map.js into the same folder as your SVG file.

Step 7: Tidy your Javascript file

When you open map.js, you’ll be greeted with some garbled nonsense like this:

You can see a couple of state names in there (red rectangles), which is a blessing. Some SVG files include random strings instead, and you have to go through the process of seeing which string of code relates to which other string of code.

In this example, the process is easier. If you find a bunch of random code, trial and error is the best way to remove the clutter (this isn’t a copout, honestly! Each file will be different, so there’s no reliably useful advice I can give).

Once any clutter is removed, tidy the code so it’s easier to read. I use Visual Studio Code, so doing this is just a case of pressing Alt+Shift+F

Step 8: Add a few bits to the code

The most important thing is to change the ‘rsr’ in the first brackets to the ID of the div element you want your map to sit in.

To give yourself more options later in terms of functionality, I recommend a few things. Let’s take a look at the code:

  1. Naming variables after states or territories makes them a lot more intuitive to refer back to later.
  2. This jargon is the coordinates for the outline of a shape. In this case, Hawaii. Nothing needs adding here, but it helps to know what you’re looking at.
  3. Adding a unique class name for each territory is useful for individual styling later (see next step).
  4. Stroke-width, stroke-opacity, and fill are where you can style your states. These values end up looking something like the image below this list.
  5. Pushing each territory to a group called ‘regions’ is an artefact of the tutorial I first followed. I don’t use it for anything specifically but have left it in just in case it proves useful later.

This is what stroke-opacity 1, fill #febdbf looks like

Step 9: Assign classes to each path to make them targetable with functions

Here’s a bit more information about why I recommend adding unique classes to each state.

On the left is the SVG code, and on the right some Jquery functions that allow buttons to change the properties of the map:

  1. Texas is assigned two classes: texas-sel and st0.
  2. The first function colours just Texas red.
  3. The second function resets all paths with st0 classes to the default colours.

This means that you can set up multiple functions, each to target any combination of states with a query to recolour them, but only one function is required to reset everything.

Here’s what it looks like:

responsive SVG map gif

(I’ve since improved this code to incorporate the reset function into all functions, hit me up if you want instructions for that.)

Step 10: Make your SVG responsive

This took me bloody ages to figure out, so I’m hopeful that this step will save you a lot of time:

Raphael treats dimensions in a slightly different way to other SVG handlers, which can interfere with certain methods of making responsive SVG maps.

Originally the first line specified the pixel dimensions of the map, instead of percentages: i.e., ‘1280’, ‘960’ instead of ‘100%’, ‘100%’.

This meant that the map rendered to that size regardless of viewport size.

By putting percents, and using the line below to set the ViewBox property, the map is now restricted to the size of its parent container, and it scales accordingly.

Step 11: Download Javascript dependencies

I’ve mentioned Raphael a few times. You need to download this Javascript library for the map to work.

You can do that here: grab ‘raphael.min.js’, and save it into your map directory.

You’ll also need JQuery, which you can grab here. Whack that in the directory too.

Step 12: Create the HTML file for your map

Now you’ve got your map Javascript sorted (map.js), it’s just a case of giving it an HTML file to sit within.

The most basic template you need is below. I’ll leave it to you to embellish it, although again: hit me up if you need any help.

Note that raphael.min.js, map.js, and jquery.min.js are all enqueued. These must be enqueued for the map to work.

Remember: the map will sit in the div whose ID matches the one specified back in Step 8!

Resources

This excellent tutorial pointed me in the right direction.

ReadSetRaphael helped in converting code into the right format.

As usual, a ton of StackOverflow answers helped. In no particular order: