MIG Location Icon Generator
Greetings to the habrosociety. I want to share with you one of my last mini-projects - the MIG geodata icon generator . Using it, you can generate vector ( SVG ) and bitmap (PNG) icons with the specified parameters (color, size, stroke, etc.).

All this works directly in the browser and is distributed under the MIT license . Under the cut you can learn how to use it and how it works.
By default, MIG uses a 1: 110m world map based on natural earth data geodata to generate icons . It contains data for ( 174 + 3 ) countries of the world (the rest are degenerating at this scale), plus three countries - these are Northern Cyprus, Kosovo and Somaliland. If this is enough for you, simply set the parameters of the icons you need directly in the code, or use the GUI on the MIG demo page . If you need to filter out part of the countries, this can be easily done by setting conditions for the available properties (
The demo looks very ascetic, because in order to achieve interesting results, you still have to change the code. So feel free to fork MIG and change it for yourself. Yes, the demo uses new inputs (HTML5), they are not yet supported everywhere: caniuse , but there is a fallback, so it should work anyway.
So what to do if the default option does not suit you. The first step is to determine the new geodata - this can be a world map, a map of a country with administrative borders, a city map with division into districts, or any other map. Once you have decided on the geodata, you need to convert it to TopoJSON . This can be done using the Command-line TopoJSON , pre-installingTopoJSON implementation for Node.js. At the conversion stage, you need to remove all unnecessary properties, you can also add names if you are not going to use an external file for this. When the new TopoJSON file is ready, update the paths and names:
Change the name
That's it, now you can generate icons!
For those cases when it is necessary to use a non-standard Mercator projection, you can easily add one of the available projections or even create your own. In this case, you can apply a separate projection for at least each icon. By the way, in the demo example, separate projections are used for Russia and the USA.
In general, there is a vast field for experimentation.
The generator is written using the D3.js library , the code can be viewed on GitHub: Map Icons Generator . So what is going on here. First, the geodata and the corresponding names are loaded (for the case when they are not sewn into the TopoJSON file). Then, for each object, an SVG element of a given size is created and the corresponding map region is drawn in it in a given projection, while the centering and scale are calculated based on
Further, based on the created vector icons, raster ones are created. It happens as follows: in a cycle we go over all SVGelements, we create canvas elements and draw our icon there with the help
I think to add filtering by country and improve the design of the demo page. Change the saving mechanism - now the icons are saved either individually, when you click on a country, or immediately the entire region (continent), while a modal window is created for each icon, I plan to replace this with the ability to download icons in one archive. I also plan to add the possibility of simplifying the geometry and accuracy for geodata, so that you can adjust them according to the size of the icons. Now it can be done at the stage of creating TopoJSON (
If you have any questions, something is unclear, found a bug or something else - write.
That's all, good luck!

All this works directly in the browser and is distributed under the MIT license . Under the cut you can learn how to use it and how it works.
How to use
By default, MIG uses a 1: 110m world map based on natural earth data geodata to generate icons . It contains data for ( 174 + 3 ) countries of the world (the rest are degenerating at this scale), plus three countries - these are Northern Cyprus, Kosovo and Somaliland. If this is enough for you, simply set the parameters of the icons you need directly in the code, or use the GUI on the MIG demo page . If you need to filter out part of the countries, this can be easily done by setting conditions for the available properties (
properties
). For example, filtering by ID looks like this:.data(topojson.feature(world, world.objects.countries).features
.filter(function(d) {return contryList.indexOf(d.id) > -1;}))
The demo looks very ascetic, because in order to achieve interesting results, you still have to change the code. So feel free to fork MIG and change it for yourself. Yes, the demo uses new inputs (HTML5), they are not yet supported everywhere: caniuse , but there is a fallback, so it should work anyway.
So what to do if the default option does not suit you. The first step is to determine the new geodata - this can be a world map, a map of a country with administrative borders, a city map with division into districts, or any other map. Once you have decided on the geodata, you need to convert it to TopoJSON . This can be done using the Command-line TopoJSON , pre-installingTopoJSON implementation for Node.js. At the conversion stage, you need to remove all unnecessary properties, you can also add names if you are not going to use an external file for this. When the new TopoJSON file is ready, update the paths and names:
.defer(d3.json, "data/TopoJSON_file.json")
.defer(d3.tsv, "data/external_file_for_names.tsv")
Change the name
feature
to match your new file:.data(topojson.feature(world, world.objects.YourNewFeatureName).features
That's it, now you can generate icons!
Additional features
For those cases when it is necessary to use a non-standard Mercator projection, you can easily add one of the available projections or even create your own. In this case, you can apply a separate projection for at least each icon. By the way, in the demo example, separate projections are used for Russia and the USA.
switch (d.id) {
//Russia
case "RUS": var projection = d3.geo.albers().rotate([-105, 0]).center([-10, 65]).parallels([52, 64]);
path = d3.geo.path().projection(projection);
break;
//USA
case "USA": var projection = d3.geo.albersUsa();
path = d3.geo.path().projection(projection);
break;
default: var projection = d3.geo.mercator();
path = d3.geo.path().projection(projection);
break;
}
In general, there is a vast field for experimentation.
What's under the hood
The generator is written using the D3.js library , the code can be viewed on GitHub: Map Icons Generator . So what is going on here. First, the geodata and the corresponding names are loaded (for the case when they are not sewn into the TopoJSON file). Then, for each object, an SVG element of a given size is created and the corresponding map region is drawn in it in a given projection, while the centering and scale are calculated based on
BoundingBox
. There are several nuances associated with this point, since the presentation of geodata depends on the projection, in some cases auto-centering and auto-scaling will give an unsightly result. For example, the countries through which the anti-meridian passes (including our long-suffering Russia) or countries with a large spread of territories (island) will look very small. This can be corrected by using a suitable projection, or by removing (filtering) part of the territories of the displayed region. Then move on to styling the icons. At this stage, you can use various SVG filters, gradients, patterns clipping
- in general, all the power of SVG . Further, based on the created vector icons, raster ones are created. It happens as follows: in a cycle we go over all SVGelements, we create canvas elements and draw our icon there with the help
context.drawImage()
, there is also a small nuance here, SVG should have everything in order with the xmlns
attribute, and it Blob
’s specified the correct MIME type, otherwise nothing will come of it. Now we fasten the save, start and enjoy the received icons.Further development
I think to add filtering by country and improve the design of the demo page. Change the saving mechanism - now the icons are saved either individually, when you click on a country, or immediately the entire region (continent), while a modal window is created for each icon, I plan to replace this with the ability to download icons in one archive. I also plan to add the possibility of simplifying the geometry and accuracy for geodata, so that you can adjust them according to the size of the icons. Now it can be done at the stage of creating TopoJSON (
simplification
and quantization
). If you have any questions, something is unclear, found a bug or something else - write.
That's all, good luck!