You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Leaflet自定义控件切换底图/地图类型的问题求助

Leaflet自定义图层切换控件问题求助

我制作了如下自定义工具栏:
查看“红色圆圈”

以下是我的HTML代码:

<div class="collapse map-custombar-collapse-left" id="listMapBaseControl">
    <ul class="ul-map-custombar-collapse-left">
        <li class="li-map-custombar-collapse-left">
            <div class="form-check">
            <input class="form-check-input" type="radio" name="radiomaptype" id="mapTypeToOSM" value="osm" checked>
            <label class="form-check-label" for="mapTypeToOSM">OSM Map</label>
            </div>
        </li>
        <li class="li-map-custombar-collapse-left">
            <div class="form-check">
            <input class="form-check-input" type="radio" name="radiomaptype" id="mapTypeToStreet" value="streetmap">
            <label class="form-check-label" for="mapTypeToStreet">Google Street</label>
            </div>
        </li>
        <li class="li-map-custombar-collapse-left">
            <div class="form-check">
            <input class="form-check-input" type="radio" name="radiomaptype" id="mapTypeToTraffic" value="trafficmap">
            <label class="form-check-label" for="mapTypeToTraffic">Google Traffic</label>
            </div>
        </li>
        <li class="li-map-custombar-collapse-left">
            <div class="form-check">
            <input class="form-check-input" type="radio" name="radiomaptype" id="mapTypeToSatellite" value="satellitemap">
            <label class="form-check-label" for="mapTypeToSatellite">Satellite Map</label>
            </div>
        </li>
        <li class="li-map-custombar-collapse-left">
            <div class="form-check">
            <input class="form-check-input" type="radio" name="radiomaptype" id="mapTypeToHybrid" value="hybridmap">
            <label class="form-check-label" for="mapTypeToHybrid">Hybrid Map</label>
            </div>
        </li>
    </ul>
</div>
<div id="map" style="height:100%;"></div>

我的JS代码如下:

var googleStreets = L.tileLayer('http://{s}.google.com/vt/lyrs=m&x={x}&y={y}&z={z}',{
        maxZoom: 20,
        subdomains:['mt0','mt1','mt2','mt3']
});
var googleHybrid = L.tileLayer('http://{s}.google.com/vt/lyrs=s,h&x={x}&y={y}&z={z}',{
        maxZoom: 20,
        subdomains:['mt0','mt1','mt2','mt3']
});
var googleSat = L.tileLayer('http://{s}.google.com/vt/lyrs=s&x={x}&y={y}&z={z}',{
        maxZoom: 20,
        subdomains:['mt0','mt1','mt2','mt3']
});
var googleTraffic = L.tileLayer('https://{s}.google.com/vt/lyrs=m@221097413,traffic&x={x}&y={y}&z={z}', {
        maxZoom: 20,
        minZoom: 2,
        subdomains: ['mt0', 'mt1', 'mt2', 'mt3'],
});
var osm = L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
    maxZoom: 20,
    attribution: '© OpenStreetMap'
});

var map = L.map('map', {
    center: [-5.368029,112.005921],
    zoom: 5,
    layers: [osm]
});

var baseMaps = {
    "OSM": osm,
    "Street": googleStreets,
    "Traffic": googleTraffic,
    "Satellite": googleSat,
    "Hybrid": googleHybrid
};
var overlays =  {//add any overlays here
};
//var layerControl = L.control.layers(baseMaps,overlays,{position:'bottomleft'}).addTo(map); Hidden default control

$('input[type=radio][name=radiomaptype]').on('change', function() {
  switch ($(this).val()) {
    case 'osm':
      baseMaps["OSM"].addTo(map);
      break;
    case 'streetmap':
      baseMaps["Street"].addTo(map);
      break;
    case 'trafficmap':
      baseMaps["Traffic"].addTo(map);
      break;
    case 'satellitemap':
      baseMaps["Satellite"].addTo(map);
      break;
    case 'hybridmap':
      baseMaps["Hybrid"].addTo(map);
      break;
      
    default:
      baseMaps["OSM"].addTo(map);
      break;
  }
});

我遇到两个问题:

  • 刷新页面后,地图会切回默认的OSM类型,但单选框仍保持上次选中的状态(比如之前选了“Satellite Map”),和HTML里设置的默认选中OSM不一致。
  • 页面首次加载后,第一次切换地图类型成功,但第二次切换失效:
    1. 打开页面
    2. 选择“Google Sat”单选框,地图切换成功
    3. 选择“Google Hybrid”单选框,地图切换成功
    4. 再次选择“Google Sat”单选框,地图无法切换

备注:使用Leaflet默认图层控件时不会遇到这些问题。
查看“黑色圆圈”


解决方案

问题1:刷新后单选框状态与地图不一致

这是浏览器表单自动填充缓存导致的,两种解决方式:

  1. 给所有单选框添加autocomplete="off"属性,禁止浏览器缓存选中状态:
<input class="form-check-input" type="radio" name="radiomaptype" id="mapTypeToOSM" value="osm" checked autocomplete="off">

(其余单选框同样添加autocomplete="off")

  1. 页面加载时强制同步单选框与默认图层状态,在地图初始化后添加:
$('#mapTypeToOSM').prop('checked', true);

问题2:第二次切换地图类型失效

原因是每次切换仅添加新图层,旧图层未被移除,重复添加同一图层不会生效(图层已在地图上)。修改切换逻辑:

方式1:移除所有基础图层后添加目标图层

$('input[type=radio][name=radiomaptype]').on('change', function() {
  // 移除所有基础图层
  Object.values(baseMaps).forEach(layer => {
    map.removeLayer(layer);
  });
  
  // 添加选中的图层
  switch ($(this).val()) {
    case 'osm':
      baseMaps["OSM"].addTo(map);
      break;
    case 'streetmap':
      baseMaps["Street"].addTo(map);
      break;
    case 'trafficmap':
      baseMaps["Traffic"].addTo(map);
      break;
    case 'satellitemap':
      baseMaps["Satellite"].addTo(map);
      break;
    case 'hybridmap':
      baseMaps["Hybrid"].addTo(map);
      break;
      
    default:
      baseMaps["OSM"].addTo(map);
      break;
  }
});

方式2:维护当前活跃图层,仅移除当前图层

let currentBaseLayer = osm; // 初始为默认图层

$('input[type=radio][name=radiomaptype]').on('change', function() {
  let targetLayer;
  switch ($(this).val()) {
    case 'osm':
      targetLayer = baseMaps["OSM"];
      break;
    case 'streetmap':
      targetLayer = baseMaps["Street"];
      break;
    case 'trafficmap':
      targetLayer = baseMaps["Traffic"];
      break;
    case 'satellitemap':
      targetLayer = baseMaps["Satellite"];
      break;
    case 'hybridmap':
      targetLayer = baseMaps["Hybrid"];
      break;
      
    default:
      targetLayer = baseMaps["OSM"];
      break;
  }
  
  // 切换图层
  map.removeLayer(currentBaseLayer);
  targetLayer.addTo(map);
  currentBaseLayer = targetLayer;
});

内容的提问来源于stack exchange,提问作者dvaa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 06:47:02