block by curran 752b97cef3f880a813ab

World City Explorer

Full Screen

This program allows you to explore the world’s cities.

Each circle represents a city. Each filled in pixel of a circle represents 50,000 people. When city circles overlap, they appear brighter, so brightness can be interpreted as population density.

The data comes from Geonames and shows only cities with population >100,000.

Draws from:

Enjoy exploring!

–Curran, April 2015

index.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>D3 Example</title>
    <script src="//cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script>
    <script src="//cdnjs.cloudflare.com/ajax/libs/d3-tip/0.6.3/d3-tip.min.js"></script>
    <link href='//fonts.googleapis.com/css?family=Raleway' rel='stylesheet' type='text/css'>
    <style>

      body {
        background: black;
      }

      circle {
        fill: rgba(255, 255, 255, 0.2);
      }

      circle:hover { 
        stroke: white;
        stroke-width: 0.5px;
      }

      .d3-tip {
        font-family: 'Raleway', sans-serif;
        font-size: 1.5em;
        line-height: 1;
        padding: 7px;
        background: black;
        color: lightgray;
        border-radius: 20px;
      }
    </style>
  </head>
  <body>
    <script>

      var outerWidth = 960;
      var outerHeight = 500;
      var margin = { left: -100, top: 0, right: -100, bottom: 0 };

      var xColumn = "longitude";
      var yColumn = "latitude";
      var rColumn = "population";
      var peoplePerPixel = 50000;

      var innerWidth  = outerWidth  - margin.left - margin.right;
      var innerHeight = outerHeight - margin.top  - margin.bottom;

      var svg = d3.select("body").append("svg")
        .attr("width",  outerWidth)
        .attr("height", outerHeight);

      var zoom = d3.behavior.zoom()
        .scaleExtent([1, 20])
        .on("zoom", zoomed);

      var g = svg.append("g")
        .attr("transform", "translate(" + margin.left + "," + margin.top + ")")
        .call(zoom);

      var rect = g.append("rect")
        .attr("width", outerWidth)
        .attr("height", outerHeight)
        .style("fill", "none")
        .style("pointer-events", "all");

      var container = g.append("g");

      function zoomed(){
        container.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")");
      }

      var populationFormat = d3.format(",");

      var tip = d3.tip()
        .attr("class", "d3-tip")
        .offset([-10, 0])
        .html(function(d) {
          return d.name + ": " + populationFormat(d.population);
        });

      g.call(tip);

      var xScale = d3.scale.linear().range([0, innerWidth]);
      var yScale = d3.scale.linear().range([innerHeight, 0]);
      var rScale = d3.scale.sqrt();

      function render(data){

        xScale.domain( d3.extent(data, function (d){ return d[xColumn]; }));
        yScale.domain( d3.extent(data, function (d){ return d[yColumn]; }));
        rScale.domain([0, d3.max(data, function (d){ return d[rColumn]; })]);

        // Compute the size of the biggest circle as a function of peoplePerPixel.
        var peopleMax = rScale.domain()[1];
        var rMin = 0;
        var rMax = Math.sqrt(peopleMax / (peoplePerPixel * Math.PI));
        rScale.range([rMin, rMax]);

        var circles = container.selectAll("circle").data(data);
        circles.enter().append("circle");
        circles
          .attr("cx", function (d){ return xScale(d[xColumn]); })
          .attr("cy", function (d){ return yScale(d[yColumn]); })
          .attr("r",  function (d){ return rScale(d[rColumn]); })
          .on("mouseover", tip.show)
          .on("mouseout", tip.hide);
        circles.exit().remove();
      }

      function type(d){
        d.latitude = +d.latitude;
        d.longitude = +d.longitude;
        d.population = +d.population;
        return d;
      }

      d3.csv("geonames_cities100000.csv", type, render);

    </script>
  </body>
</html>