Select 多个过滤器,仅显示具有共同特征的标记

Select multiple filters, display only markers that have common features

我有传单地图,已经可以使用了。目前,我有多个复选框过滤器(两张地图上总共有近 40 个):用户可以同时 select 多个标记。筛选器代表 "specialities",当我单击筛选器时,它会显示具有该专业的医院。所以在地图上,我可以有集群来显示具有多个专科的医院,以及显示具有一个专科的不同医院的单个标记。

我想做什么:

每个单独的 chekcbox 都必须显示相应的标记,但是一旦我同时选中多个复选框,我只想显示可以找到相应功能的标记(医院)。例如,如果我同时单击过滤器 A 和 B,我只想看到有专科 A 和 B 的医院,并隐藏只有一个特征的标记。

因为我已经编写了所有函数的代码,所以我想避免重建新的 GeoJSON 功能。我试过了,但它重复了标记。

我正在寻找这样的循环(当然这是行不通的):

$('#filters input').on('click', function(){// if click on checkbox
    var ID = $(this).attr("id");//I can get the checkbox IDs here, which correspond to the feature name

if ($('#filters input:checked').length >=2 ){ // as soon as there are more than one checkbox checked    
    var checkboxes = $("#filters input:checked");
        for (var i = 0; i < checkboxes.length; i++) {//for all checked checkboxes
            if(feature[i].geometry.coordinates == feature[i].geometry.coordinates){//if the markers have same coordinates
                return layer.feature.properties.Examen; // show me those markers
            }else{
                return false;// hide other markers
            }        
     }
}
})

我想我已经通过以下代码获得了所有需要的信息,但我不知道如何合并它以获得我需要的信息...

这是一项功能的示例:

{
                "type": "Feature",
                "properties": {
                    "Examen": "iduronate",
                    "Prelevement": "DBS ou Buvard 1 tâche de sang (+ 1 contrôle) ou Sang total EDTA 5 ml (Leucocytes)",
                    "Envoi": "Envoi rapide à température ambiante",
                    "Laboratoire": "Secteur des Enzymopathies UM-BEP-DBTP-IBP",
                    "Chu": "CHU de Grenoble-Alpes",
                    "Adresse": "CS 10217",
                    "Cp": "38043 Grenoble Cedex 9",
                    "Professeur": "Dr Vergnaud Sabrina",
                    "Tel": "Tel : 04 76 76 54 83 ou 04 76 76 59 05",
                    "Fax": "Fax : 04 76 76 56 08",
                    "Mail": "svergnaud@chu-grenoble.fr",

                    "Url": "http://biologie.chu-grenoble.fr/",
                    "Mode": "Buvard"
                },
                "geometry": {

                    "type": "Point",
                    "coordinates": [5.7423258, 45.2015191]
                }
            }

要添加 "iduronate" 标记:我单击 ID 为 "iduronate" 的复选框。如果我取消选中该复选框,它会隐藏我的标记。

$("#iduronate").click(function() {
        if (this.checked) {

            iduronate.addTo(clusterade);
        } else {
            clusterade.removeLayer(iduronate);

        }
    });

在地图上添加标记,显示自定义图标,并显示数据

var iduronate = L.geoJson(examenData, {
        filter: function(feature, layer) {
            return feature.properties.Examen == "iduronate";
        },
        onEachFeature: onEachFeature2,
        pointToLayer: function(feature, latlng) {

            return L.marker(latlng, {
                icon: iduronateIcon
            })
        }
    })

最后是我的过滤器示例

<div>
   <input type="checkbox" class="gaucher" id="iduronate" name="EnzymeDef_mps1[]">
   <label for="iduronate">Iduronate sulfatase </label>
<div>

很抱歉,我在这里尝试 post 我的代码,但是对于 "body" 来说太长了。所以我制作了一个 codepen 来在现场展示它。 感谢您的帮助!!

让我们假设您的数据集的简化版本,例如一个 GeoJSON FeatureCollection 包含医院中 clinics/departments 的点,其中属于同一家医院的两个(或更多)诊所共享相同的位置:

