使用Bokeh绘制OSM瓦片图时能否显示随缩放层级变化的比例尺?
Bokeh目前确实没有内置的OSM瓦片地图比例尺组件,你可以通过注解+自定义逻辑实现符合需求的动态比例尺,以下是可行方案:
方案1:固定比例尺实现(适合单缩放层级场景)
核心逻辑是基于Web墨卡托(EPSG:3857)投影的距离换算规则,用Bokeh自带的注解组件拼接比例尺:
- Web墨卡托坐标的单位为米,赤道处坐标差与实际距离完全匹配,高纬度区域需要乘以
cos(中心纬度 * π / 180)做修正 - 用
BoxAnnotation绘制比例尺的条形背景、填充条,用Label添加距离文本标注
示例代码如下:
from bokeh.plotting import figure, show from bokeh.tile_providers import get_provider, Vendors from bokeh.models import BoxAnnotation, Label import math # 初始化瓦片图 p = figure(x_axis_type="mercator", y_axis_type="mercator") tile_provider = get_provider(Vendors.OSM) p.add_tile(tile_provider) # 假设当前地图中心纬度为30度,计算修正系数 center_lat = 30 correction = math.cos(math.radians(center_lat)) # 设定比例尺对应实际长度1000米,计算坐标下的长度 scale_actual_m = 1000 scale_coord_len = scale_actual_m / correction # 绘制比例尺条形(左下角位置) scale_bar = BoxAnnotation( left=p.x_range.start + 1000, right=p.x_range.start + 1000 + scale_coord_len, bottom=p.y_range.start + 1000, top=p.y_range.start + 1200, fill_color="white", line_color="black", fill_alpha=0.8 ) p.add_layout(scale_bar) # 添加比例尺文本 scale_label = Label( x=p.x_range.start + 1000 + scale_coord_len/2, y=p.y_range.start + 1250, text=f"{scale_actual_m/1000} km", text_align="center", background_fill_color="white", background_fill_alpha=0.8 ) p.add_layout(scale_label) show(p)
方案2:动态缩放适配比例尺(适合多缩放层级场景)
通过给Bokeh的范围变更事件添加JS回调,实现缩放、平移时自动更新比例尺的长度和数值:
- 提前预设不同距离级别的规整值(100m、200m、500m、1km、2km等)
- 每次视口变化时,重新计算当前中心纬度的修正系数,匹配最适合展示的比例尺长度
- 同步更新比例尺条形的坐标和文本标注
示例核心回调逻辑如下:
const correction = Math.cos(centerLat * Math.PI / 180) const viewWidth = x_range.end - x_range.start const actualViewWidth = viewWidth * correction // 匹配最合适的比例尺长度 const scales = [100, 200, 500, 1000, 2000, 5000, 10000, 20000, 50000] const targetScale = scales.find(s => s < actualViewWidth / 10) // 更新比例尺坐标和文本 scale_bar.right = scale_bar.left + targetScale / correction scale_label.text = targetScale >= 1000 ? `${targetScale/1000} km` : `${targetScale} m`
你可以根据自己的需求调整比例尺的位置、样式、距离分级规则,实现和OSM官网一致的展示效果。
内容的提问来源于stack exchange,提问作者sehan2
相关产品推荐
相关产品推荐

