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不一致。
- 页面首次加载后,第一次切换地图类型成功,但第二次切换失效:
- 打开页面
- 选择“Google Sat”单选框,地图切换成功
- 选择“Google Hybrid”单选框,地图切换成功
- 再次选择“Google Sat”单选框,地图无法切换
备注:使用Leaflet默认图层控件时不会遇到这些问题。
解决方案
问题1:刷新后单选框状态与地图不一致
这是浏览器表单自动填充缓存导致的,两种解决方式:
- 给所有单选框添加
autocomplete="off"属性,禁止浏览器缓存选中状态:
<input class="form-check-input" type="radio" name="radiomaptype" id="mapTypeToOSM" value="osm" checked autocomplete="off">
(其余单选框同样添加autocomplete="off")
- 页面加载时强制同步单选框与默认图层状态,在地图初始化后添加:
$('#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
相关产品推荐
相关产品推荐

