[GIS] Custom marker based on geojson attribute in Leaflet

filtergeojsoniconleafletmarkers

I would like to customize a marker to add an id (number) on top of it, this id is coming from an attribute of the geojson ("id" in the following example)

{
"type":"FeatureCollection",
"features":[
    {
      "type":"Feature",
      "geometry":{
        "type":"Point",
        "id":1,
        "destination":"Police station",
        "coordinates":[
          "4.3520735404177699","50.846502697562201"
        ]
      },
    {
      "type":"Feature",
      "geometry":{
        "type":"Point",
        "id":2,
        "destination":"Museum",
        "coordinates":[
          "4.347903728485107","50.846658450225334"
        ]
      },
...

I'm stuck with L.ExtraMarkers :

var json = L.ExtraMarkers.icon({
            icon: 'fa-number',
            number: 'x',
            iconColor: 'white',
            markerColor: 'black',
            shape: 'circle',
            prefix: 'fa'
            });

    var geojsonLayer = new L.GeoJSON.AJAX("query_json.php?&do=DCT1",{pointToLayer: function (feature, latlng) {
                return L.marker(latlng, {icon: json});    
    },

    onEachFeature: function (feature,layer) {
        var popup = [];
        for (var prop in feature.properties) {
            popup.push(prop + ": " + feature.properties[prop]);
        }
        layer.bindPopup(popup.join("<br />"));
    }}).addTo(map);

number: 'x', should be the variable "id" coming from the geojson.

I'm also stuck with L.circleMarker :

var stylegeojson = {color:'white', fillColor:'blue', radius:10, opacity:1.0, fillOpacity:1.0, weight:2};

var geojsonLayer = new L.GeoJSON.AJAX("query_json.php?&do=DCT1", {pointToLayer: function (feature, latlng) {
                return L.circleMarker(latlng, stylegeojson);
                // what should I add here to print "id" value on top of it ?
    },
    }).addTo(map);

I think I have to add an

onEachFeature: function(feature, id) {

but I don't know to write it.

Ideally I'd also like to have a different marker color per "destination"

I am wondering if someone already did this before or has an idea how to do this?

Best Answer

First, your GeoJSON is invalid. Each feature should have a geometry and a properties property. i.e. the following is wrong:

var feature = {
  "type":"Feature",
  "geometry":{
    "type":"Point",
    "coordinates":[ "4.347903728485107","50.846658450225334" ],
    "id":2,
    "destination":"Museum"
  }
}

And the following is right:

var feature = {
  "type":"Feature",
  "geometry":{
    "type":"Point",
    "coordinates":[ "4.347903728485107","50.846658450225334" ]
  }, 
  "properties": {
    "id":2,
    "destination":"Museum"
  }
}

Use GeoJSONLint to check validity of your GeoJSON.

Second: the pointToLayer function should refer to the value of the id property of the feature if you want to use it.

This is wrong:

var icon= L.icon.glyph({
  prefix: '',
  glyph: feature.properties.id,
  // Any other icon options here
});

var geoJsonLayer = L.geoJSON(featureCollection, {
  pointToLayer: function(feature, latlng) {
    return L.marker(latlng, {icon: icon})
  }
});

And this is right (note the variable scope for feature and thus feature.properties.id:

var geoJsonLayer = L.geoJSON(featureCollection, {
  pointToLayer: function(feature, latlng) {
    return L.marker(latlng, {
      icon: L.icon.glyph({
        prefix: '',
        glyph: feature.properties.id
      })
    })
  }
})

See a working example using Leaflet.Icon.Glyph.

I think I have to add an onEachFeature: function(feature, id) {

No, you don't. If you want to create a different marker for each GeoJSON point feature, do so in the pointToLayer callback option. Use onEachFeature for stuff you want to get done after the leaflet layers (markers/lines/polygons) have been instantiated.