经纬志
首页 / Leaflet / 教程

弹窗与提示

先看结论

Popup 是点击后弹出的浮层,Tooltip 是悬停或常驻的小标签。 两者都挂在某个坐标或某个图层上,区别在于触发方式、默认样式与是否独占。

最后验证 2026-11-03 · Leaflet 1.9.4 · 更新 2026-10-29 · 引用本文

两种浮层的分工

对比项PopupTooltip
触发bindPopup 后点击或调用 openPopupbindTooltip 后悬停,或设 permanent: true 常驻
同时可见数量默认只保留一个可以多个同时显示
默认样式白色气泡,带关闭按钮深色小标签,无关闭按钮
典型内容表单、图片、详情链接名称、数值、编号

「默认只保留一个」是 Popup 的重要行为:打开新的会自动关掉旧的, 由 autoClose 控制。想同时开多个,绑定时传 { autoClose: false, closeOnClick: false }。

绑定与手动打开

绑在图层上是最省事的用法。弹窗的位置默认取图层中心, 线、面会落在几何中心,看起来可能离鼠标很远。

var marker = L.marker([39.907359, 116.391263]).addTo(map);

marker.bindPopup(
  '<b>天安门</b><br>东经 116.391263,北纬 39.907359',
  { maxWidth: 260, autoPan: true }
);

// 也可以在地图任意坐标打开一个独立弹窗
L.popup()
  .setLatLng([39.916345, 116.397155])
  .setContent('<p>王府井</p>')
  .openOn(map);

autoPan: true(默认)在弹窗超出视野时自动平移地图。 嵌在固定高度容器里、或页面本身可滚动时,自动平移会让整页跳动, 这时改成 autoPan: false 更稳。

内容更新

setContent 会替换整块内容。已经打开的弹窗要立即刷新, 再调用一次 update() 重新计算尺寸与位置;否则长内容会把弹窗撑出边界。

var popup = L.popup()
  .setLatLng([39.907359, 116.391263])
  .setContent('加载中…')
  .openOn(map);

fetch('/api/station/42')
  .then(function (r) { return r.json(); })
  .then(function (data) {
    popup.setContent(
      '<h4>' + data.name + '</h4><p>客流:' + data.flow + '</p>'
    );
    popup.update();       // 重算尺寸与箭头位置
  });

定位与偏移

弹窗箭头默认指向锚点。用 offset 微调,用 direction 指定优先方向,Leaflet 会在空间不足时自动翻转。

选项取值说明
offset[x, y]相对锚点的像素偏移,向上为负 y
directiontop / bottom / left / right / autoTooltip 优先出现的方向
permanenttrue / falseTooltip 是否常驻
stickytrue / falseTooltip 是否跟随鼠标而不是固定在几何中心
className字符串附加类名,用于自定义外观
L.circleMarker([39.907359, 116.391263], { radius: 8 })
  .bindTooltip('监测点 A · PM2.5 42', {
    permanent: true,
    direction: 'top',
    offset: [0, -10],
    className: 'monitor-label'
  })
  .addTo(map);

注意事项

弹窗里的图片把布局撑开

图片没有尺寸时,弹窗按 0 高度计算,加载完成后图片溢出。 给 img 写死宽高,或在 load 事件里调用 popup.update()。

点线面弹窗位置不对

面要素的弹窗落在几何中心,狭长多边形可能落在图形之外。 在绑定前用 layer.getBounds().getCenter() 覆盖坐标, 或在 click 里用 L.popup().setLatLng(e.latlng) 手动打开。

频繁开关弹窗后内存上涨

每次 L.popup() 都创建新实例,并挂在地图容器上。 高德式「点哪都弹」的交互里,复用同一个弹窗实例、只改坐标与内容, 可以避免节点反复创建销毁。

内容拼接要转义。弹窗内容走 innerHTML。来自接口的字段名 直接拼进去,等于把后端数据当代码执行。文本先转义,富文本用白名单过滤。

引用本文

经纬志(2026)。《弹窗与提示》。https://www.jingweizhi.com/leaflet/tutorial/popup-tooltip.html(访问日期 2026-11-03)。