Boiler

Mount Doom dinner Gollum dolor i Tolkien Numenoreans Minas Tirith where there’s life there’s hope, and need of vittles justo cras Huorns Rohan iaculis vitae. Mount Doom Tom Bombadil Eregion Elrond a sodales.

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="utf-8" />
	<title>d3: Setup</title>
	<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
	<script src="http://d3js.org/topojson.v1.min.js"></script>
	<style>
		/* CSS Styles */
	</style>
	<!--[if IE]>
		<script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>
	<![endif]-->
</head>
<body>
	<div id="map"></div>
	<script>
		//d3 code
	</script>
</body>
</html>

TopoJSON Basemap

Mount Doom dinner Gollum dolor i Tolkien Numenoreans Minas Tirith where there’s life there’s hope, and need of vittles justo cras Huorns Rohan iaculis vitae. Mount Doom Tom Bombadil Eregion Elrond a sodales.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8" />
  <title>d3: Topojson Basemap</title>
  <script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
  <script src="http://d3js.org/topojson.v1.min.js"></script>
  <style>
  body { margin:0; padding:0; }
  #map {
    display:block;
    width:900px;
    height:500px;
  }
  .county {
    fill:#c0c0c0;
    stroke:white;
    stroke-width:1px;
  }
  </style>
</head>

<body>
  <div id="map"></div>

  <script>
  var width = 900, 
    height = 480;  

  projection = d3.geo.albersUsa() 
    .scale(1000)
    .translate([width / 2, height / 2])
    .precision(.1);

  path = d3.geo.path()  
    .projection(projection);  

  svg = d3.select("#map").append("svg")   
    .attr("width", width)
    .attr("height", height);

  d3.json("data/admin1_poly_topo.json", function(error,state) {
    svg.selectAll(".county")   
      .data(topojson.feature(state, state.objects.admin1_poly).features)  
      .enter().append("path") 
      .attr("class", "county") 
      .attr("d", path);
  });
  </script>
</body>
</html>

GeoJSON Basemap

Make a basemap with a geojson for fun!

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8" />
  <title>d3: Geojson Basemap</title>
  <script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
  <script src="http://d3js.org/topojson.v1.min.js"></script>
  <style>
    #map {
      display:block;
      width:900px;
      height:500px;
    }
    .stroke {
      fill:none;
      stroke:#666;
      stroke-width:2px;
    }
    .graticule {
      fill:none;
      stroke:#c0c0c0;
      stroke-width:1px;
      stroke-opacity:0.5;
    }
    .state {
      fill:#c0c0c0;
      stroke:white;
      stroke-width:1px;
    }
  </style>
  <!--[if IE]>
    <script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>
  <![endif]-->
</head>


<body>
  <a href="index.html">List</a>
  <div id="map"></div>
  
  <script>
  var width = 900, 
    height = 480;  

  projection = d3.geo.albers() 
    .scale(1000)
    .translate([width / 2, height / 2])
    .precision(.1);

  path = d3.geo.path()  
    .projection(projection);  

  svg = d3.select("#map").append("svg")   
    .attr("width", width)
    .attr("height", height);

  d3.json("data/admin1_poly_topo.json", function(error,state) {
    svg.selectAll(".state")   
      .data(topojson.feature(state, state.objects.admin1_poly).features)  
      .enter().append("path") 
      .attr("class", "state") 
      .attr("d", path);
  });
  </script>
</body>
</html>

Graticule

Add a graticule to the map svg space.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8" />
  <title>d3: Topojson Basemap</title>
  <script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
  <script src="http://d3js.org/topojson.v1.min.js"></script>
  <style>
  #map {
    display:block;
    width:900px;
    height:500px;
  }
  .graticule {
    fill:none;
    stroke:steelblue;
    stroke-width:1px;
    stroke-opacity:0.5;
  }
  .state {
    fill:#c0c0c0;
    stroke:white;
    stroke-width:1px;
  }
  </style>
  <!--[if IE]>
    <script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>
  <![endif]-->
</head>


