唯杰地图 logo唯杰地图
VJMAP
EN

create

vjmap/references/marker/create.md 4.8 KB122 行
原文

本文回答:创建 Marker —— new vjmap.Marker / setLngLat / addTo / remove / show / hide。

一、最小用法

const marker = new vjmap.Marker()
  .setLngLat([113.0, 23.0]);
marker.addTo(map);

⚠️ Marker.addTo() 返回 undefined(d.ts 声明 this,运行时无返回值——源码 marker.ts 重写时未 return)。不要写 const m = new Marker().setLngLat(x).addTo(map)——m 会是 undefined,后续 m.remove() 报 TypeError。setLngLat/setPopup 等链返回 this 正常,仅 addTo 断链。

setLngLat 接受:

  • [lng, lat] 数组
  • LngLat 实例:new vjmap.LngLat(lng, lat)
  • { lng, lat } 对象

二、从 CAD 坐标创建

CAD 坐标必须先转经纬度:

const cadPt = [725.32, 18969.19];
const lngLat = map.toLngLat(cadPt);
new vjmap.Marker().setLngLat(lngLat).addTo(map);

三、两种构造形式

// 形式 1:只传 options
new vjmap.Marker({ color: "#f00", draggable: true });

// 形式 2:传 DOM + options
const el = document.createElement("div");
el.className = "my-marker";
new vjmap.Marker(el, { anchor: "bottom" });

// 形式 3(推荐):options.element
new vjmap.Marker({ element: el, anchor: "bottom" });

四、常用方法

方法 功能
addTo(map) 附加到地图
remove() 从地图移除
setLngLat(ll) 设置 / 移动位置(会触发重绘)
getLngLat() 当前位置
getElement() 获取底层 DOM(可 addEventListener / 改样式)
setPopup(popup) 绑定 Popup
togglePopup() 切换 Popup
setOffset([x, y]) 运行时改偏移
setRotation(deg) 旋转
show() / hide() 显隐(不从 map 里移除)
isHidden() 是否隐藏
setColor(c) 改默认水滴颜色
setDraggable(b) 启用拖拽
setAnimation(t) 弹跳 / 坠落动画(见 animation)

五、批量创建

const markers = [];
for (let i = 0; i < 100; i++) {
  const m = new vjmap.Marker({ color: "#0af" })
    .setLngLat(map.toLngLat(bounds.randomPoint()));
  m.addTo(map);          // addTo 返回 undefined,勿把链尾赋给 m
  markers.push(m);
}
// 批量移除
markers.forEach(m => m.remove());
markers.length = 0;

> 500 个 Marker 建议改用 Symbol 图层,见 performance-tips。

六、更新位置(动画式)

function moveTo(marker, target, duration = 1000) {
  const start = marker.getLngLat();
  const startT = performance.now();
  function step() {
    const t = Math.min(1, (performance.now() - startT) / duration);
    marker.setLngLat([
      start.lng + (target.lng - start.lng) * t,
      start.lat + (target.lat - start.lat) * t
    ]);
    if (t < 1) requestAnimationFrame(step);
  }
  requestAnimationFrame(step);
}

七、show / hide vs remove

API 行为
hide() DOM 仍在文档,display: none
setVisible(v, true) isDisplay=true 分支=CSS display 显隐切换(等价 show()/hide())
setVisible(false, false) isDisplay 假分支调 this.remove(),等价 remove():真正移除
remove() DOM 摘除、事件解绑、_map 删除(并置 isRemoved=true)

⚠️ remove() 不是不可逆:marker.addTo(map) 会重置 isRemoved、重建全部监听并重新挂上。

⚠️ setVisible(false,false) 之后不能用 setVisible(true,false) 恢复——它调 addTo(this._map),而 _map 已被删(addTo(undefined) 报错)。恢复要用 marker.addTo(map)。

⚠️ 更深坑:一旦误调 setVisible(true,false) 并捕获了异常,之后再 addTo(map) 会静默无效——addTo 包装在调原生方法之前就把 isShow 置 true,异常中断后 isShow 停在 true,下次 addTo 被 if (this.isShow) return 拦截。补救:marker.isShow = false 再 addTo(map)。

"DOM 摘除但保留地图登记"是内部 remove(true) / addTo(map, true) 布尔参路径(removeWhenNoInMapView 自动裁剪专用),公开 API 不暴露该开关。

八、常见坑

  1. CAD 坐标直接 setLngLat → marker 出现在赤道非洲;必须 map.toLngLat。
  2. 没有 addTo → 新建的 Marker 不显示。
  3. 元素没有尺寸 → 自定义 DOM 没 width/height 时,看起来像没创建。
  4. 重复创建未 remove → 同一个逻辑点反复 new Marker().addTo(map) 会重影。保留引用,需要时移除。
  5. addTo 链尾赋值 → const m = new Marker().setLngLat(x).addTo(map) 得到的 m 是 undefined(addTo 无返回值,d.ts 声明 this 与运行时不符);先 setLngLat 赋值再单独 addTo。Popup.addTo 未被重写、正常返回 this,不受影响。