Create your own vector map for jQuery Mapael

Some maps are packaged with jquery mapael and some other are available on the mapael-maps repository (feel free to contribute to this repository !). In this tutorial, I will explain you how to create a new map for jQuery Mapael from an existing SVG file. Let’s create a United Kingdom map for mapael !

Summary

Tools used to create a map for Mapael

#First step : find a SVG map that will serve as a basis

The first step is to find an SVG map file. You can find many maps on SVG format with a Creative Commons license on the web. You can find this kind of resources on Natural Earth Data or Wikimedia Commons. A map is based on a specific projection such as mercator, Miller, Lambert or equirectangular projection. Here is a list of map projections.

If you want to plot cities by latitude and longitude on your map, you have to care about the projection that is used on the choosen map. Indeed, the algorithm to convert a latitude and a longitude to x and y coordinates depends on the map projection. The simpliest projection is the equirectangular one (see below fore more information). https://commons.wikimedia.org/wiki/Main_Page

Here is the map of of United kingdom with an equirectangular projection and under SVG format.

#Refine the map with Inkscape

Inkscape is a powerful Open Source tool to edit vector graphics. It will allows us to clean the map by removing unwanted SVG paths and groups, SVG transformations, and trimming the map. Thus, we will be able to extract only the wanted paths that compose the map.

Go to File > Inkscape Preferences > Transforms. Ensure that “Optimized“ is checked for the “Store transformation” option. It will force Inkscape to translate SVG transforms (such as translations, rotations, …) into coordinates within the paths.

All we want to retrieve from the SVG file are the paths of each county that will compose our map. We do not want lakes, rivers, small islands, neighbourhood countries. You can remove all these unwanted elements.

The paths may be grouped within SVG <g> elements. As transformations can be applied to SVG groups, we have to ungroup all groups from the SVG file. Ungroup all objects will make inkscape translate transforms into coordinates within the paths. In order to ungroup all groups, open the XML editor (edit > XML editor) and, for each <g> element found in the XML tree, click on Object > Ungroup.


Ungroup all groups through the XML editor


Cleaned map

Once your SVG file is cleaned from all unwanted elements and all groups are ungrouped, you can be in front of two cases :

First case : the SVG file contains paths that already represent correctly the different areas of the country. In such a case, you just have to select all the wanted areas (by holding CTRL + uppercase pressed) and copy them in a new Inkscape document.

Second case : The SVG file contains paths that do not match with the areas (for example, the file can contains paths just for the boundaries). In such a case, you can use the "Fill bounded areas" tool : . Set appropriate values for the “Threshold” option (you can set it to 0 if the concerned area has a single color) and the "grow/shrink" option. Ensure that you have zoomed your map enough before filling the areas. Indeed, the filling precision depends on the zoom level. You can now fill all the wanted areas. If you can't fill an area with only one click because of the zoom level, you can complete the filling by clicking on another area and holding CTRL + Uppercase pressed. When all the wanted areas are filled, you can select them (by holding CTRL + Uppercase pressed) and copy them in a new Inkscape document.


All the wanted areas are selected in order to copy them in a new document

The areas in the new document may not fit with the document dimensions. In this case, go to File > Document Properties > Resize page to content, and click on the “Resize page to drawing or selection”. Resize the document makes Inkscape group the areas in a <g> element and apply the transformation on this element. In order to translate this transformation into the paths coordinates, open the XML editor (edit > XML editor) and, for each <g> element found in the XML tree, click on Object > Ungroup.


Resized page to drawing

The last step is to associate more explicit IDs than “pathXXX” to each area. To achieve this, you can use the XML editor.


Associate more explicit IDs to the paths

Save this new SVG file, we are done with Inkscape but you may want to go further by reading the next part.

#Go a little further with Inkscape

I will not explain all the features for editing vector images provided by Inkscape because this is not a tutorial dedicated to the tool, but some of them are very usefull for refining the maps.

Simplify paths

If your final javascript map is too big, you can lighten the paths data with Inkscape by using the tool “Path > Simplify”. If your map is not enough lightened, you can also change the value of the round precision field in the tool “SVG To mapael” (see below).

Combine paths

Sometimes, a single area is divided into several distinct SVG paths. Inkscape allows you to gather these paths in one single path : select all paths to be combined (by holding Uppercase) and use the tool “Path > Combine”.

Break apart paths

In some other cases, you may want to break apart areas that are gathered in one single SVG path. This is the aim of the tool “Path > Break apart”.

