MapLibreGL 如何按特征过滤?

问题描述 投票:0回答:1

我正在寻找一个助手来向我的地图添加过滤器。 我指定我使用 MapLibreGL 作为我的地图,但也以 Mapbox 教程为基础,因为它们适用

我成功创建了一种商店定位器,其中标记按簇分组。

所以我混合了这个教程这个,结果还可以。

我的所有标记列表位于左侧,当我单击列表元素时,地图会放大到相应的标记并显示弹出窗口。这次当我单击标记时,列表会快速滚动到相应的项目。

我的地图显示机构的名称、地址、地区、电话号码、电子邮件等。 我现在想创建一个过滤器块(复选框)以允许我按“区域”功能进行过滤。总共大约有十个区域。目标是当点击某个区域时,仅显示相应的标记

我阅读了本页处理过滤器,但我根本不知道如何实现它。

页面“通过切换列表过滤符号”和“filter-within-layer/”也对我没有帮助。

我有点初学者,因为我在使用语法并将其应用到我的代码中时遇到了困难

当我遵循 mapBox 集群教程时,我已经有了

filter: ['has', 'point_count'],
的三层,所以我不明白如何在“区域”功能上添加过滤器,如 here 中类似问题中所述

   <div>
      <input id="region1" type="checkbox" />
      <label for="region1">Region One</label>
    </div>
    <div>
      <input id="region2" type="checkbox" />
      <label for="region2">Region 2</label>
    </div>
    function getSelectedRegions() {
     const selectedRegions = [];
     const regionCheckboxes = 
     document.querySelectorAll('input[type=checkbox]:checked');
      regionCheckboxes.forEach(checkbox => 
      selectedRegions.push(checkbox.id));
      return selectedRegions;
    }
 
    function filterMarkers() {
     const selectedRegions = getSelectedRegions();
     const mapSource = map.getSource('places');
     if (selectedRegions.length === 0) {
       setAllMarkersVisible(mapSource); 
     return;
    }
   mapSource.setData({
     ...stores,
      features: stores.features.filter(feature => 
      selectedRegions.includes(feature.properties.region))
    });
   }
 
   function setAllMarkersVisible(mapSource) {
     mapSource.setData(stores); 
   }

我已经从https://www.devgem.io/posts/how-to-implement-region-based-filters-in-a-maplibregl-map-with-clusters-and-markers

实现了此代码

这正是我正在寻找的。但是,当单击任何复选框时,它会清除我的所有标记,但不会按区域进行过滤。

这里有什么问题吗?我希望当单击“region1”复选框时仅显示相应的标记。

这是创建我的地图的基本数据:

     map.on('load', () => {
          map.addSource('places', {
            'type': 'geojson',
            'data': stores,
            'cluster': true,
            'clusterMaxZoom': 14, // Max zoom to cluster points on
            'clusterRadius': 50
          });
  
          
          // addMarkers();
          map.addLayer({
          id: 'clusters',
          type: 'circle',
          source: 'places',
          filter: ['has', 'point_count'],
          paint: {
     
          'circle-color': [
          'step',
          ['get', 'point_count'],
          '#525CA3',
          100,
          '#525CA3',
          750,
          '#525CA3'
          ],
          'circle-radius': [
          'step',
          ['get', 'point_count'],
          20,
          100,
          30,
          750,
          40
          ]
          }
          });
   
          map.addLayer({
          id: 'cluster-count',
          type: 'symbol',
          source: 'places',
          filter: ['has', 'point_count'],
          layout: {
          'text-field': '{point_count_abbreviated}',
          'text-font': ['Open Sans Light'],
          'text-size': 12,
          "icon-image": "{marker-symbol}",
          "icon-size": 0.20
          },
          paint: {
      "text-color": "#ffffff"
    }
          });
  
   
          map.addLayer({
          id: 'unclustered-point',
          type: 'circle',
          source: 'places',
          filter: ['!', ['has', 'point_count']],
          paint: {
          'circle-color': '#525CA3',
          'circle-radius': 15,
          'circle-stroke-width': 1,
          'circle-stroke-color': '#fff'
          }
          });
filter mapbox maplibre-gl
1个回答
0
投票

最终,最后提出的代码很好。事实上,它使用复选框的 ID,这意味着标签的文本必须相同。这在大多数情况下并不合适,因为您不像编写 ID 名称那样编写标签文本。所以解决方案是瞄准标签,这样就可以了

function getLabel(id) {
  return $("#"+id).next("label").html();
 }
function getSelectedRegions() {

  const selectedRegions = [];
  const regionCheckboxes = 
  document.querySelectorAll('input[type=checkbox]:checked');
   regionCheckboxes.forEach(checkbox => 
   selectedRegions.push(getLabel(checkbox.id)));
   return selectedRegions; 
 }
© www.soinside.com 2019 - 2024. All rights reserved.