如何使用多边形更改 geojson 矢量图层中的样式

How to change style in geojson vector layer with multipolygons

我正在处理一张地图,其上的矢量图层来自不同的 geojson 文件。每个文件都包含一系列多边形(type = multipolygon)。

每个多边形由一系列参数表征,例如"species"。默认情况下,图层设置为不可见并具有特定样式(填充和描边)。

我创建了一个 select 以启用按物种搜索

            <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>

然后我写了一个 jquery 仅当文件中存在 selected 物种时才允许上传图层

$(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);
            });
});

一切正常。但是,由于我实际上在同一层中处理不同的多边形,因此我需要更进一步。 在上面的循环中将图层设置为可见后 (prova1.setVisible(true); ),我需要将样式更改为不是整个图层,而是根据 if 条件更改为单个多边形:参数 "species" 做的那些不包含 selected 选项值的必须将填充和描边更改为 none(透明),而参数 species 包含 selected 选项值的多边形必须用颜色填充。

考虑到 geojson 文件中的参数 "species" 包含多个名称(例如 "Species":"Monachus monachus, Balaenoptera physalus, Physeter macrocephalus, Ziphius cavirostris, Globicephala melas, Grampus griseus, Tursiops truncatus, Stenella coeruleoalba, Delphinus delphis")

有什么建议吗?谢谢!

=========== 更新 ===========

我听从了@pavlos 的建议,研究了报告的示例 here。但是我没有通过。

这里是我用于样式和创建 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]];
}

因此,我尝试重写 JQuery/javascript 来处理用户搜索物种时的样式更改。在执行此操作时,我没有使用 forEachFeature 函数,因为我从未成功获得任何结果,但我通过 jQuery 在对象内部循环。各种循环是由于 "species" 参数包含一个具有不同名称(属 + 种)的字符串,否则我可以通过完全复制上面 link 中给出的示例来解决这个问题。如前所述,我想用不同的样式突出显示那些在字符串中包含用 select 搜索的物种的多边形(最好突出显示这些并隐藏所有其他不包含搜索物种的多边形)。

$(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);
    });

});

但它不起作用:显示 feature.set('selectedLevel', 'species'); 错误,所有图层再次以默认样式上传。我很担心,因为这是一个简单的例子。最后,我应该处理 18 个 geojson 文件和两个 selection(按物种和 "criteriacode",这是我的 geojson 文件中的另一个参数)。

我在此处添加一个 link 到所用的 files(包括用作测试的 geojson)

这是对上面发布的问题的 ====UPDATE===

感谢@pavlos提供的一些建议,我成功解决了上述问题。

包含测试文件的完整解决方案可在此处获得fiddle

为图层设置样式

//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,
});

管理样式

//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);
});