#Build the basic JSON map file for Mapael

You have two ways for building the basic JSON map file for Mapael.

The tedious way : as SVG is just XML, you can open the file with any text editor. You just have to extract manually the wanted paths data (‘d’ attribute in elements) and paths ids (‘id attribute in elements) in order to build the JSON map for mapael. It should look to something like this :

(function($) {
                $.extend(true, $.fn.mapael, 
                    {
                        maps :{
                            yourMapName : {
                                width : 600,
                                height : 500,
                                getCoords : function (lat, lon) {
                                    // Convert latitude,longitude to x,y here
                                    return {'x' : lat, 'y' : lon};
                                }
                                elems : {
                                    // List of SVG paths for building the map
                                    "department-29" : "m 37.28,156.11 c -1.42,1.23 -3.84,1.18 (...)",
                                    "department-22" : "m 77.67,146.73 c -2.58,0.94 -4.37,2.6 -5.78,4.84 1.21 (...)",
                                    (...)
                                }
                            }
                        }
                    }
                );
            })(jQuery);
            

The easy way : Go to the "SVG to Mapael" tool and submit your brand new SVG file in order to get the JS file generated for Mapael. You can set a value for the round precision field in order to round all paths coordinates. It allows to lighten the size of the output. Usually, a round precision of 2 is enough in most of cases. Leave this input blank if you do not want to round the paths coordinates.

Save the output in a javascript and your map should now be ready to be loaded into jQuery Mapael !


The UK map displayed through jQuery mapael

#Fill the getCoords Function

If you want to go further with your map, you may want plot cities by latitude and longitude on it. We assume that the projection of your map is an equirectangular one.

With this projection, the algorithm to convert a latitude and a longitude to x and y coordinates is as simple as that :

You just have to found the proper values for xFactor, yFactor, xOffset and yoffset in order to be able to plot cities by latitude and longitude on your map.

To get the values of xFactor and xOffset, you just have to resolve an equation with two unknowns. Plot two points at the max left and the max right of your map with x and y coordinates. Go to Google Map in order to find the matching longitudes for these two points (Right click > More info about this place on Google map) .

You can now find the values for xFactor and xOffset by resolving this equation (this is the tedious way, there is a tool for that, see below ;-) ) :

Then, you have to do exactly the same thing to get the values of yFactor and yOffset with matching latitudes.

You can use the getCoords() generator tool that will resolve equations and generate the getCoords() method for you !

Use mapael for plotting points in order s to find min x, max x, min y and max y coordinates. Here is an example for the United Kingdom map where I plotted four points with x and y coordinates on the map :

(function($) {
            $(function(){
                $(".container1").mapael({
                    map : {
                        name : "united_kingdom",
                        zoom: {
                            enabled:true
                        },
                        defaultPlot : {
                            size:5,
                            attrs: {
                                fill:"red",
                                stroke:"white",
                                "stroke-width":2,
                                opacity:0.5
                            }
                        }
                    },
                    plots : {
                        p1 : {
                            x:647,
                            y:3
                        },
                        p2 : {
                            x:352,
                            y:1238
                        },
                        p3 : {
                            x:1,
                            y:995
                        },
                        p4 : {
                            x:818,
                            y:945
                        }
                    }
                });
            });
        

Then, you can use Google Maps in order to find the matching latitudes and longitudes and fill the form of the getCoords() generator.

With the getCoords() function added to your JS vector map, you can now plot cities by latitude and longitude, here is an example with London plotted on the UK map (latitude : 51.5085300, longitude : -0.1257400) :

Your map for mapael is now complete ! Take a look at the mapael documentation to see what you can do with it. Feel free to contribute to mapael-maps repository (https://github.com/neveldo/mapael-maps) by adding your new map !

#Editing existing maps

  • You want to bring some changes to an existing Mapael map through Inkscape ? You still can transform a Mapael map to an SVG file with the "Mapael to SVG" tool.
  • Another alternative is to copy existing SVG paths from the source file into an SVG editor, like SVG-edit.
    For example, if you want to add an additional country to a map, you first start by drawing a random line with the Pencil Tool. Then you open the SVG editor (the "<SVG>" button) and paste the SVG paths of the country you wish to add a neighbouring country to. This way you will have a reference to add the new country.
    Then you either draw the new country yourself, or use the SVG paths from a SVG file you found somewhere and use the same method to paste it in the SVG editor.
    Now you only have to copy the SVG paths from SVG-edit into the map source file with a new label and you're done.