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

如何在Python代码中通过JS Leaflet扩展Folium功能(如测距)

没问题!既然Folium是Leaflet的Python封装,那咱们完全可以直接调用Leaflet的原生API来实现Folium没提供的功能,不管是计算坐标距离还是删除标记都可以搞定。下面给你具体的实现步骤和代码示例:

一、调用Leaflet.LatLng.distanceTo计算坐标距离

Leaflet的distanceTo方法可以直接计算两个经纬度点之间的球面距离(底层用的就是球面余弦定理),咱们只需要在Folium生成的HTML中插入自定义JavaScript代码,就能调用这个方法。

具体实现步骤:

  1. 先正常用Folium创建地图和标记;
  2. 编写自定义JS代码,获取Leaflet的地图实例和标记对象,调用distanceTo计算距离;
  3. 将这段JS代码插入到Folium生成的HTML中,再加载到QtWebEngineView里。

示例代码:

import folium
import io
from PyQt5 import QtWebEngineWidgets

# 假设你的起止坐标
lat_1, lng_1 = 32.5236, 54.0
lat_2, lng_2 = 33.0, 55.0

# 创建Folium地图
self.m = folium.Map(
    location=[32.5236, 54],
    tiles="Stamen terrain",
    zoom_start=5,
    control_scale=True,
    box_zoom=True
)
self.marker1 = folium.Marker((lat_1, lng_1)).add_to(self.m)
self.marker2 = folium.Marker((lat_2, lng_2)).add_to(self.m)
self.m.add_child(folium.LatLngPopup())

# 自定义JavaScript代码:调用Leaflet的distanceTo计算距离
custom_js = f"""
<script>
// 获取Leaflet地图实例(Folium会把地图对象挂载到window.map上)
const map = window.map;
// 获取所有标记对象(Folium生成的标记存在map._markers里)
const allMarkers = Object.values(map._markers);
const marker1 = allMarkers[0];
const marker2 = allMarkers[1];

// 计算两点距离,单位是米
const distance = marker1.getLatLng().distanceTo(marker2.getLatLng());
console.log('起止坐标距离:', Math.round(distance) + ' 米');

// 可选:在地图中间弹出距离信息
const distancePopup = L.popup()
  .setLatLng([{(lat_1 + lat_2)/2}, {(lng_1 + lng_2)/2}])
  .setContent(`<strong>两点距离</strong><br>${Math.round(distance)} 米`)
  .openOn(map);
</script>
"""

# 保存地图并插入自定义JS
self.data = io.BytesIO()
self.m.save(self.data, close_file=False)
html_content = self.data.getvalue().decode()
# 在</body>标签前插入JS,确保Leaflet已经加载完成
html_content = html_content.replace('</body>', custom_js + '</body>')

# 加载到QtWebEngineView
self.map = QtWebEngineWidgets.QWebEngineView(self.centralwidget)
self.map.setHtml(html_content)
二、借助Leaflet实现标记删除功能

Folium本身删除标记确实不太方便,但咱们可以用Leaflet的removeLayer方法来删除标记,同样通过自定义JS或者Python端调用JS来实现。

方法1:在地图上添加删除按钮(前端交互)

把这段JS加到上面的custom_js里,就能给地图加一个删除所有标记的按钮:

// 添加删除按钮控件
const deleteControl = L.control({position: 'topright'});
deleteControl.onAdd = function(map) {
  const btnDiv = L.DomUtil.create('div', 'leaflet-bar leaflet-control');
  btnDiv.innerHTML = '<button style="padding: 6px 8px; border: none; background: white; cursor: pointer;">删除所有标记</button>';
  btnDiv.onclick = function() {
    // 遍历所有标记并删除
    Object.values(map._markers).forEach(marker => {
      map.removeLayer(marker);
    });
  };
  return btnDiv;
};
deleteControl.addTo(map);

方法2:从Python端触发删除(Qt交互)

如果需要在Python代码里(比如用户点击GUI按钮时)删除标记,可以用QtWebEngine的runJavaScript方法执行删除逻辑:

# 假设这是你的GUI按钮点击事件处理函数
def on_delete_markers_clicked(self):
    self.map.page().runJavaScript("""
        const map = window.map;
        Object.values(map._markers).forEach(marker => {
            map.removeLayer(marker);
        });
    """)

思路总结

Folium生成的HTML本质就是一个Leaflet网页,所有Leaflet的原生API都能通过JavaScript调用。咱们的核心思路就是:

  • 要么在Folium保存地图后,修改HTML内容插入自定义JS;
  • 要么通过QtWebEngine的runJavaScript方法动态执行JS代码,实现和Leaflet地图的交互。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:40:33