如何为Folium Draw Toolbar添加图层选择选项框?
协作地图项目完整解决方案
针对你的需求,以下是基于Folium和Draw插件的实现方案,包含图层选择下拉框、绘制元素关联图层、数据保存三个核心功能:
1. 创建基础地图与图层
首先初始化地图和三个目标图层,每个图层分配唯一名称用于后续关联:
import folium from folium.plugins import Draw from folium.elements import MacroElement # 初始化地图(坐标示例为利马,可根据需求修改) m = folium.Map(location=[-12.0464, -77.0428], zoom_start=12) # 创建三个业务图层 layer_mujeres = folium.FeatureGroup(name="Ubicacion de mujeres", show=True) layer_violencia = folium.FeatureGroup(name="Zona de Violencia", show=True) layer_diversas = folium.FeatureGroup(name="Poblaciones diversas", show=True) # 添加图层到地图并启用图层控制器 m.add_child(layer_mujeres) m.add_child(layer_violencia) m.add_child(layer_diversas) folium.LayerControl().add_to(m)
2. 添加图层选择下拉框与绘制逻辑
通过自定义MacroElement插入HTML和JS代码,实现绘制前选择图层,自动将标记/多边形添加到选中图层:
class LayerSelector(MacroElement): def __init__(self): super().__init__() self._template = """ {% macro script(this, kwargs) %} <!-- 图层选择UI --> <div style="position: fixed; top: 10px; right: 100px; z-index: 9999; background: #fff; padding: 8px 12px; border-radius: 6px; box-shadow: 0 2px 4px rgba(0,0,0,0.1);"> <label for="layer-picker" style="margin-right: 8px;">选择图层:</label> <select id="layer-picker" style="padding: 4px; border-radius: 4px; border: 1px solid #ddd;"> <option value="Ubicacion de mujeres">Ubicacion de mujeres</option> <option value="Zona de Violencia">Zona de Violencia</option> <option value="Poblaciones diversas">Poblaciones diversas</option> </select> </div> <!-- 绑定Draw插件的绘制事件 --> <script> const layerPicker = document.getElementById('layer-picker'); // 映射图层名称到实际图层对象 const targetLayers = { 'Ubicacion de mujeres': {{ this._parent.get_name() }}.getChild('Ubicacion de mujeres'), 'Zona de Violencia': {{ this._parent.get_name() }}.getChild('Zona de Violencia'), 'Poblaciones diversas': {{ this._parent.get_name() }}.getChild('Poblaciones diversas') }; // 监听绘制完成事件 {{ this._parent.get_name() }}.on('draw:created', function(e) { const drawnLayer = e.layer; const selectedLayerName = layerPicker.value; // 给绘制元素添加图层归属属性,方便后续识别 drawnLayer.feature.properties = { layer: selectedLayerName }; // 将元素添加到选中的图层 targetLayers[selectedLayerName].addLayer(drawnLayer); }); </script> {% endmacro %} """ # 添加图层选择器到地图 LayerSelector().add_to(m) # 配置Draw插件,只启用需要的绘制类型 Draw( draw_options={ 'marker': True, # 允许添加标记 'polygon': True, # 允许添加多边形 'polyline': False, 'rectangle': False, 'circle': False, 'circlemarker': False }, edit_options={'edit': False} # 可根据需求开启编辑功能 ).add_to(m)
3. 添加数据保存功能
同样通过MacroElement添加保存按钮,点击后导出所有绘制元素为GeoJSON格式:
class SaveMapData(MacroElement): def __init__(self): super().__init__() self._template = """ {% macro script(this, kwargs) %} <!-- 保存按钮UI --> <div style="position: fixed; top: 10px; right: 10px; z-index: 9999;"> <button onclick="exportMapData()" style="padding: 8px 16px; border-radius: 6px; background: #28a745; color: #fff; border: none; cursor: pointer;">保存数据</button> </div> <script> function exportMapData() { const allFeatures = []; // 遍历所有图层,收集绘制的要素 {% for layer in this._parent._children.values() %} if ({{ layer.get_name() }} instanceof L.FeatureGroup) { {{ layer.get_name() }}.eachLayer(function(layer) { if (layer.feature) { allFeatures.push(layer.feature); } }); } {% endfor %} // 构建标准GeoJSON对象 const geoJSON = { type: 'FeatureCollection', features: allFeatures }; // 创建下载链接 const dataStr = JSON.stringify(geoJSON, null, 2); const dataUri = 'data:application/json;charset=utf-8,' + encodeURIComponent(dataStr); const link = document.createElement('a'); link.href = dataUri; link.download = 'map-drawings.geojson'; link.click(); } </script> {% endmacro %} """ # 添加保存功能到地图 SaveMapData().add_to(m) # 生成最终的地图HTML文件 m.save('collaborative_map.html')
核心要点说明
- 图层选择框采用固定定位,悬浮在地图右上角,不影响地图操作
- 绘制元素会自动关联选中的图层,同时在要素属性中标记归属图层,便于后续数据分类
- 保存功能导出的GeoJSON是标准格式,可直接导入GIS工具或后端数据库
- 如果需要后端实时保存,可修改
exportMapData函数,通过AJAX将GeoJSON数据发送到你的后端接口
内容的提问来源于stack exchange,提问作者Victor Cubas
相关产品推荐
相关产品推荐

