Question

I'm developing an interactive choropleth map with Leaflet.js using a geoJSON base layer and symbolizing polygons with JSON data pulled from a Socrata API endpoint. It's based on the Leaflet.js choropleth example posted here.

I'm stumped on one issue -- when I color (i.e. style) the geoJSON polygons using a property that is initially part of the JSON data (e.g. pop) the polygon colors load when the map loads. However, when I style the geoJSON polygons using a property that I appended to the geoJSON layer (e.g. estimate), the polygon colors do not load on map load and only appear when I hover over each polygon. My live map can be viewed here.

Here's the relevant code, can anyone see what my problem is? As I'm relatively new to learning JavaScript I assume I'm missing some simple syntax or program order rule that is preventing the Leaflet map from coloring the polygons based on appended properties. I've rearranged the order of my code and changed many things but am getting the same result again and again. Thank you so much for helping a newbie with learning JavaScript!!

//Initiate geojson variable so listeners can access
var geojson;

//Add TopoJSON layer and append SODA data to symbolize polygons

//Use d3.js to pull in TopoJSON, convert to geoJSON, and add to Leaflet map
d3.json("hrabasetopo.json", function(error, topology) {
    var collection = topojson.feature(topology, topology.objects.layer1);
    var hraData = [collection];

    //Pull summary data from SODA

    //Variable to select desired indicator
    var where = "$where=indicator='uninsure'";
    //Variable to order HRA and zip by VID to match order of features in geoJSON base
    var order = "&$order=vid";
    //Variable to concatenate queries with URL
    var url = "http://data.kingcounty.gov/resource/ajpg-dges.json?"+where+order;
    //jQuery GET request to pull data from SODA and feed to callback function with geoJSON
    $.get(url, 
    function(soda) {
        //Output SODA JSON and hra base geoJSOn to external function
        symbolize(soda);
        }, 
    "json");    

    //Function to append SODA data to TopoJSON converted to geoJSON
    function symbolize(soda) {

         //Loop to copy all of SODA JSON properties to HRA base geoJSON
         for (var i = 0; i<hraData[0].features.length; i++) {
            hraData[0].features[i].properties.estimate = Number(soda[i].estimate);
        }
    };

    //Get color depending on selected estimate
    function getColor(d) {
        return d > 20.1 ? '#e31a1c' :
               d > 16.2 ? '#fd8d3c' :
               d > 11.3 ? '#fecc5c' :
                           '#ffffb2';
    }

    //Incorporate getColor function into overall style function for HRA layer
    function style(feature) {
        return {
            weight: 1,
            opacity: 1,
            color: 'white',
            dashArray: '5',
            fillOpacity: 0.8,
            fillColor: getColor(feature.properties.estimate)
        };
    }

    //Add hraData as geoJSON layer to Leaflet map
    geojson = L.geoJson(hraData, {
        style: style,
        onEachFeature: onEachFeature
    }).addTo(map);

})
Was it helpful?

Solution

Figured it out myself! One challenging aspect (for me) of learning JavaScript is getting used to asynchronous program flow, as all of the statistical software coding languages that I am used to (Stata, R, SAS, etc.) use synchronous programming. My problem here was that I was not forcing the Leaflet.js map to wait to load until my JSON data from my API endpoint had been called and appended to my geoJSON layer. The solution was to wrap the map setup functions in a big function called mapSetup, and use the jqXHR Object .done method as in the following code:

    //jQuery GET request to pull data from SODA and feed to callback function with geoJSON
        $.get(url) 
            .done(function(soda) {
            //Output SODA JSON and hra base geoJSOn to external function
            symbolize(soda);        
            })
            .done(function() {
            mapSetup();
            }); 

    //Function to append SODA data to TopoJSON converted to geoJSON
    function symbolize(soda) {

        //Loop to copy all of SODA JSON properties to HRA base geoJSON
        for (var i = 0; i<hraData[0].features.length; i++) {
            hraData[0].features[i].properties.estimate = Number(soda[i].estimate);
        }
    };

        function mapSetup() {
        //Functions to add geoJSON to leaflet map, add controls, legends, etc.
        };
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top