block by emeeks 24083e6ac8d3c6e4009c

Ch. 7, Fig. 15 - D3.js in Action

Full Screen

This is the code for Chapter 7, Figure 15 from D3.js in Action showing how to create an isometric map using the d3.geo.satellite() projection.

index.html

<html>
<head>
  <title>D3 in Action Chapter 7 - Example 6</title>
  <meta charset="utf-8" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script>
<script src="https://d3js.org/d3.geo.projection.v0.min.js" type="text/JavaScript"></script>
<script src="https://d3js.org/queue.v1.min.js" type="text/JavaScript"></script>
<script src="https://d3js.org/colorbrewer.v1.min.js" type="text/JavaScript"></script>
</head>
<style>
  svg {
    height: 500px;
    width: 500px;
    border: 1px solid gray;
  }
  
  .countries {
    fill: red;
    fill-opacity: .5;
    stroke: black;
    stroke-width: 1px;
  }

</style>
<body>

<div id="viz">
  <svg>
  </svg>
</div>
<div id="controls" />
</body>
  <footer>
    
<script>
    queue()
    .defer(d3.json, "world.geojson")
    .defer(d3.csv, "cities.csv")
    .await(function(error, file1, file2) { createMap(file1, file2); });
    
  function createMap(countries, cities) {
    expData = countries;
    width = 500;
    height = 500;
    projection = d3.geo.satellite()
    .scale(1330)
    .translate([250,250])
    .rotate([-30.24, -31, -56])
    .tilt(30)
    .distance(1.199)
    .clipAngle(45)

    geoPath = d3.geo.path().projection(projection);
    
    var mapZoom = d3.behavior.zoom().translate(projection.translate()).scale(projection.scale()).on("zoom", zoomed);
    d3.select("svg").call(mapZoom);

    function zoomed() {
      var currentRotate = projection.rotate()[0];
      projection.translate(mapZoom.translate()).scale(mapZoom.scale());
      d3.selectAll("path.graticule").attr("d", geoPath);
      d3.selectAll("path.countries").attr("d", geoPath);
      
      d3.selectAll("circle.cities")
      .attr("cx", function(d) {return projection([d.y,d.x])[0]})
      .attr("cy", function(d) {return projection([d.y,d.x])[1]})
      .style("display", function(d) {return parseInt(d.y) + currentRotate < 45 && parseInt(d.y) + currentRotate > -45 ? "block" : "none"})

    }

    featureSize = d3.extent(countries.features, function(d) {return geoPath.area(d)});
    countryColor = d3.scale.quantize().domain(featureSize).range(colorbrewer.Reds[7]);

    var graticule = d3.geo.graticule();
    
    d3.select("svg").append("path")
    .datum(graticule)
    .attr("class", "graticule line")
    .attr("d", geoPath)
    .style("fill", "none")
    .style("stroke", "lightgray")
    .style("stroke-width", "1px");
    
    d3.select("svg").selectAll("path.countries").data(countries.features)
    .enter()
    .append("path")
    .attr("d", geoPath)
    .attr("class", "countries")
    .style("fill", function(d) {return countryColor(geoPath.area(d))})
    .style("stroke-width", 1)
    .style("stroke", "black")
    .style("opacity", .5)

    d3.select("svg").selectAll("circle").data(cities)
    .enter()
    .append("circle")
    .attr("class", "cities")
    .style("fill", "black")
    .style("stroke", "white")
    .style("stroke-width", 1)
    .attr("r", 3)
    .attr("cx", function(d) {return projection([d.y,d.x])[0]})
    .attr("cy", function(d) {return projection([d.y,d.x])[1]})
    .style("display", function(d) {return parseInt(d.y) -30.24 < 45 && parseInt(d.y) -30.24 > -45 ? "block" : "none"})

  }
</script>
  </footer>

</html>

cities.csv

"label","population","country","x","y"
"San Francisco", 750000,"USA",37,-122
"Fresno", 500000,"USA",36,-119
"Lahore",12500000,"Pakistan",31,74
"Karachi",13000000,"Pakistan",24,67
"Rome",2500000,"Italy",41,12
"Naples",1000000,"Italy",40,14
"Rio",12300000,"Brazil",-22,-43
"Sao Paolo",12300000,"Brazil",-23,-46