Leaflet GeoJSON – Unable to Use fillColor Values from GeoJSON

geojsonleafletpolygonstyle

I have a web page which fetches some remote GeoJSON and displays a combination of marker points, polygons and lines on my map.

Within that JSON is the fillColor, fillOpacity, etc that I wish to use for each polygon.

Here's an excerpt of the GeoJSON which is returned:

{
    "geometry": {
    "coordinates": [
        [
        [
            -2.4710206012402689,
            53.470236995186752
        ],
        [
            -2.4691196881249033,
            53.4613205079861
        ],
        [
            -2.4681978304127927,
            53.461390191450619
        ],
        [
            -2.4681448784765276,
            53.461140769261917
        ],
        [
            -2.4710206012402689,
            53.470236995186752
        ]
        ]
    ],
    "type": "Polygon"
    },
    "id": "CE71BB87D309C9199DC60BC7586774468D2AE99C",
    "properties": {
    "hazardFactor": "60",
    "hazardFactorName": "Danger",
    "fillColor": "#FF0055",
    "strokeColor": "#BF0442",
    "fillOpacity": "0.35",
    "strokeWidth": "1",
    "strokeOpacity": "0.8",
    "detailedCategory": "uk:frz",
    "iconUrl": "https://domain.com//v1/map/icon?icon=uk_frz.png",
    "name": "Manchester/barton",
    "pointOfContact": "0161-789 1362 (Administration and Operations)",
    "listOrderHint": "1000",
    "category": "airspace",
    "designator": "EGCB",
    "filters": [
        {
        "name": "Airspace",
        "property": "show",
        "active": true
        },
        {
        "name": "Fight Restriction Zone",
        "property": "show",
        "active": true
        }
    ],
    "display": {
        "category": "airspace",
        "detailedCategory": "Flight Restriction Zone",
        "title": "Manchester/barton",
        "sections": [
        {
            "iconUrl": "https://domain.com//v1/map/icon?icon=warning.png",
            "title": "Flight Restriction Zone",
            "text": "Flight Restriction Zones surround certain protected aerodromes. To Fly in this area you will need permission from Air Traffic Control or the Flight Information Service at this aerodrome."
        },
        {
            "iconUrl": "https://domain.com//v1/map/icon?icon=warning.png",
            "title": "Summary",
            "text": "Red zones are regulated high-risk areas."
        }
        ],
        "actions": []
    }
    },
    "type": "Feature"
},

I wish to loop through each item and apply the style settings to each polygon, based on the returned feature.properties.fillColor and feature.properties.fillOpacity and so on.

Here's my code.

The polygons, markers and lines all display correctly but they are all in the default Blue color and seem to be ignoring my requests to use the fillColor value in the GeoJSON.

// Create an empty layergroup for the data
var LayerAA = L.layerGroup();

// Build Layer: AA
function getAAdata() {
    LayerAA.clearLayers();
    fetch("/v2/mapdata/geojson?n=" + map.getBounds().getNorth() + "&e=" + map.getBounds().getEast() + "&s=" + map.getBounds().getSouth() + "&w=" + map.getBounds().getWest())
      .then(function (responseAA) { return responseAA.json() })
      .then(function (dataAA) {

          // Create a L.GeoJSON out of the data
          var locationsAA = L.geoJson(dataAA, {

              onEachFeature: function (feature, layer) {
                  layer.bindPopup(feature.properties.name, { color: feature.properties.fillColor });
              },

              // Filter out CTA & TMA airspace types
              filter: function (feature, layer) {
                  return (feature.properties.airspaceType !== "CTA" && feature.properties.airspaceType !== "TMA");
              },

          });

          // Add the L.GeoJSON instance to the empty layergroup
          LayerAA.addLayer(locationsAA).addTo(map);

      });

}

Why does this not work?

Best Answer

If you take a look at Leaflet docs about creating GeoJSON layer (which you should), you will see there is style option by which you can set dynamic styling function, which can set feature style depending on feature properties.

That's exactly what is done in Leaflet choropleth example, where GeoJSON layer is created with dynamic style, exactly as you want:

function style(feature) {
    return {
        fillColor: getColor(feature.properties.density),
        weight: 2,
        opacity: 1,
        color: 'white',
        dashArray: '3',
        fillOpacity: 0.7
    };
}

L.geoJson(statesData, {style: style}).addTo(map);

In your case this would be something like:

function setStyle(feature) {
  return {
    fillColor: feature.properties.fillColor,
    color: feature.properties.strokeColor,
    fillOpacity: feature.properties.fillOpacity,
    opacity: feature.properties.strokeOpacity
  };
}
function getAAdata() {
...
    var locationsAA = L.geoJson(dataAA, {
        style: setStyle,
        onEachFeature: function (feature, layer) {
            layer.bindPopup(feature.properties.name, { color: feature.properties.fillColor });
        },
        filter: function (feature, layer) {
            return (feature.properties.airspaceType !== "CTA" && feature.properties.airspaceType !== "TMA");
        },
    });
...
}
Related Question