> **本文回答**：Popup 与 Marker 绑定 —— setPopup / togglePopup / getPopup / 自动联动位置。

## 一、setPopup 一次设定

```js
const popup = new vjmap.Popup({ offset: [0, -40] })
  .setHTML("<b>站点 A</b>");

new vjmap.Marker()
  .setLngLat([lng, lat])
  .setPopup(popup)
  .addTo(map);
```

点 Marker 打开 Popup。⚠️ 默认 `closeOnClick: true` 时再点 Marker 会先关后开（popup 在 `preclick` 关闭，Marker 随后在 `click` 里 toggle 又打开，关不掉）；要开 / 关切换用 `new vjmap.Popup({ closeOnClick: false })`。

## 二、解绑 / 替换

```js
marker.setPopup(undefined);        // 解绑
marker.setPopup(newPopup);         // 换新 popup
```

## 三、手动 toggle / 开关

```js
marker.togglePopup();              // 切换
marker.getPopup()?.isOpen();       // 读状态
```

## 四、动态更新 Popup 内容

```js
const popup = new vjmap.Popup().setHTML("loading...");
marker.setPopup(popup);

async function refresh() {
  const data = await fetchSiteData();
  popup.setHTML(`<b>${data.name}</b><br/>温度：${data.temp}℃`);
}
```

## 五、悬停打开，离开关闭

```js
const popup = new vjmap.Popup({ closeButton: false, offset: [0, -40] })
  .setHTML("hover me");

const el = marker.getElement();
el.addEventListener("mouseenter", () => {
  if (!popup.isOpen()) popup.setLngLat(marker.getLngLat()).addTo(map);
});
el.addEventListener("mouseleave", () => popup.remove());
```

## 六、Marker 移动时 Popup 跟随

marker 绑定 popup 后，marker 移动时 popup 位置**自动跟随**：

```js
marker.setLngLat([newLng, newLat]);  // popup 自动跟着
```

不绑定的独立 Popup 需要手动：

```js
popup.setLngLat([newLng, newLat]);
```

## 七、多个 Marker 共享一个 Popup

```js
const popup = new vjmap.Popup({ closeButton: false });

markers.forEach(m => {
  m.getElement().addEventListener("click", e => {
    popup.setLngLat(m.getLngLat()).setHTML(m.data.name).addTo(map);
  });
});
```

好处：少 DOM 节点、少内存。

## 八、绑定后修改 Popup Offset

```js
marker.setPopup(new vjmap.Popup({ offset: [0, -60] }).setHTML("..."));
```

注意：默认水滴 Marker 绑 popup 时，vjmap 自动把 popup 的默认 offset 设为 `{bottom:[0,-38.1],...}`（38.1px ≈ 水滴高 41px），已对齐底端；**自定义 element 时该默认值改为 `this._offset`**，要手动对齐。

## 九、绑定 popup 和 dragend

```js
const popup = new vjmap.Popup().setHTML("拖我");
marker.setPopup(popup);
marker.togglePopup();           // 预先打开

marker.on("drag", () => {
  const ll = marker.getLngLat();
  popup.setHTML(`(${ll.lng.toFixed(4)}, ${ll.lat.toFixed(4)})`);
});
```

## 十、常见坑

1. **setPopup 后不自动打开**：需要 `togglePopup` 或点击 Marker。
2. **Popup 离 Marker 位置偏**：检查 marker 的 anchor 和 popup 的 offset 是否对齐。
3. **marker 被 hide** 时 popup 还在：hide marker 不自动关 popup；自己 popup.remove()。
4. **Popup 点击关闭但 Marker 仍选中状态**：popup 关不影响 marker；可监听 `popup.on('close', ...)` 更新业务状态。
