nicegui地图总结

这个问题困扰我两周,总算找到解决的办法,我看了这个完成了项目,虽说不难吧,但也耗费了很大的精力去做这件事,我一直坚持纯python开发,至于用这个架构原因就不用我多说了,对于和我一样遇到类似的问题,看了这个文章受到启发,解决自己项目难题。

一,地图基础

这个元素是Leaflet JavaScript库的包装器。

  • center: 地图的初始中心位置(纬度/经度,默认值:(0.0, 0.0))

  • zoom: 地图的初始缩放级别(默认值:13)

  • draw_control: 是否显示绘图工具栏(默认值:False)

  • options: 传递给Leaflet地图的其他选项(默认值:{})

python 复制代码
from nicegui import ui

m = ui.leaflet(center=(51.505, -0.09))
ui.label().bind_text_from(m, 'center', lambda center: f'Center: {center[0]:.3f}, {center[1]:.3f}')
ui.label().bind_text_from(m, 'zoom', lambda zoom: f'Zoom: {zoom}')

with ui.grid(columns=2):
    ui.button('London', on_click=lambda: m.set_center((51.505, -0.090)))
    ui.button('Berlin', on_click=lambda: m.set_center((52.520, 13.405)))
    ui.button(icon='zoom_in', on_click=lambda: m.set_zoom(m.zoom + 1))
    ui.button(icon='zoom_out', on_click=lambda: m.set_zoom(m.zoom - 1))

ui.run()

二、多点经纬度坐标和一点经纬度坐标

默认的地图样式是OpenStreetMap。您可以在 https://leaflet-extras.github.io/leaflet-providers/preview/ 找到更多的地图样式。每次调用tile_layer都会叠加在前面的图层上。因此,如果您想更改地图样式,必须先移除默认的样式。
一点标记

python 复制代码
from nicegui import events, ui

BEIJING_CENTER = (39.904200, 116.407400)
ui.add_head_html('<style>.nicegui-content { max-width: none !important; padding: 0; }</style>')

with ui.column().classes('w-full p-4 gap-4'):
    m = ui.leaflet(center=BEIJING_CENTER, zoom=10).classes('w-full h-[600px]')
    coord_label = ui.label('点击地图查看坐标').classes('text-lg')

# 用于保存当前标记的引用
current_marker = None

def handle_click(e: events.GenericEventArguments):
    global current_marker
    
    lat = e.args['latlng']['lat']
    lng = e.args['latlng']['lng']
    lat_rounded = round(lat, 6)
    lng_rounded = round(lng, 6)
    
    # 如果已有标记,先移除它
    if current_marker is not None:
        m.remove_layer(current_marker)
    
    # 添加新标记并保存引用
    current_marker = m.marker(latlng=(lat_rounded, lng_rounded))
    
    coord_label.set_text(f"最新标记位置 → 纬度: {lat_rounded:.6f}, 经度: {lng_rounded:.6f}")

m.on('map-click', handle_click)

ui.run()
python 复制代码
from nicegui import ui

ui.echart({
    'toolbox': {'feature': {'brush': {'type': ['rect']}}},
    'brush': {},
    'xAxis': {'type': 'category'},
    'yAxis': {'type': 'value'},
    'series': [{'type': 'line', 'data': [1, 2, 3]}],
}).on('chart:selectchanged', lambda e: label.set_text(
    f'Selected point {e.args["fromActionPayload"]["dataIndexInside"]}'
))
label = ui.label()

ui.run()

多点标记

python 复制代码
from nicegui import events, ui

BEIJING_CENTER = (39.904200, 116.407400)
ui.add_head_html('<style>.nicegui-content { max-width: none !important; padding: 0; }</style>')

with ui.column().classes('w-full p-4 gap-4'):
    m = ui.leaflet(center=BEIJING_CENTER, zoom=10).classes('w-full h-[600px]')
    coord_label = ui.label('点击地图查看坐标').classes('text-lg whitespace-pre')

# 用于累积坐标文本
coordinates_history = []

def handle_click(e: events.GenericEventArguments):
    lat = e.args['latlng']['lat']
    lng = e.args['latlng']['lng']
    lat_rounded = round(lat, 6)
    lng_rounded = round(lng, 6)
    
    # 添加新标记(保留所有)
    m.marker(latlng=(lat_rounded, lng_rounded))
    
    # 记录坐标
    coordinates_history.append(f"({lat_rounded:.6f}, {lng_rounded:.6f})")
    if len(coordinates_history) > 100:
        coordinates_history.pop(0)  # 移除最旧的
    
    # 更新标签:每行一个坐标
    coord_label.set_text('\n'.join(coordinates_history))

m.on('map-click', handle_click)

ui.run()

三、标记

您可以使用marker在地图上添加标记。center参数是一个包含纬度和经度的元组。这个演示通过点击地图来添加标记。请注意,"map-click"事件是指地图对象的点击事件,而"click"事件是指容器div的点击事件。

python 复制代码
from nicegui import events, ui

m = ui.leaflet(center=(51.505, -0.09))

def handle_click(e: events.GenericEventArguments):
    lat = e.args['latlng']['lat']
    lng = e.args['latlng']['lng']
    m.marker(latlng=(lat, lng))
m.on('map-click', handle_click)

ui.run()
python 复制代码
<nicegui.elements.leaflet.Leaflet at 0x7f87d5dbf6d0>

四、标记后移动

您可以使用move方法移动标记。

python 复制代码
from nicegui import ui

m = ui.leaflet(center=(51.505, -0.09))
marker = m.marker(latlng=m.center)
ui.button('Move marker', on_click=lambda: marker.move(51.51, -0.09))

