如何用Folium导出绘制区域内的标记点坐标?
如何导出Folium框选区域内的标记点坐标
Folium本身的局限与实现方案
Folium的Draw插件默认仅支持导出绘制的几何图形(矩形、多边形等),没有内置的「筛选区域内标记点」功能,但可以通过两种方式实现需求:
方案1:结合前端JavaScript扩展交互
在Folium地图中注入自定义JS代码,监听Draw插件的绘制完成事件,获取区域边界后遍历标记点,通过空间判断筛选出区域内的点并导出:
import folium from folium.plugins import Draw, MarkerCluster import pandas as pd import json # 初始化地图 m = folium.Map([25.143591,55.193512], zoom_start=10) marker_cluster = MarkerCluster(control=False).add_to(m) # 模拟测试数据(替换为你的data_df) data_df = pd.DataFrame({ 'latitude': [25.1, 25.2, 25.15], 'longitude': [55.1, 55.2, 55.15] }) # 添加标记点并绑定坐标属性 marker_ids = [] for idx, row in data_df.iterrows(): loc = row[['latitude','longitude']].tolist() marker = folium.Marker(loc, id=f"marker-{idx}") # 把坐标存在弹窗内容里,供JS读取 marker.add_child(folium.Popup(json.dumps({'lat': loc[0], 'lon': loc[1]}))) marker.add_to(marker_cluster) marker_ids.append(f"marker-{idx}") # 添加Draw控件 draw = Draw( export=True, filename='data.geojson', position='topleft', draw_options={'polyline': False, 'circlemarker': False, 'polygon': False, 'marker': False}, edit_options={'poly': {'allowIntersection': False}}) draw.add_to(m) # 注入自定义JS代码 custom_js = f""" // 监听绘制完成事件 map.on('draw:created', function(e) {{ var layer = e.layer; var bounds = layer.getBounds(); // 获取绘制区域的边界 // 收集区域内的标记点坐标 var pointsInArea = []; {','.join([f"var marker{idx} = document.getElementById('{mid}'); if (marker{idx}) {{ var loc = JSON.parse(marker{idx}.getPopup().getContent()); if (bounds.contains(L.latLng(loc.lat, loc.lon))) {{ pointsInArea.push(loc); }}" for idx, mid in enumerate(marker_ids)])} // 导出为JSON文件 if (pointsInArea.length > 0) {{ var dataStr = "data:text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(pointsInArea)); var downloadAnchor = document.createElement('a'); downloadAnchor.setAttribute("href", dataStr); downloadAnchor.setAttribute("download", "points_in_area.json"); document.body.appendChild(downloadAnchor); downloadAnchor.click(); downloadAnchor.remove(); }} }}); """ folium.Element(custom_js).add_to(m.get_root().html) m
方案2:后端空间筛选(非实时交互)
先让用户用Draw插件导出绘制的区域GeoJSON,再用Python的空间分析库筛选区域内的点:
import geopandas as gpd from shapely.geometry import Point # 读取标记点数据 points_gdf = gpd.GeoDataFrame( data_df, geometry=gpd.points_from_xy(data_df.longitude, data_df.latitude), crs="EPSG:4326" ) # 读取导出的区域GeoJSON文件 area_gdf = gpd.read_file("data.geojson") # 筛选区域内的点 points_in_area = gpd.sjoin(points_gdf, area_gdf, predicate="within") # 导出结果为CSV points_in_area[['latitude', 'longitude']].to_csv("points_in_area.csv", index=False)
替代库推荐
如果需要更原生的交互式点筛选能力,可以考虑以下库:
1. ipyleaflet
基于ipywidgets的交互式地图库,支持在Python端直接监听绘制事件,无需编写JS:
from ipyleaflet import Map, Marker, DrawControl, LayerGroup import pandas as pd from shapely.geometry import shape, Point # 初始化地图 m = Map(center=(25.143591,55.193512), zoom=10) marker_group = LayerGroup() m.add_layer(marker_group) # 添加标记点 for _, row in data_df.iterrows(): marker = Marker(location=(row['latitude'], row['longitude'])) marker_group.add_layer(marker) # 添加绘制控件 draw_control = DrawControl( circlemarker={}, polyline={}, marker={}, polygon={}, rectangle={'shapeOptions': {'color': '#00FF00'}} ) m.add_control(draw_control) # 监听绘制完成事件,筛选并导出点 def handle_draw(action, geo_json): area = shape(geo_json['geometry']) points_in_area = [] for marker in marker_group.layers: point = Point(marker.location[1], marker.location[0]) if area.contains(point): points_in_area.append(marker.location) # 导出为CSV pd.DataFrame(points_in_area, columns=['latitude', 'longitude']).to_csv("points_in_area.csv", index=False) draw_control.on_draw(handle_draw) m
2. Plotly Dash
适合构建完整的Web应用,支持复杂交互逻辑,用户绘制区域后可直接触发筛选并提供下载按钮,适合需要部署成Web服务的场景。
内容的提问来源于stack exchange,提问作者RalphCh97
相关产品推荐
相关产品推荐

