Select 多个过滤器,仅显示具有共同特征的标记
Select multiple filters, display only markers that have common features
我有传单地图,已经可以使用了。目前,我有多个复选框过滤器(两张地图上总共有近 40 个):用户可以同时 select 多个标记。筛选器代表 "specialities",当我单击筛选器时,它会显示具有该专业的医院。所以在地图上,我可以有集群来显示具有多个专科的医院,以及显示具有一个专科的不同医院的单个标记。
- 如果用户点击过滤器 A,它会显示例如 5 个具有特征 A 的标记。
- 如果用户点击过滤器 B,它会显示 5 个具有特征 B 的标记。
- 当用户同时点击筛选器 A 和 B 时,它会显示 A + B,因此 10 个标记、单个标记和集群标记。
我想做什么:
每个单独的 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。即使代码看起来有点复杂,示例数据也得到了简化(所以我的非医学大脑可以更好地处理它),迭代器和数据结构的使用有点繁重,并且可以进行优化,它应该让你走上正轨。
我有传单地图,已经可以使用了。目前,我有多个复选框过滤器(两张地图上总共有近 40 个):用户可以同时 select 多个标记。筛选器代表 "specialities",当我单击筛选器时,它会显示具有该专业的医院。所以在地图上,我可以有集群来显示具有多个专科的医院,以及显示具有一个专科的不同医院的单个标记。
- 如果用户点击过滤器 A,它会显示例如 5 个具有特征 A 的标记。
- 如果用户点击过滤器 B,它会显示 5 个具有特征 B 的标记。
- 当用户同时点击筛选器 A 和 B 时,它会显示 A + B,因此 10 个标记、单个标记和集群标记。
我想做什么:
每个单独的 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。即使代码看起来有点复杂,示例数据也得到了简化(所以我的非医学大脑可以更好地处理它),迭代器和数据结构的使用有点繁重,并且可以进行优化,它应该让你走上正轨。