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

如何将ipyleaflet DrawControl的面积计算单位从ha改为km2?

将ipyleaflet DrawControl的面积单位从公顷改为平方千米

ipyleaflet的DrawControl本身没有直接配置面积单位的选项,但可以通过两种方式实现单位转换:

方法一:自定义JavaScript覆盖前端计算逻辑

ipyleaflet基于Leaflet.draw开发,我们可以直接覆盖Leaflet.draw中负责生成面积文本的函数,将默认的公顷转换为平方千米。

示例代码:

from ipyleaflet import Map, basemaps, basemap_to_tiles, DrawControl, JavascriptLink

watercolor = basemap_to_tiles(basemaps.Stadia.StamenTerrain)
m = Map(layers=(watercolor, ), center=(50, 354), zoom=5)

draw_control = DrawControl()
draw_control.polyline =  {
    "shapeOptions": {
        "color": "#6bc2e5",
        "weight": 8,
        "opacity": 1.0
    }
}
draw_control.polygon = {
    "shapeOptions": {
        "fillColor": "#6be5c3",
        "color": "#6be5c3",
        "fillOpacity": 1.0
    },
    "drawError": {
        "color": "#dd253b",
        "message": "Oups!"
    },
    "allowIntersection": False
}
draw_control.circle = {
    "shapeOptions": {
        "fillColor": "#efed69",
        "color": "#efed69",
        "fillOpacity": 1.0
    }
}
draw_control.rectangle = {
    "shapeOptions": {
        "fillColor": "#fca45d",
        "color": "#fca45d",
        "fillOpacity": 1.0
    }
}

m.add(draw_control)

# 注入自定义JS修改面积显示
js_code = """
// 替换Leaflet.draw的面积文本生成函数
L.Draw.Polyline.prototype._getMeasurementString = function(area) {
    if (area > 0) {
        // Leaflet内部计算的面积单位是平方米,转换为平方千米(1km² = 1e6 m²)
        const km2 = area / 1000000;
        return km2.toFixed(2) + ' km²';
    } else {
        // 非多边形显示长度(米)
        const meters = this._getTooltipDistance();
        return meters.toFixed(0) + ' m';
    }
};
"""

JavascriptLink(target=m, code=js_code)

m

这段代码会在绘制多边形时,实时将面积转换为平方千米并显示,无需额外后端计算。

方法二:Python监听绘制事件计算并更新显示

通过监听DrawControl的draw:created事件,获取绘制的GeoJSON数据,在Python端计算面积(注意要转换到等面积坐标系保证精度),再通过JS更新地图上的提示文本。

示例代码:

from ipyleaflet import Map, basemaps, basemap_to_tiles, DrawControl
from shapely.geometry import shape
import pyproj

watercolor = basemap_to_tiles(basemaps.Stadia.StamenTerrain)
m = Map(layers=(watercolor, ), center=(50, 354), zoom=5)

draw_control = DrawControl()
draw_control.polyline =  {
    "shapeOptions": {
        "color": "#6bc2e5",
        "weight": 8,
        "opacity": 1.0
    }
}
draw_control.polygon = {
    "shapeOptions": {
        "fillColor": "#6be5c3",
        "color": "#6be5c3",
        "fillOpacity": 1.0
    },
    "drawError": {
        "color": "#dd253b",
        "message": "Oups!"
    },
    "allowIntersection": False
}
draw_control.circle = {
    "shapeOptions": {
        "fillColor": "#efed69",
        "color": "#efed69",
        "fillOpacity": 1.0
    }
}
draw_control.rectangle = {
    "shapeOptions": {
        "fillColor": "#fca45d",
        "color": "#fca45d",
        "fillOpacity": 1.0
    }
}

m.add(draw_control)

def calculate_area_km2(geo_json):
    # 将GeoJSON转换为shapely几何对象
    geom = shape(geo_json['geometry'])
    # 定义坐标系转换:WGS84(经纬度)转等面积投影(EPSG:6933适合全球范围)
    transformer = pyproj.Transformer.from_crs(
        "EPSG:4326", "EPSG:6933", always_xy=True
    )
    # 转换几何对象到等面积坐标系
    geom_proj = shape(transformer.transform(*geom.exterior.xy))
    # 计算面积(平方米)转平方千米
    area_km2 = geom_proj.area / 1000000
    return round(area_km2, 2)

def update_area_display(event):
    geo_json = event['geo_json']
    if geo_json['geometry']['type'] in ['Polygon', 'MultiPolygon']:
        area_km2 = calculate_area_km2(geo_json)
        # 执行JS更新地图上的提示框文本
        update_js = f"""
        const tooltip = document.querySelector('.leaflet-draw-tooltip');
        if (tooltip) {{
            tooltip.textContent = '{area_km2} km²';
        }}
        """
        m.execute_js(update_js)
        # 同时在Python控制台输出结果
        print(f"区域面积:{area_km2} km²")

# 绑定绘制完成事件
draw_control.on_draw_created(update_area_display)

m

这种方法适合需要对面积数据做后续处理的场景,计算精度更高。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 04:35:31