<body>
  <a href="index.html">List</a>
  <div id="map"></div>

  <script>
  var width = 900, 
    height = 480;  

  projection = d3.geo.albers() 
    .scale(1000)
    .translate([width / 2, height / 2])
    .precision(.1);

  path = d3.geo.path()  
    .projection(projection);  

  graticule = d3.geo.graticule(); 

  svg = d3.select("#map").append("svg")   
    .attr("width", width)
    .attr("height", height);

  svg.append("path")    
    .datum(graticule)
    .attr("class", "graticule")
    .attr("d", path);

  d3.json("data/admin1_poly_topo.json", function(error,state) {
    svg.selectAll(".state")   
      .data(topojson.feature(state, state.objects.admin1_poly).features)  
      .enter().append("path") 
      .attr("class", "state") 
      .attr("d", path);
  });
  </script>
</body>
</html>

Queue.js

Use queue.js to load data before running d3 functions.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8" />
  <title>d3: Queue</title>
  <script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
  <script src="http://d3js.org/topojson.v1.min.js"></script>
  <script src="http://d3js.org/queue.v1.min.js"></script>
  <style>
    #map {
      display:block;
      width:900px;
      height:500px;
    }
    .county {
      fill:#c0c0c0;
      stroke:white;
      stroke-width:1px;
    }
  </style>
  <!--[if IE]>
    <script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>
  <![endif]-->
</head>


<body>
  <a href="index.html">List</a>
  <div id="map"></div>
  
  <script>
  var width = 900, 
    height = 480;  

  projection = d3.geo.albersUsa() 
    .scale(1000)
    .translate([width / 2, height / 2])
    .precision(.1);

  path = d3.geo.path()  
    .projection(projection);  

  svg = d3.select("#map").append("svg")   
    .attr("width", width)
    .attr("height", height);

  queue()   
    .defer(d3.json, "data/admin1_poly_topo.json")
    //load more data here 
    .await(drawMap);   

  function drawMap(error,state) {
    svg.selectAll(".county")   
      .data(topojson.feature(state, state.objects.admin1_poly).features)  
      .enter().append("path") 
      .attr("class", "county") 
      .attr("d", path);
  }

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

Data Points

Adding point data

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8" />
  <title>d3: Point Data</title>
  <script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
  <script src="http://d3js.org/topojson.v1.min.js"></script>
  <script src="http://d3js.org/queue.v1.min.js"></script>
  <style>
  #map {
    display:block;
    width:900px;
    height:500px;
  }
  .states {
    fill: #e5e5e5;
    stroke: #fff;
    stroke-width:1px;
  }
  .cities {
    fill: red;
    opacity:0.7;
  }
  </style>
  <!--[if IE]>
    <script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>
  <![endif]-->
</head>


<body>
  <a href="index.html">List</a>
  <div id="map"></div>
  
  <script>
  var width = 960,
    height = 500;
   
  var svg = d3.select('#map').append('svg')
      .attr('width', width)
      .attr('height', height);
   
  var projection = d3.geo.albersUsa()
    .scale(1000)
    .translate([width / 2, height / 2]);
   
  var path = d3.geo.path()
    .projection(projection);
    
  queue()
    .defer(d3.json, 'data/admin1_poly_topo.json')
    .defer(d3.json, 'data/usa_cities.json')
    .await(makeMyMap);

  function makeMyMap(error, states, cities) {
    svg.append('path')
      .datum(topojson.feature(states, states.objects.admin1_poly))
        .attr('d', path)
        .attr('class', 'states');
    svg.selectAll('.cities')
      .data(cities.features)
      .enter()
      .append('path')
      .attr('d', path.pointRadius(5))
      .attr('class', 'cities');
  }
  </script>
</body>
</html>

Proportional Symbols

Add a graticule to the map svg space.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8" />
  <title>d3: Point Data</title>
  <script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
  <script src="http://d3js.org/topojson.v1.min.js"></script>
  <script src="http://d3js.org/queue.v1.min.js"></script>
  <style>
  #map {
    display:block;
    width:900px;
    height:500px;
  }
  .states {
    fill: #e5e5e5;
    stroke: #fff;
    stroke-width:1px;
  }
  .cities {
    fill:red;
    fill-opacity:0.5;
    stroke:#fff;
    stroke-width:2px;
  }
  </style>
  <!--[if IE]>
    <script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>
  <![endif]-->
</head>


