I am dealing with a map on which vector layers come from different geojson files. Each file contains a series of polygons (type = multipolygon).
Each polygon is characterised by a series of parameters, such as "species". By default layers are set non visible and have a certain style (fill and stroke).
I created a select to enable the search by species
<form>
<select class="species">
<option value="">Choose</option>
<option value="Balaenopteraphysalus">Balaenoptera physalus</option>
<option value="Physetercatodon">Physeter catodon</option>
<option value="Delphinusdelphis">Delphinus delphis</option>
<option value="Tursiopstruncatus">Tursiops truncatus</option>
<option value="Stenellacoeruleoalba">Stenella coeruleoalba</option>
<option value="Grampusgriseus">Grampus griseus</option>
<option value="Globicephalamelaena">Globicephala melaena</option>
<option value="Ziphiuscavirostris">Ziphius cavirostris</option>
<option value="Monachusmonachus">Monachus monachus</option>
</select>
</form>
<button id="clearSpecies">Clear</button>
I then wrote a jquery that enables to upload the layers only if the selected species is present in the file
$(document).ready(function() {
$("select.species").change(function() {
var selectedSpecies = $(".species option:selected").val();
if (selectedSpecies) {
//geojson request
$.getJSON('http://localhost:8888/maps/prova/immas_test_separated_js_immas_file/resources/test_imma_2.geojson', function (data) {
$.each(data.features, function (key, val) {
$.each(val.properties, function(i,j){ //i = proprietà l = valore proprietà
if(i == 'Species') {
//replace spaces to have one single word
j = j.replace(/\s+/g, '');
species = j.split(",");
species.forEach(function(animal) {
if(animal == selectedSpecies) {
//test passed
prova1.setVisible(true);
//add something to change style (hide the multipolygon not which are not satisfying the condition and show those who satisfy the condition
}
});
}
});//loop ends
});//loop ends
});
//ends geojson request
}
});
//clears layers
$("#clearSpecies").click(function(){
prova1.setVisible(false);
});
});
Everything works fine. However, since I actually deal with different polygons in the same layer, I need a further step.
After setting the layer as visible in the loop above (prova1.setVisible(true);
), I need to change style not to the whole layer, but to single polygons ccording to the if condition: those in which the parameter "species" do not contain the selected option value must change fill and stroke to none (transparent), while the polygons for which the parameter species contains the selected option value must be filled with color.
Consider that the parameter "species" in the geojson file contains more than one name (ex. "Species": "Monachus monachus, Balaenoptera physalus, Physeter macrocephalus, Ziphius cavirostris, Globicephala melas, Grampus griseus, Tursiops truncatus, Stenella coeruleoalba, Delphinus delphis")
Any suggestion? Thanks!
=========== UPDATE ===========
I followed @pavlos suggestion an studied the example reported here. However I didn't come through.
Here the code I used for the styles and to create the function styleFunction(feature, resolution)
//SET STYLES
//set colours
var colourSpecies = [64,196,64,1];
var colourCriteria = [90,160,64,1];
//set levelnames related to colours
var selectedLevels = {
'species': colourSpecies,
'criteria': colourCriteria
}
//default style
var defaultStyle =
new ol.style.Style({
fill: new ol.style.Fill({
color: [0,0,0,1]
}),
stroke: new ol.style.Stroke({
color: [0,0,0,1],
width: 1
})
});
//custom styleFunction
var styleCache = {};
function styleFunction(feature, resolution) {
var level = feature.get('selectedLevel');
if (!level || !selectedLevels[level]) {
return [defaultStyle];
}
if (!styleCache[level]) {
styleCache[level] =
new ol.style.Style({
fill: new ol.style.Fill({
color: selectedLevels[level]
}),
stroke: defaultStyle.stroke
});
}
return [styleCache[level]];
}
I hence tried to rewrite the JQuery/javascript for handling the style change, when the user search for a species. In doing this I didn't use the forEachFeature function as I never succeeded in getting any results, but I looped inside the objects via jQuery. The various loops are due because the "species" parameter contains a string with different names (genus + species), otherwise I could have overcomed the problem by copying exactly the example given in the link above. As said previously, I would like to highlight with a differen style those polygons which contain in the string the species searched with the select (better would be to hightlight these and hide all the others not containing the species searched).
$(document).ready(function() {
$("select.species").change(function() {
var selectedSpecies = $(".species option:selected").val();
if (selectedSpecies && selectedSpecies !='') {
//geojson request
$.getJSON('http://localhost:8888/maps/prova/immas_test_separated_js_immas_file/resources/test_imma_2.geojson', function (data) {
{$.each(data.features, function (key, val) {
console.log(val.properties);
$.each(val.properties, function(i,j){ //i = proprietà l = valore proprietà
console.log(i);
if(i == 'Species') {
j = j.replace(/\s+/g, ''); //eliminates spaces between genus and species
var species = j.split(",");
console.log(species);
var species_array_length = species.length;
console.log(species_array_length);
var counter;
for (counter = 0; counter < species_array_length; counter++){
if (selectedSpecies === species[counter]){
var animal = species[counter];
console.log('Found' + animal);
var feature = val.properties;
console.log(feature);
feature.set('selectedLevel', 'species');
}
}//termina ciclo for
}
});//termina loop
});//temrina loop}
});
//ends geojson request
prova1.setVisible(true);
}
});
//clears layers
$("#clearSpecies").click(function(){
prova1.setVisible(false);
});
});
However it doesn't work: an error with feature.set('selectedLevel', 'species');
is displayed and again all layers are uploaded with the default style. I am quite worried as this is a simple example. At the end I should deal with something like 18 geojson files and two selections (by species and by "criteriacode" which is another parameter inside my geojson file).
I add here a link to the files used (included teh geojson used as test)
This an ====UPDATE=== to the question posted above.
thanks to some suggestions provided by @pavlos, I succeded in solving the problems above.
The whole solution with test files is available at this fiddle.
SETTING STYLES TO THE LAYER
//SET STYLES
//default style
var defaultStyle =
new ol.style.Style({
fill: new ol.style.Fill({
color: [0,0,0,1]
}),
stroke: new ol.style.Stroke({
color: [0,0,0,1],
width: 1
})
});
var selectStyle = new ol.style.Style({
fill: new ol.style.Fill({
color: [64,196,64,1]
}),
stroke: new ol.style.Stroke({
color: [64,196,64,1],
width: 1
})
});
var transparentStyle = new ol.style.Style({
fill: new ol.style.Fill({
color: [255,255,255, 0]
}),
stroke: new ol.style.Stroke({
color: [255,255,255, 0],
width: 1
})
});
//Gets the layer sources
var ocean_map =
new ol.layer.Tile({
source: new ol.source.XYZ({
url: 'https://services.arcgisonline.com/ArcGIS/rest/services/' +
'Ocean_Basemap/MapServer/tile/{z}/{y}/{x}',
}),
visible: true,
});
var source =
new ol.source.Vector({
format: new ol.format.GeoJSON({
}),
dataProjection: 'EPSG:3857',
url: 'test.geojson',
attributions: [
new ol.Attribution({
html: 'Mediteranean region'
})
]
});
var prova1 =
new ol.layer.Vector({
source: source,
style: defaultStyle,
name: 'Mediteranean region',
visible: false,
});
MANAGING THE STYLES
//when clicking the select
document.getElementById("species_select").addEventListener('click', function () {
resetSelectElement(mySelect);
//first step it loads the vector layer and sets the style to transparent
prova1.setStyle(transparentStyle);
prova1.setVisible(true);
//second step when the select changes (i.e. I make a choice)
$("#species_select").change(function() {
//it starts the function to change styles according to the selection made
var selectedSpecies = $("#species_select option:selected").text();
console.log('selectedSpecies',selectedSpecies);
source.forEachFeature(function(feat){
console.log(feat);
console.log(feat.get('Species'))
console.log(feat.get('Species').indexOf(selectedSpecies));
//if substring(selected text) exist within fetaure property('Speices)
//should return any value other than -1
if (feat.get('Species').indexOf(selectedSpecies)!=-1) {
//so set the style on each feature
feat.setStyle(selectStyle);
} else {
//and if doesnt exist switch back to the deafult style
feat.setStyle(transparentStyle);
}
})
});
});
//clears layers
$("#clearSpecies").click(function(){
prova1.setVisible(false);
prova1.setStyle(defaultStyle);
});