> **本文回答**：Marker 与 Popup 的绑定 —— setPopup / togglePopup / getPopup。

## 一、基本绑定

```js
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 })`。

## 二、手动打开 / 关闭

```js
marker.togglePopup();    // 切换

// 读
const p = marker.getPopup();
p.isOpen();              // true / false

// 手动 addTo / remove
p.addTo(map);
p.remove();
```

## 三、Popup 参数（常用）

```js
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

```js
const el = marker.getElement();
el.addEventListener("mouseenter", () => {
  if (!popup.isOpen()) marker.togglePopup();
});
el.addEventListener("mouseleave", () => {
  if (popup.isOpen()) popup.remove();
});
```

## 五、自定义 Popup 内容

### 5.1 HTML 字符串

```js
popup.setHTML(`
  <div class="card">
    <img src="/a.jpg"/>
    <h3>站点 A</h3>
    <p>温度：26℃</p>
    <button onclick="alert(1)">详情</button>
  </div>
`);
```

### 5.2 setText（纯文本）

```js
popup.setText("纯文本，不解析 HTML");
```

### 5.3 setDOMContent（现成 DOM）

```js
const div = document.createElement("div");
div.appendChild(imgEl);
div.appendChild(titleEl);
popup.setDOMContent(div);
```

## 六、Popup 样式

```css
.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`：

```js
new vjmap.Popup({ className: "my-popup" });
// .my-popup .vjmapgis-popup-content { ... }
```

## 七、按钮动作（setHTML 内）

setHTML 后 DOM 是 vjmap 控制的，事件要在 addTo 之后挂：

```js
popup.setHTML('<button id="btn-x">删除</button>');
popup.on("open", () => {
  document.getElementById("btn-x")?.addEventListener("click", () => {
    marker.remove();
    popup.remove();
  });
});
```

## 八、Vue/React 渲染到 Popup

```js
const container = document.createElement("div");
createApp(MyPopupCard, { site: data }).mount(container);
popup.setDOMContent(container);
```

## 九、多个 Marker 共享一个 Popup（切换式）

```js
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 对象，性能好，不会累积。

## 十、常见坑

1. **setPopup 后点 Marker 不开** → Marker 本身是 draggable 时 click 被拖拽拦截；用 `clickTolerance`。
2. **Popup 位置不对**：检查 `offset`；Marker 用 anchor: bottom，Popup 一般用 offset: [0, -40]（向上）。
3. **Popup 内按钮无反应**：setHTML 后 popup DOM 还没挂到文档；等 `open` 事件或用 `setDOMContent`。
4. **Popup 关了再开内容仍在**：`remove()` 只把 `_content` 从文档摘除，重开时 `_update` 会重新 `appendChild(_content)`——**内容不丢**，不用重新 setDOMContent/setHTML。
5. **`closeOnMove: true` 导致 hover 难用** → 设为 false。