<body>
  <a href="index.html">List</a>
  <div id="map"></div>
  
  <script>
  var width = 960,
    height = 500;
   
  var svg = d3.select('#map').append('svg')
    .attr('width', width)
    .attr('height', height);
   
  var projection = d3.geo.albers()
    .scale(1000)
    .translate([width / 2, height / 2]);
   
  var path = d3.geo.path()
    .projection(projection);
    
  queue()
    .defer(d3.json, 'data/admin1_poly_topo.json')
    .defer(d3.json, 'data/usa_cities.json')
    .await(makeMyMap);
   
  function makeMyMap(error, states, cities) {
    
    var length = cities.features.length;
    var pops = [];
    for (var mug=0; mug<length; mug++) {
      var pop = cities.features[mug].properties.POPULATION;
      pops.push(Number(pop));
    }
    var min = Math.min.apply(Math, pops);
    var max = Math.max.apply(Math, pops);
    
    var radius = d3.scale.sqrt()
      .domain([min, max])
      .range([10, 30]);
    
    svg.append('path')
      .datum(topojson.feature(states, states.objects.admin1_poly))
      .attr('d', path)
      .attr('class', 'states');
      
    svg.selectAll('.cities')
      .data(cities.features)
      .enter().append('path')
      .attr('class', 'cities')
      .attr('d', path.pointRadius(function(d) { return radius(d.properties.POPULATION); }));
      
  }
  </script>
</body>
</html>

Point Labels

Adding labels to point data.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8" />
  <title>d3: Point Data</title>
  <script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
  <script src="http://d3js.org/topojson.v1.min.js"></script>
  <script src="http://d3js.org/queue.v1.min.js"></script>
  <style>
  #map {
    display:block;
    width:900px;
    height:500px;
  }
  .states {
    fill: #e5e5e5;
    stroke: #fff;
    stroke-width:1px;
  }
  .cities {
    fill: red;
    opacity:0.7;
  }
  .labels {
    fill: #444;
    font-family:arial;
    font-size:0.7em;
  }
  </style>
  <!--[if IE]>
    <script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>
  <![endif]-->
</head>


<body>
  <a href="index.html">List</a>
  <div id="map"></div>
  
  <script>
  var width = 960,
    height = 500;
   
  var svg = d3.select('#map').append('svg')
      .attr('width', width)
      .attr('height', height);
   
  var projection = d3.geo.albersUsa()
    .scale(1000)
    .translate([width / 2, height / 2]);
   
  var path = d3.geo.path()
    .projection(projection);
    
  queue()
    .defer(d3.json, 'data/admin1_poly_topo.json')
    .defer(d3.json, 'data/usa_cities.json')
    .await(makeMyMap);

  function makeMyMap(error, states, cities) {
    svg.append('path')
      .datum(topojson.feature(states, states.objects.admin1_poly))
      .attr('d', path)
      .attr('class', 'states');
    svg.selectAll('.cities')
      .data(cities.features).enter().append('path')
      .attr('d', path.pointRadius(4))
      .attr('class', 'cities');
    svg.selectAll('.labels')
      .data(cities.features).enter().append('text')
      .attr('transform', function(d) {
        return 'translate(' + projection(d.geometry.coordinates) + ')';
      })
      .attr('dy', function(d){ // vertical offset
        var city = d.properties.NAME
        if (city == 'Washington') {
          return 8;
        }
        else {
          return -3;
        }
      }) 
      .attr('dx', 3) // horizontal offset
      .text(function(d) {
        return d.properties.NAME;
      })
      .attr('class', 'labels');
  }

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

Related infographic

Updating anothor object via the map and its data.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8" />
  <title>d3: Topojson Basemap</title>
  <script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
  <script src="http://d3js.org/topojson.v1.min.js"></script>
  <style>
  body {
    margin:0; padding:0;
  }
  #map {
    display:block;
    width:900px;
    height:500px;
  }
  #name {
    position:absolute;
    top:30px;
    left:20px;
    font-family:arial;
    font-size:3em;
  }
  .state {
    fill:#c0c0c0;
    stroke:white;
    stroke-width:1px;
  }
  .state:hover {
    fill:#333;
  }
  </style>
  <!--[if IE]>
    <script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>
  <![endif]-->
</head>