let clinics = {
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "properties": { "clinic": "cardio", "phone": "11 22 33 44 55" },
      "geometry": {
         "type": "Point", "coordinates": [5.74, 45.20]
      }
    },
    {
      "type": "Feature",
      "properties": { "clinic": "trauma", "phone": "66 77 88 99 00" },
      "geometry": {
         "type": "Point", "coordinates": [5.74, 45.20]
      }
    },
    {
      "type": "Feature",
      "properties": { "clinic": "neuro", "phone": "77 66 55 44 33" },
      "geometry": {
         "type": "Point", "coordinates": [6.12, 43.88]
      }
    } 
  ]
};

我的方法是手动循环上述 GeoJSON FeatureCollection,根据坐标索引点特征,并将它们的属性聚合到一个数组中,例如:

let clinicsByPosition = {};

for (let clinic of clinics.features) {
  // Let the index be the string representation of the coordinates array;
  // this is probably inefficient, but will suffice.
  // Note there are no sanity checks performed here (e.g. checking geometry type)
  let idx = clinic.geometry.coordinates.toString();

  // Does clinicsByPosition already have something in that index?
  if (clinicsByPosition[idx] === undefined) {
    // Create a new feature in that index
    // Initialize the properties of that new feature to an array with
    // one element, the properties of the clinic, and same geometry
    // than the clinic.
    clinicsByPosition[idx] = { 
      type: "Feature", 
      geometry: clinic.geometry, 
      properties: [clinic.properties]
    }
  } else {
    // Add the properties of the clinic to the already existing indexed
    // feature
    clinicsByPosition[idx].properties.push(clinic.properties);
  }
}

// Second pass: convert the "clinicsByPosition" data structure 
// into a GeoJSON FeatureCollection
let hospitals = {
  type:'FeatureCollection',
  features: []
}

for (let indexedClinicSet of Object.values(clinicsByPosition)) {
  hospitals.features.push(indexedClinicSet)
}

转换后,聚合数据集将如下所示:

let hospitals = {
  type: "FeatureCollection",
  features: [
    {
      type: "Feature",
      geometry: { type: "Point", coordinates: [5.74, 45.2] },
      properties: [
        { clinic: "cardio", phone: "11 22 33 44 55" },
        { clinic: "trauma", phone: "66 77 88 99 00" },
      ],
    },
    {
      type: "Feature",
      geometry: { type: "Point", coordinates: [6.12, 43.88] },
      properties: [{ clinic: "neuro", phone: "77 66 55 44 33" }],
    },
  ],
};

让我们将其放入带有一些信息弹出窗口的 Leaflet 中:

var hospitals = L.geoJson(hospitalsData,{
    onEachFeature: function(feat, marker) {
        // For this example, let the contents of the popup of a hospital marker
        // to be a concatenation of the data for all clinics in that hospital
        marker.bindPopup(feat.properties.map(function(clinicData){
            return clinicData.clinic + " - tlf " + clinicData.phone
        }).join("<br>"))
    }
}).addTo(map);

一个working example with that看起来还不错:

现在应该清楚了,同一坐标上的每组诊所只有 一个特征

现在可以以(恕我直言)合理的方式进行过滤。循环遍历 L.GeoJSON 实例中的医院标记,并循环遍历每个相关特征的属性,以查看是否满足其组件的 any 的可见性条件,例如:

function recalculateHospitalVisibility(){
    var cardioVisible = document.getElementById('cardio').checked;
    var traumaVisible = document.getElementById('trauma').checked;
    var neuroVisible = document.getElementById('neuro').checked;

    hospitals.eachLayer(function (marker) {
        // See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/some
        if (
            marker.feature.properties.some(function (clinic) {
                return (
                    (clinic.clinic === "cardio" && cardioVisible) ||
                    (clinic.clinic === "trauma" && traumaVisible) ||
                    (clinic.clinic === "neuro" && neuroVisible)
                );
            })
        ) {
            marker.addTo(map);
        } else {
            marker.remove();
        }
    });
}

Working example here。即使代码看起来有点复杂,示例数据也得到了简化(所以我的非医学大脑可以更好地处理它),迭代器和数据结构的使用有点繁重,并且可以进行优化,它应该让你走上正轨。