Skip to content

Making a map of germany with topojson

25. February 2013

Original Source:

Download data:


Convert data:

  • get german states as geojson
ogr2ogr \
  -f GeoJSON \
  -where "sr_adm0_a3 IN ('DEU')" \
  subunits.json \
  • get populated places a geojson…I just want to have the capital cities of each german state
ogr2ogr \
  -f GeoJSON \
  -where "adm0_a3 = 'DEU' AND FEATURECLA = 'Admin-1 capital'" \
  places.json \
  • combine both layers to one topojson
topojson \
  --id-property su_a3 \
  -p NAME=name \
  -p name \
  -o de.json \
  subunits.json \

Final visualisation of the newly created topojson

<!DOCTYPE html>
<meta charset="utf-8">
.subunit.Nordrhein-Westfalen{ fill: #aba; }
.subunit.Baden-Württemberg{ fill: #bab; }
.subunit.Hessen{ fill: #bcb; }
.subunit.Niedersachsen{ fill: #cbc; }
.subunit.Thüringen{ fill: #cdc; }
.subunit.Hamburg{ fill: #dcd; }
.subunit.Schleswig-Holstein{ fill: #ded; }
.subunit.Rheinland-Pfalz{ fill: #ede; }
.subunit.Saarland{ fill: #efe; }
.subunit.Sachsen-Anhalt{ fill: #fef; }
.subunit.Brandenburg{ fill: #aaa; }
.subunit.Mecklenburg-Vorpommern{ fill: #bbb; }
.subunit.Bayern { fill: #ccc; }
.subunit.Sachsen { fill: #ddd; }
.subunit.Bremen { fill: #eee; }
.subunit.Berlin { fill: #fff; }

.subunit-boundary {
  fill: none;
  stroke: #777;
  stroke-dasharray: 2,2;
  stroke-linejoin: round;
.place-label {
  fill: #444;
text {
  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
  font-size: 20px;
  pointer-events: none;
.subunit-label {
  fill: #777;
  fill-opacity: .5;
  font-size: 30px;
  font-weight: 200;
  text-anchor: middle;
<script src=""></script>
<script src=""></script>

var width = 1050,
    height = 1400;

var path = d3.geo.path();

var svg ="body").append("svg")
    .attr("width", width)
    .attr("height", height);

d3.json("data/de.json", showData);

function showData(error, de) {
    var subunits = topojson.object(de, de.objects.subunits);

    var projection = d3.geo.mercator()
        .center([10.5, 51.35])
        .translate([width / 2, height / 2]);

    var path = d3.geo.path()

        .attr("d", path)

        .data(topojson.object(de, de.objects.subunits).geometries)
        .attr("class", function(d) { return "subunit " +; })
        .attr("d", path)
        .on("click", click);

    function click(a){

        .datum(topojson.mesh(de, de.objects.subunits, function(a,b) { if (a!==b || === "Berlin"|| === "Bremen"){var ret = a;}return ret;}))
        .attr("d", path)
        .attr("class", "subunit-boundary");

        .datum(topojson.object(de, de.objects.places))
        .attr("d", path)
        .attr("class", "place");

        .data(topojson.object(de, de.objects.places).geometries)
        .attr("class", "place-label")
        .attr("transform", function(d) { return "translate(" + projection(d.coordinates) + ")"; })
        .attr("dy", ".35em")
        .text(function(d) { if (!=="Berlin"&&!=="Bremen"){return;} })
        .attr("x", function(d) { return d.coordinates[0] > -1 ? 6 : -6; })
        .style("text-anchor", function(d) { return d.coordinates[0] > -1 ? "start" : "end"; });

        .data(topojson.object(de, de.objects.subunits).geometries)
        .attr("class", function(d) { return "subunit-label " +; })
        .attr("transform", function(d) { return "translate(" + path.centroid(d) + ")"; })
        .attr("dy", function(d){ 
            {return ".9em"}
        else if("Brandenburg"||"Hamburg")
            {return "1.5em"}
        else if("Berlin"||"Bremen")
            {return "-1em"}else{return ".35em"}})
        .text(function(d) { return; });


Have a look at the final result!

  1. Thanks for this excellent example. I too was looking at to make a map of Germany with places & stats in topojson. Too bad the result is no longer online – it would save me some time 🙂

  2. Excellent! Im looking to create the exact same topoJson File – even following the same example 🙂

    Any Chance to get the result Link back up? Id save me some time…

    • Ups…it is still online, but the adress changed.
      I’ve fixed that and now you can access the result…

  3. draschke permalink

    Thanks, great work! Is there also a solution for umlauts (umlaute)?
    For example, Thüringen will be displayed wrong. How can I fix it?
    Best wishes

    • I did not care for that so far, as I’ve got no clue about how to avoid ‘umlaut-problems’ in JavaScript.
      Problems with umlaute appear heterogenious and depend on your system (and maybe the browser?).
      So…in my Chromium (Ubuntu 12.04), does the map look good, but maybe not on your system (browser)!?!

      I’d be grateful for a solution, when you found one 😉


  4. padmalcom permalink

    Thanks for the fantastic example! 🙂

    • You’re welcome … but It’s just a re-implementation of Mikes good example. So props should be dedicated to him 😉

  5. Achim Grunde permalink

    Germany is not only a state but a European region distributed onto several states, see e.g.

  6. Miten Suresh Mehta permalink

    ogr2ogr -f GeoJSON -where “adm0_a3 = ‘IND’ AND FEATURECLA = ‘Admin-1 capital'” states.json places/ne_10m_populated_places.shp

    I had to use above for Inida. Note you use sr_admin0_a3. The topojson v0 was giving some error so I tried v1 and then it gives different error like length related error. I changed all object calls to feature calls.

    here is code:

Trackbacks & Pingbacks

  1. D3 Geodata Basics – A Map Overlay can have many Faces :

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: