with-popup
本文回答:Marker 与 Popup 的绑定 —— setPopup / togglePopup / getPopup。
一、基本绑定
const popup = new vjmap.Popup({ offset: [0, -40] })
.setHTML("<h3>站点 A</h3><p>状态:正常</p>");
const marker = new vjmap.Marker()
.setLngLat([lng, lat])
.setPopup(popup);
marker.addTo(map); // addTo 返回 undefined,勿接链尾
点 Marker 打开 Popup。⚠️ 默认 closeOnClick: true 时再点 Marker 会先关后开(popup 在 preclick 关闭,Marker 随后在 click 里 toggle 又打开,关不掉);要开 / 关切换用 new vjmap.Popup({ closeOnClick: false })。
二、手动打开 / 关闭
marker.togglePopup(); // 切换
// 读
const p = marker.getPopup();
p.isOpen(); // true / false
// 手动 addTo / remove
p.addTo(map);
p.remove();
三、Popup 参数(常用)
new vjmap.Popup({
closeButton: true, // 右上 ×
closeOnClick: true, // 点击地图任意处(含要素、Marker)即关闭
closeOnMove: false, // 地图移动时关闭
anchor: "bottom", // 尖尖方向:top/bottom/left/right/top-left/...
offset: [0, -40], // 像素偏移
className: "my-popup", // 自定义类名
maxWidth: "300px"
});
四、hover 显示 Popup
const el = marker.getElement();
el.addEventListener("mouseenter", () => {
if (!popup.isOpen()) marker.togglePopup();
});
el.addEventListener("mouseleave", () => {
if (popup.isOpen()) popup.remove();
});
五、自定义 Popup 内容
5.1 HTML 字符串
popup.setHTML(`
<div class="card">
<img src="/a.jpg"/>
<h3>站点 A</h3>
<p>温度:26℃</p>
<button onclick="alert(1)">详情</button>
</div>
`);
5.2 setText(纯文本)
popup.setText("纯文本,不解析 HTML");
5.3 setDOMContent(现成 DOM)
const div = document.createElement("div");
div.appendChild(imgEl);
div.appendChild(titleEl);
popup.setDOMContent(div);
六、Popup 样式
.vjmapgis-popup { z-index: 10; }
.vjmapgis-popup-content {
background: rgba(0,0,0,0.8);
color: #fff;
border-radius: 8px;
}
[class*="vjmapgis-popup-anchor-bottom"] .vjmapgis-popup-tip { border-top-color: rgba(0,0,0,0.8); } /* 含 bottom-left/right;top/left/right 角向同理 */
或用 className:
new vjmap.Popup({ className: "my-popup" });
// .my-popup .vjmapgis-popup-content { ... }
七、按钮动作(setHTML 内)
setHTML 后 DOM 是 vjmap 控制的,事件要在 addTo 之后挂:
popup.setHTML('<button id="btn-x">删除</button>');
popup.on("open", () => {
document.getElementById("btn-x")?.addEventListener("click", () => {
marker.remove();
popup.remove();
});
});
八、Vue/React 渲染到 Popup
const container = document.createElement("div");
createApp(MyPopupCard, { site: data }).mount(container);
popup.setDOMContent(container);
九、多个 Marker 共享一个 Popup(切换式)
const popup = new vjmap.Popup({ closeButton: false });
markers.forEach(m => {
m.getElement().addEventListener("click", () => {
popup.setLngLat(m.getLngLat()).setHTML(m.data.name).addTo(map);
});
});
好处:只有一个 Popup 对象,性能好,不会累积。
十、常见坑
- setPopup 后点 Marker 不开 → Marker 本身是 draggable 时 click 被拖拽拦截;用
clickTolerance。 - Popup 位置不对:检查
offset;Marker 用 anchor: bottom,Popup 一般用 offset: [0, -40](向上)。 - Popup 内按钮无反应:setHTML 后 popup DOM 还没挂到文档;等
open事件或用setDOMContent。 - Popup 关了再开内容仍在:
remove()只把_content从文档摘除,重开时_update会重新appendChild(_content)——内容不丢,不用重新 setDOMContent/setHTML。 closeOnMove: true导致 hover 难用 → 设为 false。