Wednesday, 27 February 2019

leaflet - Adding one search box for multiple GeoJSON polygon layers?


Multiple GeoJSON markers can be combined to one group layer then search on a specific attribute but doesn't work for GeoJSON polygons.


How to put multiple GeoJSON markers and polygons in one search box?


 var map = L.map('map', {
zoom: 14,
center: new L.latLng(35.948782,8.139912),
layers: L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png')

});
//Geojson points
var piky1=new L.geoJson(pol00);
var piky2=new L.geoJson(pol01);
//Geojson polygones
var piky3=new L.geoJson(pick1);
var piky4=new L.geoJson(pick2);

//group of Geojson points markers
var lay=L.featureGroup([piky1,piky2]);

//group of Geojson polygones
var pik=L.featureGroup([piky3,piky4]);

L.control.search({

//If we consider searshing layers as the marker group
//layer: pik,

//If we consider searshing layers as the polygones group
layer: lay,


propertyName: 'Name',
})
.addTo(map);

Answer



Searching in GeoJSON features on a specific "attribute", especially through a search box, is not part of standard Leaflet API as far as I know.


Do you mean you use a plugin that does not support polygons? If so, please can you kindly detail which plugin you are using?


I know Leaflet Control Search plugin has no problem searching into GeoJSON markers and other geometry types.


Demo with US States polygons: http://labs.easyblog.it/maps/leaflet-search/examples/geojson-layer.html





EDIT: following the sharing of your code


In your code, you build one GeoJSON Layer Group per GeoJSON data object (which contains a Feature Collection, with several points or polygons). Then you gather them into a single Feature Group, so that Leaflet Control Search can receive a single Layer Group in its layer option.


Unfortunately, current version of Leaflet Control Search badly handles nested GeoJSON Layer Groups: it correctly manages points (markers), but it fails on vector shapes because they do not have getLatLng method.


So you have 2 possible workarounds:



  1. Instead of building several GeoJSON Layer Groups and to nest them into a single Feature Group, directly build a single GeoJSON Layer Group (pass all your GeoJSON data objects as an array, like L.geoJson([pol00, pol01]). Then you can directly pass this Group into layer option of L.control.search factory. And Leaflet Control Search plugin will correctly search into the polygons.


// You can directly build a GeoJSON layer group with an array of GeoJSON objects:
var piky5 = L.geoJson([pol00, pol01]);



  1. Patch Leaflet Control Search plugin code to correctly handle nested Layer Groups with vector shapes inside. It is quite simple, even though it means many lines of code, but most of them are unchanged.


///////////////////////////
// Patch leaflet-search to manage nested GeoJSON shapes.
///////////////////////////

// Copy-paste into your script before instantiating L.control.search.
L.Control.Search.include({
_recordsFromLayer: function() { //return table: key,value from layer

var that = this,
retRecords = {},
propName = this.options.propertyName,
loc;

function searchInLayer(layer) {
if (layer instanceof L.Control.Search.Marker) return;

if (layer instanceof L.Marker || layer instanceof L.CircleMarker) {
if (that._getPath(layer.options, propName)) {

loc = layer.getLatLng();
loc.layer = layer;
retRecords[that._getPath(layer.options, propName)] = loc;

} else if (that._getPath(layer.feature.properties, propName)) {

loc = layer.getLatLng();
loc.layer = layer;
retRecords[that._getPath(layer.feature.properties, propName)] = loc;


} else {
throw new Error("propertyName '" + propName + "' not found in marker");
}
} else if (layer.hasOwnProperty('feature')) { //GeoJSON

if (layer.feature.properties.hasOwnProperty(propName)) {
loc = layer.getBounds().getCenter();
loc.layer = layer;
retRecords[layer.feature.properties[propName]] = loc;
} else {

throw new Error("propertyName '" + propName + "' not found in feature");
}
} else if (layer instanceof L.LayerGroup) {
//TODO: Optimize
layer.eachLayer(searchInLayer, this);
}
}

this._layer.eachLayer(searchInLayer, this);


return retRecords;
}
});

Updated JSFiddle: http://jsfiddle.net/gevzoxs1/15/


EDIT: mentioned in repository issue #95 and submitted PR #101. Hopefully the plugin will be corrected soon and it should work for you with the new version without having to "patch" it in your script.


No comments:

Post a Comment

arcpy - Changing output name when exporting data driven pages to JPG?

Is there a way to save the output JPG, changing the output file name to the page name, instead of page number? I mean changing the script fo...