唯杰地图 logo唯杰地图
VJMAP
EN

drag

vjmap/references/marker/drag.md 3.5 KB130 行
原文

本文回答:Marker 拖拽 —— draggable / dragstart / drag / dragend。

一、启用拖拽

const m = new vjmap.Marker({ draggable: true })
  .setLngLat([lng, lat]);
m.addTo(map);

// 运行时
m.setDraggable(true);
m.isDraggable();            // true

二、拖拽事件

m.on("dragstart", () => {
  console.log("开始拖拽");
});

m.on("drag", () => {
  const ll = m.getLngLat();
  console.log("拖拽中", ll.lng, ll.lat);
});

m.on("dragend", () => {
  const ll = m.getLngLat();
  console.log("拖拽结束", ll);
});

三、clickTolerance(点击 vs 拖拽的容差)

new vjmap.Marker({ draggable: true, clickTolerance: 3 })

鼠标在按下过程中移动超过 3 像素算拖拽,否则视为点击。

限制可发起拖拽的鼠标键(vjmap 引擎扩展,d.ts 未声明,TS 需 // @ts-ignore):默认任意键都能拖;disableDragButton 列出禁止的键,取值 left / middle / right / touch,多个用逗号连接:

const m2 = new vjmap.Marker({ draggable: true, disableDragButton: "middle,right" })  // 只允许左键和触摸拖动
  .setLngLat([lng, lat]);
m2.addTo(map);

四、实时显示坐标(在 Marker 上)

const el = document.createElement("div");
el.style.cssText = "background:#fff;padding:4px;border:1px solid #aaa;cursor:move";
el.textContent = "拖我";

const m = new vjmap.Marker({ element: el, anchor: "bottom", draggable: true })
  .setLngLat([lng, lat]);
m.addTo(map);

m.on("drag", () => {
  const ll = m.getLngLat();
  el.textContent = `(${ll.lng.toFixed(5)}, ${ll.lat.toFixed(5)})`;
});

五、拖到指定位置后吸附

m.on("dragend", () => {
  const ll = m.getLngLat();
  // 找最近的目标点
  const snapTo = findNearest(ll, candidates);
  if (distance(ll, snapTo) < 50) {
    m.setLngLat(snapTo);   // 吸附
  }
});

六、拖出边界回弹

m.on("dragend", () => {
  const ll = m.getLngLat();
  const bounds = map.getMapExtent();            // CAD 全图范围(getGeoBounds() 默认只是全图×initViewScale/0.7)
  // ⚠️ GeoBounds.contains 只收 GeoPoint:先把经纬度转回 CAD 点再判定
  if (!bounds.contains(map.fromLngLat(ll))) {
    m.setLngLat(savedLastValidLngLat);
    alert("超出范围,已回弹");
  } else {
    savedLastValidLngLat = ll;
  }
});

七、拖动时同步 popup 位置

const popup = new vjmap.Popup({ closeButton: false }).setText("拖我");
m.setPopup(popup);
m.togglePopup();            // 打开

m.on("drag", () => {
  // popup 会自动跟着 marker 移动,不用手动调整
});

八、禁止拖拽

m.setDraggable(false);

九、坐标转 CAD

m.on("dragend", () => {
  const ll = m.getLngLat();
  const cadPt = map.fromLngLat(ll);            // → { x, y }
  console.log("CAD 坐标", cadPt.x, cadPt.y);
});

十、常见坑

  1. 拖拽过程中触发 click → 用 clickTolerance 容差(默认 0 即继承 map)。
  2. 拖拽后位置不对 → 可能 anchor 是 center 但视觉上以为是 bottom;拖的是几何中心。
  3. CSS 禁用 user-select:cursor: move; user-select: none;,避免拖拽时选中文本。
  4. setDraggable(true) 后没拖 → 检查自定义 element 上有没有阻止 pointer 事件的 CSS。
  5. 多个 Marker 同时拖:vjmap Marker 是独立 DOM,可以独立拖;但 hitTest 顺序取决于 z-index。