DEV Community

Cover image for Interactive SVG + JS map
Luca Faggianelli
Luca Faggianelli

Posted on

Interactive SVG + JS map

Now and then, on several web applications projects, I need to use maps to display data, sometimes it's a world map, sometimes a country map with regions and provinces, often I need a click-on-region event handler and I always need to display some data on the map as colors or numbers. You know what I'm talking about right? Not a Google Maps map, but a simple and plain map with country borders.

Of course there are libraries for this purpose, also free ones, but not so many and they're pretty heavy as they bring a lot of functionalities, whereas I just need a simple map, so I like to make my own map, also because it's fun 🙂. Let's make it!

Get started

The first step is to find a map in SVG format, I typically use simplemaps they have world and regional maps and they're free to use (check the license for details).

When I speak of regions I refer to geographical regions, that is any of country, region, province, state, area, etc.

Now we're ready to go, these are the features we're going to implement at the end of the article:

  1. Load the SVG map and render it into the HTML page
  2. Color the map regions based on supplied data
  3. Attach mouse events listeners (for click and hover) to regions

So let's start with step 1 and part of 2:

Yeah so easy! I only used a tiny library for SVG manipulation called Svg.js, even if it's not mandatory, it makes life a bit easier.
In the codepen above we load the map SVG file content with the fetch() method and we render it into the HTML, then we manipulate the map adding labels and changing the colors just for demo purpose.

Please note that I'm selecting the map regions with draw.find('path') but if you use another map, the regions may be represented by <g> elements or may be inside nested into other elements.

OK let's make this thing a bit more useful, I found Belgian population data (2019) on Wikipedia and we're going to plot it on our map, plus we'll make it interactive!

Better? Now we have real data and each region's color represent its population, the colors are shades between green and white, whereas the most populated region (Antwerp province) has a mix of 100% of green and 0% of white, while the least populated (Luxembourg province) has more white than green: this is called a heatmap. As for the interaction, if you hover a region, you get a popup and the region color changes. The color effect is done with CSS to demonstrate that you can style an SVG element (and its children) with plain CSS.

This is pretty basic, but it's good starting point for creating a fully featured map.
I'm going to extend this demo with more features and I'm going to package it into an NPM library, so stay tuned!

Well now I'm curious, do you use maps and for what? Do you use them in apps you develop or in blog post or whatever? What library do you use?
Questions and feedbacks are highly appreciated!

Luca

Top comments (10)

Collapse
 
anwar_nairi profile image
Anwar

Very cool! I did not know this tool.

On my previous job, we had to be able to drag, pan and rotate a map, and we first used npmjs.com/package/svg-pan-zoom, but we came up to some difficulties when adding the rotation. So we ended up creating our own SVG engine. It was fun to do!

Collapse
 
lucafaggianelli profile image
Luca Faggianelli

Thank you! Yeah pan and zoom may be very tricky, in fact also svg.js has some glitches in certain cases during panning, but overall is very useful and light.

Collapse
 
redtigerr73 profile image
Redtigerr73 • Edited

Hello Everybody,

First of all Thanks Luca for your code.

It's exactly what i'm looking for a small project at school.

Problem is when I use exactly the same code as your, the map never is displayed.

Any idea ?

dev-to-uploads.s3.amazonaws.com/up...

Collapse
 
tavi profile image
Octavian Nita

Awesome! Is there any option to display a map with a 3D-ish/extruded like border?

Collapse
 
lucafaggianelli profile image
Luca Faggianelli

Thanks! It's a nice idea, you can play with SVG filters to add a drop shadow or even better you can create an extrusion effect with <feConvolveMatrix> filter. SVG filters is a tricky topic, here a nice article: smashingmagazine.com/2015/05/why-t...
And here a plugin for svg.js to handle filters github.com/svgdotjs/svg.filter.js

Collapse
 
tavi profile image
Octavian Nita

Thanks!

Collapse
 
maqabljh profile image
Jalal

I enjoyed reading this article. Thank you!

I created an interactive map for office locations to make it easier for clients to reach out to the nearest office. I use HTML file, CSS file, and JS file together for this map. Everything works fine except when your point out a location on the map, information about the nearest office should popup on the right side of the screen. This information includes a hyperlink to the office's website. The problem is that the hyperlink looks fine (blue and underlined) but it is not clickable. I mean the link does not work.
Can I share the code with you and you help me figure out the problem?

Collapse
 
abhijeetbhushan profile image
abhijeetbhushan

Hello Everyone,
This is the perfect example which I was looking for, thank you.

However, I am wondering that how I can add +, - and reset controls with this?
I tried to search many panzoom js but nothing worked.

Can you please help me?

Thank you

Collapse
 
abhijeetbhushan profile image
abhijeetbhushan

can anyone suggest something here?
It is very important at the moment.

Collapse
 
abhijeetbhushan profile image
abhijeetbhushan

How can I implement max and min zoom of the map using the JS?