block by curran 1dd7ab046a4ed32380b21e81a38447aa

World Countries Hierarchy

Full Screen

A tree visualization of the hierarchy of countries in the World.

Data from the United Nations Place Hierarchy.

Inspired by:

Built with blockbuilder.org

web counter

index.html

<!DOCTYPE html>
<head>
  <meta charset="utf-8">
  <script src="//d3js.org/d3.v4.min.js"></script>
  <link href="//fonts.googleapis.com/css?family=Open+Sans" rel="stylesheet" type="text/css">
  
  <style>
    .link {
      fill: none;
      stroke: #4fb9b5;
    }
    .glow {

      /* This trick adds a heavy white shadow around the text. */
      text-shadow:
       -1px -1px 3px white,
       -1px  1px 3px white,
        1px -1px 3px white,
        1px  1px 3px white;

    }
    text {
      font-family: "Open Sans", sans-serif;
      pointer-events: none;
    }
  </style>
</head>

<body>
  <script>
    var width = 960,
        height = 950,
        svg = d3.select("body").append("svg")
          .attr("width", width)
          .attr("height", height),
        g = svg.append("g"),
        cluster = d3.cluster()
          .size([2 * Math.PI, width / 2 - 150])
        fontSize = d3.scaleSqrt()
          .range([30, 7]);

    svg.append("rect")
      .attr("width", width)
      .attr("height", height)
      .style("fill", "none")
      .style("pointer-events", "all")
      .call(d3.zoom()
          .scaleExtent([1 / 2, 4])
          .on("zoom", zoomed));

    function zoomed() {
      g.attr("transform", d3.event.transform);
    }
    
    d3.json("countryHierarchy.json", function (data){
      var hierarchy = d3.hierarchy(data);
      cluster(hierarchy);
      var descendants = hierarchy.descendants();
      
      fontSize.domain(d3.extent(descendants, function (d){ return d.depth; }))
      
      var link = g.selectAll(".link")
          .data(descendants.slice(1))
        .enter().append("path")
          .attr("class", "link")
          .attr("d", function(d) {
            if(d.parent === descendants[0]){
              return "M" + project(d.x, d.y)
                + " " + project(d.parent.x, d.parent.y);
            } else {
              return "M" + project(d.x, d.y)
                + "C" + project(d.x, (d.y + d.parent.y) / 2)
                + " " + project(d.parent.x, (d.y + d.parent.y) / 2)
                + " " + project(d.parent.x, d.parent.y);
            }
          });
      
      var node = g.selectAll(".node")
          .data(descendants)
        .enter().append("g")
          .attr("transform", function(d) {
            return "translate(" + project(d.x, d.y) + ")";
          });

      node.append("text")
        .text(function (d){
          return d.data.data.id;
        })
        .attr("font-size", function (d){
          return fontSize(d.depth) + "pt";
        })
        .attr("transform", function(d) {
          var theta = -d.x / Math.PI * 180 + 90;
          if(d.x > Math.PI){
            theta += 180;
          }
          if(d.depth !== 3 && Math.abs(theta) < 30){
            theta = 0;
          }
          if(d.depth > 1){
            return "rotate(" + theta + ")";
          } else {
            return "";
          }
        })
        .attr("text-anchor", function (d){
          if(d.depth === 3){
            return (d.x > Math.PI) ? "end" : "start";
          } else {
            return "middle";
          }
        })
        .attr("dx", function (d){
          if(d.depth === 3){
            return (d.x > Math.PI) ? "-2px" : "2px";
          } else {
            return "0px";
          }
        })
        .classed("glow", function (d){
          return d.depth !== 3;
        })
        .attr("alignment-baseline", "central");
    });
    
    function project(theta, r){
      return [
        width / 2 + r * Math.sin(theta),
        height / 2 + r * Math.cos(theta) + 4
      ]
    }
  </script>
</body>