根据在 select/dropdown 框中而不是复选框中选择的值动态获取和显示地图图层

Dynamically fetch and display map layers based on the value selected in a select/dropdown box instead of checkbox

我有大约 5 个地图图层作为单独的 json 文件。使用复选框单击动态获取和显示每个地图层文件。它工作得很好。我的代码如下所示。我还有另一个要求将这 5 个复选框更改为单个下拉列表。当我 select 来自下拉输入字段的特定值时,它必须显示其对应的图层。如果我 select 下拉列表中的另一个值,它必须删除以前 selected 的地图层并显示新 selected 值的相应层。是否可以在下拉菜单中做同样的事情?

<div id="inputParentId" />
<input type="checkbox" id="1" onClick="togglejsonLayer(this,'lay1');" />
Layer 1
<input type="checkbox" id="2" onClick="togglejsonLayer(this,'lay2');" />
Layer 2
<input type="checkbox" id="3" onClick="togglejsonLayer(this,'lay3');" />
Layer 3
<input type="checkbox" id="4" onClick="togglejsonLayer(this,'lay4');" />
Layer 4
<input type="checkbox" id="5" onClick="togglejsonLayer(this,'lay5');" />
Layer 5

<div id="map" style="height: 600px; width: 100%;"></div>

<script>
  const mbAttr = "";
  const mbUrl =
    "https://api.mapbox.com/styles/v1/{id}/tiles/{z}/{x}/{y}?access_token=xxxxxxxx";

  const streets = L.tileLayer(mbUrl, {
    id: "mapbox/streets-v11",
    tileSize: 512,
    zoomOffset: -1,
    attribution: mbAttr
  });

  const sattelite = L.tileLayer(mbUrl, {
    id: "mapbox/satellite-v9",
    tileSize: 512,
    zoomOffset: -1,
    attribution: mbAttr
  });

  const map = L.map("map", {
    center: [39.74739, -105],
    zoom: 12,
    layers: [streets]
  });

  var baseLayers = {
    Streets: streets,
    Sattelite: sattelite
  };
  L.control.layers(baseLayers).addTo(map);

  function onEachFeature(feature, layer) {
    var popupContent;
    if (feature.properties && feature.properties.popupContent) {
      popupContent = feature.properties.popupContent;
    }
    layer.bindPopup(popupContent);
  }

  async function getGeojson(checkbox, layerName) {
    if (layers[layerName]) {
      if (checkbox.checked) layers[layerName].addTo(map);
      else map.removeLayer(layers[layerName]);
      return;
    }

    const response = await fetch(`./${layerName}.json`);
    const geojson = await response.json();
    return geojson;
  }

  const layers = {};

  const togglejsonLayer = async (checkbox, layerName) => {
    const geojsonData = await getGeojson(checkbox, layerName);
    const geojson = L.geoJSON([geojsonData], {
      onEachFeature
    });

    const checkId = checkbox.id;
    if (checkbox.checked) {
      layers[layerName] = geojson;
      layers[layerName].addTo(map);
    } else map.removeLayer(layers[layerName]);
  };
</script>

您可以使用 Layer.Control,因为它的作用与 JRI 提到的相同,但由于您想要在地图之外实施,您可以使用以下方法:

你保持原来的样子,只是对缓存已经获取的层稍作改动

async function getGeojson(layerName) {
    const response = await fetch(`./${layerName}.json`);
    const geojson = await response.json();
    return geojson;
}

您可以有一个变量保存所有获取的图层,还有一个变量用于 add/remove 地图上的当前 selected 图层。一旦处于缓存模式而不是缓存模式,也可以重复使用 clearMap 函数来清空地图。

const layerCaching = {};
const currentDisplayedLayer = {};

document.getElementById("layers").onchange = (e) => {
  togglejsonLayer(e.target.value);
};

const clearMap = () => {
    Object.keys(currentDisplayedLayer).forEach((layer) => {
      map.removeLayer(currentDisplayedLayer[layer]);
      delete currentDisplayedLayer[layer];
    });
};

const togglejsonLayer = async (id) => {
  if (id === "0") return clearMap();

  const layerName = `lay${id}`;

  let geojson;
  if (!layerCaching[layerName]) {
     const geojsonData = await getGeojson(layerName);
     geojson = L.geoJSON([geojsonData], { onEachFeature });
  } else geojson = layerCaching[layerName];

  if (Object.keys(currentDisplayedLayer).length > 0) clearMap();

  currentDisplayedLayer[layerName] = geojson;
  if (!layerCaching[layerName]) layerCaching[layerName] = geojson;
  currentDisplayedLayer[layerName].addTo(map);
}

最后但并非最不重要的一点是,您可以 运行 一个 for 循环来动态构建 select 项目,因此如果您决定在将来使用约定的 laynumber 添加更多层,这将非常容易这样做。

<select name="layers" id="layers"></select>

const layersSelect = document.getElementById("layers");
layersSelect.add(new Option("Select Layer", "0"));
const arrayLength = Array.from(Array(5).keys());

arrayLength.forEach((_, id) => {
  layersSelect.add(new Option(`Layer ${id + 1}`, id + 1));
});

Demo