ui.run()
python 复制代码
<nicegui.elements.button.Button at 0x7f87d596e750>

五、矢量图层

Leaflet支持一系列矢量图层,如圆形、多边形等。这些可以使用generic_layer方法添加。我们欢迎任何关于添加更多特定图层以简化使用的pull请求。

python 复制代码
from nicegui import ui

m = ui.leaflet(center=(51.505, -0.09)).classes('h-32')
m.generic_layer(name='circle', args=[m.center, {'color': 'red', 'radius': 300}])

ui.run()
python 复制代码
GenericLayer(leaflet=<nicegui.elements.leaflet.Leaflet object at 0x7f87d5db0f90>, id='205b53bd-e7f1-421c-ba93-7cb7471b4804', name='circle', args=[(51.505, -0.09), {'color': 'red', 'radius': 300}])

六、平移和缩放

Leaflet中有多种选项可以配置地图。这个演示禁用了平移和缩放控件。

python 复制代码
from nicegui import ui

options = {
    'zoomControl': False,
    'scrollWheelZoom': False,
    'doubleClickZoom': False,
    'boxZoom': False,
    'keyboard': False,
    'dragging': False,
}
ui.leaflet(center=(51.505, -0.09), options=options)

# ui.run()
python 复制代码
<nicegui.elements.leaflet.Leaflet at 0x7f87d5dcff90>

七、地图上绘制

您可以启用一个工具栏在地图上绘制。可以使用draw_control配置工具栏。这个演示通过点击地图添加标记和多边形。

python 复制代码
from nicegui import events, ui

def handle_draw(e: events.GenericEventArguments):
    if e.args['layerType'] == 'marker':
        m.marker(latlng=(e.args['layer']['_latlng']['lat'],
                         e.args['layer']['_latlng']['lng']))
    if e.args['layerType'] == 'polygon':
        m.generic_layer(name='polygon', args=[e.args['layer']['_latlngs']])

draw_control = {
    'draw': {
        'polygon': True,
        'marker': True,
        'circle': False,
        'rectangle': False,
        'polyline': False,
        'circlemarker': False,
    },
    'edit': False,
}
m = ui.leaflet(center=(51.505, -0.09), zoom=13, draw_control=draw_control)
m.on('draw:created', handle_draw)

ui.run()
python 复制代码
<nicegui.elements.leaflet.Leaflet at 0x7f87d5dd9390>

八、运行地图方法

您可以使用run_map_method方法运行Leaflet地图对象的方法。这个演示展示了如何将地图适配到整个世界。

python 复制代码
from nicegui import ui

m = ui.leaflet(center=(51.505, -0.09)).classes('h-32')
ui.button('Fit world', on_click=lambda: m.run_map_method('fitWorld'))

ui.run()
python 复制代码
<nicegui.elements.button.Button at 0x7f87d5dd4350>

九、运行地图图层

您可以使用run_layer_method方法运行Leaflet图层对象的方法。这个演示展示了如何更改标记的透明度或更改其图标。

python 复制代码
from nicegui import ui

m = ui.leaflet(center=(51.505, -0.09)).classes('h-32')
marker = m.marker(latlng=m.center)
ui.button('Hide', on_click=lambda: marker.run_method('setOpacity', 0.3))
ui.button('Show', on_click=lambda: marker.run_method('setOpacity', 1.0))

icon = 'L.icon({iconUrl: "http://leafletjs.com/examples/custom-icons/leaf-green.png"})'
ui.button('Change icon', on_click=lambda: marker.run_method(':setIcon', icon))

ui.run()
python 复制代码
<nicegui.elements.button.Button at 0x7f87d5ddba90>

十、等待初始化

您可以使用initialized方法等待地图初始化。当您想在创建地图后立即运行像适应边界这样的方法时,这是必要的。

python 复制代码
from nicegui import ui

m = ui.leaflet(zoom=5)
central_park = m.generic_layer(name='polygon', args=[[
    (40.767809, -73.981249),
    (40.800273, -73.958291),
    (40.797011, -73.949683),
    (40.764704, -73.973741),
]])

async def fit_bounds():
    await m.initialized()
    bounds = await central_park.run_method('getBounds')
    m.run_map_method('fitBounds', [bounds['_southWest'], bounds['_northEast']])

# 使用一次性定时器(延迟 0 秒),触发异步函数
ui.timer(0, fit_bounds, once=True)

ui.run()

相信看了这个,对项目中遇到用地图,就会启发,做出产品需要的样子。

相关推荐
北京盟通科技官方账号2 小时前
工业通讯底层对齐:EtherNet/IP Class 1 连接中的 32-bit Header 与内存映射逻辑
服务器·网络·网络协议·自动化·制造
@淡 定2 小时前
消息队列使用场景
网络
Tom4i2 小时前
【网络优化】Android 如何监听系统网络连接成功
android·网络
不易思不逸2 小时前
SAM2 测试
人工智能·python
趣知岛4 小时前
智能家居与物联网项目实战全指南:从架构设计到落地部署
python·物联网·智能家居
龘龍龙4 小时前
Python基础(八)
开发语言·python
kkce4 小时前
vsping 推出海外检测节点的核心目的
大数据·网络·人工智能
Joy T4 小时前
【PE 最终章】思维链、自洽性与 Prompt 安全防御指南
网络·prompt·prompt engineer·提示词工程
一世琉璃白_Y5 小时前
Ubuntu(VMware)虚拟机网络异常排查与解决方案
linux·网络·ubuntu