1

Similarly to this question, we want to functionally set our Leaflet map's marker's colors based off a value, except our map is built with geojson data.

We want markers' colors to be functional to color_value (eg. different shade of green), but we don't know how to build that like this answer explains with L.AwesomeMarkers.icon({markerColor: determineColor(rating)});, because the markers for all our entries are built at once with pointToLayer: function (feature, coordinates) {return L.marker(coordinates, { icon: customicon });}. Simplified eg:

<!DOCTYPE html>
<style>
    html,
    body { margin: 0px; height: 100%; }
    body {display: flex;}
</style>

<body>
    <link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css"
        integrity="sha512-xodZBNTC5n17Xt2atTPuE1HxjVMSvLVW9ocqUKLsCC5CXdbqCmblAshOMAS6/keqq/sMZMZ19scR4PsZChSR7A=="
        crossorigin="" />
    <script src="https://unpkg.com/[email protected]/dist/leaflet.js"
        integrity="sha512-XQoYMqMTK8LvdxXYG3nZ448hOEQiglfqkJs1NOQV44cWnUrBc8PkAOcXy20w0vlaXaVUearIOBhiXZ5V3ynxwA=="
        crossorigin=""></script>
    <div id="mapid" style="flex: 1"></div>
    <script>var myMap = L.map("mapid");
        L.tileLayer('https://{s}.tile.openstreetmap.fr/hot/{z}/{x}/{y}.png').addTo(myMap);
        myMap.setView([51.5, -0.09], 10);

        var geojsonFeatureCollection =
        {
            "type": "FeatureCollection",
            "features": [{
                "type": "Feature",
                "geometry": {
                    "type": "Point",
                    "coordinates": [-0.09, 51.5]
                },
                "properties": {
                    "color_value": 1
                }
            },
            {
                "type": "Feature",
                "geometry": {
                    "type": "Point",
                    "coordinates": [-0.4, 51.5]
                },
                "properties": {
                    "color_value": 10
                }
            }]
        }

        const myCustomColor = '#007a83'
        const markerHtmlStyles = `
  background-color: ${myCustomColor};  width: 1.3rem;  height: 1.3rem;  display: block;`
        const customicon = L.divIcon({html: `<span style="${markerHtmlStyles}" />`})

        L.geoJSON(geojsonFeatureCollection, {
            pointToLayer: function (feature, coordinates) {
                return L.marker(coordinates, { icon: customicon });
            }
        })
            .addTo(myMap);
    </script>
</body>
</html>

We've found this tutorial which gets us a little closer by explaining how to choose different markers based off some value, but we want to set the color itself, not choose from existing markers.

How can we make myCustomColor functional to color_value, or otherwise set marker colors programmatically for geojson data?

1 Answer 1

2

You are almost there! :-)

You can define the desired color directly as a property on each GeoJSON feature. Leaflet passes each feature of the GeoJSON collection to pointToLayer, allowing you to access its properties.

Check out the snippet below.

var myMap = L.map("mapid");

L.tileLayer('https://{s}.tile.openstreetmap.fr/hot/{z}/{x}/{y}.png').addTo(myMap);

myMap.setView([51.5, -0.09], 10);

var geojsonFeatureCollection = {
  "type": "FeatureCollection",
  "features": [{
      "type": "Feature",
      "geometry": {
        "type": "Point",
        "coordinates": [-0.09, 51.5]
      },
      "properties": {
        // You can define a different color for each property
        // and access it in pointToLayer().
        "color_value": '#007a83'
      }
    },
    {
      "type": "Feature",
      "geometry": {
        "type": "Point",
        "coordinates": [-0.4, 51.5]
      },
      "properties": {
        // Here I might use a different color
        "color_value": '#003134'
      }
    }
  ]
};

L.geoJSON(geojsonFeatureCollection, {
    pointToLayer: function(feature, coordinates) {
      // Leaflet passes each GeoJSON feature in the collection in here,
      // allowing you to access the feature's properties
      const color_value = feature.properties.color_value;

      // With the color obtained from the properties, you can now create
      // the marker icon with the correct color.
      const markerHtmlStyles = `background-color: ${color_value};  width: 1.3rem;  height: 1.3rem;  display: block;`;

      const customicon = L.divIcon({
        html: `<span style="${markerHtmlStyles}" />`
      });

      return L.marker(coordinates, {
        icon: customicon
      });
    },
  })
  .addTo(myMap);
html,
body {
  margin: 0px;
  height: 100%;
}

body {
  display: flex;
}
<!DOCTYPE html>

<body>
  <link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css" integrity="sha512-xodZBNTC5n17Xt2atTPuE1HxjVMSvLVW9ocqUKLsCC5CXdbqCmblAshOMAS6/keqq/sMZMZ19scR4PsZChSR7A==" crossorigin="" />
  <script src="https://unpkg.com/[email protected]/dist/leaflet.js" integrity="sha512-XQoYMqMTK8LvdxXYG3nZ448hOEQiglfqkJs1NOQV44cWnUrBc8PkAOcXy20w0vlaXaVUearIOBhiXZ5V3ynxwA==" crossorigin=""></script>
  <div id="mapid" style="flex: 1"></div>
</body>

</html>

Alternatively, if you want to calculate the color based off color_value, you can proceed almost the same way: Read color_value property inside pointToLayer, generate the color (e.g., by using an approach like the one outlined here: Programmatically Lighten or Darken a hex color (or rgb, and blend colors)) and pass it to your marker's styling.

Hope this helps!

Not the answer you're looking for? Browse other questions tagged or ask your own question.