<body>
  <div id="map">
    <div id="name"></div>
  </div>

  <script>
  var width = 900, 
    height = 480;  

  projection = d3.geo.albersUsa() 
    .scale(1000)
    .translate([width / 2, height / 2])
    .precision(.1);

  path = d3.geo.path()  
    .projection(projection);  

  svg = d3.select("#map").append("svg")   
    .attr("width", width)
    .attr("height", height);

  d3.json("data/us.json", function(error,state) {
    svg.selectAll(".state")   
      .data(topojson.feature(state, state.objects.usStates).features)  
      .enter().append("path") 
      .attr("class", "state") 
      .attr("d", path)
      .on('mouseover', function(d) {
        var abbreviation = d.properties.STATE_ABBR;
        return document.getElementById('name').innerHTML=abbreviation;
      })
  });
  </script>
</body>
</html>

Topojson Interaction

Interacting with topojson metadata

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8" />
  <title>d3: Topojson Basemap</title>
  <script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
  <script src="http://d3js.org/topojson.v1.min.js"></script>
  <style>
  body {
    margin:0; padding:0;
  }
  #map {
    display:block;
    width:900px;
    height:500px;
  }
  #name {
    position:absolute;
    top:30px;
    left:20px;
    font-family:arial;
    font-size:3em;
  }
  .state {
    fill:#c0c0c0;
    stroke:white;
    stroke-width:1px;
  }
  .state:hover {
    fill:#333;
  }
  </style>
  <!--[if IE]>
    <script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>
  <![endif]-->
</head>


<body>
  <div id="map">
    <div id="name"></div>
  </div>

  <script>
  var width = 900, 
    height = 480;  

  projection = d3.geo.albersUsa() 
    .scale(1000)
    .translate([width / 2, height / 2])
    .precision(.1);

  path = d3.geo.path()  
    .projection(projection);  

  svg = d3.select("#map").append("svg")   
    .attr("width", width)
    .attr("height", height);

  d3.json("data/us.json", function(error,state) {
    svg.selectAll(".state")   
      .data(topojson.feature(state, state.objects.usStates).features)  
      .enter().append("path") 
      .attr("class", "state") 
      .attr("d", path)
      .on('mouseover', function(d) {
        var abbreviation = d.properties.STATE_ABBR;
        return document.getElementById('name').innerHTML=abbreviation;
      })
  });
  </script>
</body>
</html>

Reprojection (Destructive)

This example allows the user to choose between two projections. Each time the projeciton is chosen the svg space is removed and redrawn, therefore doesn’t allow for a smooth transition. For a smooth reprojection, one must interpolate between the two projections. Note: This is still pretty hacky

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8" />
  <title>d3: Reprojection (no transition)</title>
  <script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
  <script src="http://d3js.org/topojson.v1.min.js"></script>
  <style>
  body { margin:0; padding:0; }
  #map {
    display:block;
    width:900px;
    height:500px;
  }
  .county {
    fill:#c0c0c0;
    stroke:white;
    stroke-width:1px;
  }
  #projections {
    list-style-type: none;
  }
  #projections li {
    display:inline-block;
    margin-right:10px;
    border:1px solid #333;
    padding:10px;
  }
  #projections li:hover {
    cursor:pointer;
  }
  </style>
</head>

<body>
  <ul id="projections">
    <li id="conicEqui">Conic Equidistant</li>
    <li id="azimuthal">Azimuthal Equidistant</li>
  </ul>
  <div id="map"></div>

  <script>

  var width = 900, 
    height = 480;  

  conicEqui = d3.geo.conicEquidistant() 
    .scale(200)
    .translate([width / 2, height / 2])
    .precision(.1);

  azimuthal = d3.geo.azimuthalEquidistant()
    .scale(200)
    .translate([width / 2, height / 2])
    .precision(.1);

  projection = getActiveProjection();

  function drawMap(projection) {
    console.log('reprojected!');
    path = d3.geo.path()  
      .projection(projection);  

    svg = d3.select("#map").append("svg")   
      .attr("width", width)
      .attr("height", height);

    d3.json("data/world_topo.json", function(error,countries) {
      svg.selectAll(".county")   
        .data(topojson.feature(countries, countries.objects.world).features)  
        .enter().append("path") 
        .attr("class", "county") 
        .attr("d", path);
    });
  }
  
  function init() {
    drawMap(conicEqui);
    var projections = document.getElementById('projections').childNodes;
    for (i = 0, len = projections.length; i < len; i++){
      projections[i].onclick=function() {
        var id = this.id;
        if(id=='azimuthal') {
          proj = azimuthal;
        } else {
          proj = conicEqui;
        }
        d3.select('svg').remove();
        drawMap(proj);
      }
    }

  }
  window.onload = init();

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