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:
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.
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.
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.
This step is nice and easy. Just open the file.
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:
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…
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.
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
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:
This is what stroke-opacity 1, fill #febdbf looks like
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:
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:
(I’ve since improved this code to incorporate the reset function into all functions, hit me up if you want instructions for that.)
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.
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.
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!
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: