[GIS] display a choropleth map using D3 and Leaflet

choroplethd3geojsonjavascriptleaflet

I am trying to get a leaflet map to display a choropleth map using d3. I have written this code using samples I have found however the map just displays as the black fill, not the color classes I defined. This is the code I am using. Anyone have an idea about what I'm doing wrong?

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />

<meta name="viewport" content="width=device-width, initial-scale=1.0">

<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.5/leaflet.css" />

</head>
<body>
<div id="map" style="width: 900px; height: 500px"</div>
<script src="http://d3js.org/d3.v2.min.js?2.9.3"></script>
<script src="http://cdn.leafletjs.com/leaflet-0.5/leaflet.js"></script>
<script>

    var map = L.map('map').setView([41.57, -93.71], 4);

         L.   tileLayer('http://{s}.tile.cloudmade.com/9067860284bc491e92d2342cc51d47d9/998/256/{z}/{x}/{y}.png', {
        //minZoom: 7,
        //maxZoom: 18,
        attribution: 'Map data &copy; <a href="http://openstreetmap.org">OpenStreetMap</a> contributors, <a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, Imagery © <a href="http://cloudmade.com">CloudMade</a>'
    }).addTo(map);

var svg = d3.select(map.getPanes().overlayPane).append("svg"),
g = svg.append("g").attr("class", "leaflet-zoom-hide");

//quantize scale and output range -input domain specified after data is loaded
var color = d3.scale.quantize()
                .range(["rgb(237,248,233)","rgb(186,228,179)","rgb(116,196,118)","rgb(49,163,84)","rgb(0,109,44)"]);

d3.json("us-states.json", function(collection) {
var bounds = d3.geo.bounds(collection),
  path = d3.geo.path().projection(project);

var feature = g.selectAll("path")
  .data(collection.features)
.enter().append("path");

map.on("viewreset", reset);
reset();

// Reposition the SVG to cover the features.
function reset() {
var bottomLeft = project(bounds[0]),
    topRight = project(bounds[1]);

svg .attr("width", topRight[0] - bottomLeft[0])
    .attr("height", bottomLeft[1] - topRight[1])
    .style("margin-left", bottomLeft[0] + "px")
    .style("margin-top", topRight[1] + "px");

g   .attr("transform", "translate(" + -bottomLeft[0] + "," + -topRight[1] + ")");

feature.attr("d", path);
}

// Use Leaflet to implement a D3 geographic projection.
function project(x) {
var point = map.latLngToLayerPoint(new L.LatLng(x[1], x[0]));
return [point.x, point.y];
}
});
// load population data
d3.csv("population.csv", function(data) {
//Set input domain for color scale
color.domain([
    d3.min(data, function(d) { return d.population; }), 
    d3.max(data, function(d) { return d.population; })
]);
//Load in GeoJSON data
d3.json("us-states.json", function(json) {

    //Merge the ag. data and GeoJSON
    //Loop through once for each ag. data value
    for (var i = 0; i < data.length; i++) {

        //Grab state name
        var dataState = data[i].state;

        //Grab data value, and convert from string to float
        var dataPopulation = parseFloat(data[i].population);

        //Find the corresponding state inside the GeoJSON
        for (var j = 0; j < json.features.length; j++) {

            var jsonState = json.features[j].properties.name;

                if (dataState == jsonState) {

                    //Copy the data value into the JSON
                    json.features[j].properties.population = dataPopulation;

                    //Stop looking through the JSON
                    break;

                }
        }       
    }

    //Bind data and create one path per GeoJSON feature
    svg.selectAll("path")
       .data(json.features)
       .enter()
       .append("path")
       .attr("d", path)
       .style("fill", function(d) {
            //Get data value
            var value = d.properties.value;

                if (population) {
                //If value exists…
                    return color(value);
                } else {
                //If value is undefined…
                    return "#ccc";
                }
       });

});

});


</script>

<body>
</body>
</html>

Best Answer

Difficult to understand what is really going on here without fiddling with some live code, but have you checked the console for errors?

if (population) { //If value exists…

As a guess, this bit of code looks wrong. population looks like an undefined variable to me, so probably the code errors here and nothing gets styled. Maybe try d.properties.population instead?