唯杰地图 logo唯杰地图
VJMAP
EN

overlay-coords

vjmap/references/coord/overlay-coords.md 4.4 KB68 行
原文

本文回答:vjmap 每个覆盖物(Marker/Popup/Symbol/GeoJSON/CircleFill/MarkerCluster/DivOverlay/SvgOverlay)的坐标参数到底该传哪个空间——CAD 坐标还是渲染经纬度。

一、判断原则

同名"坐标"参数,有的要渲染经纬度,有的要 CAD 坐标——区别只看这个对象内部有没有调 map.toLngLat。

记忆法:画"几何形状"的(圆/椭圆/任意 div/svg 区域)内部生成图形坐标再统一转——传 CAD;摆"位置"的(Marker/Popup/Symbol 点)和通用 GeoJSON 管线——传渲染经纬度。 互联网底图下两列等价(toLngLat 是恒等),但混传的习惯带到 CAD 底图就会出 bug。

二、传「渲染经纬度」(调用方自己 map.toLngLat 转换)

对象 入口 说明
vjmap.Marker setLngLat(lngLat) 引擎原生,只吃渲染经纬度;传 CAD(y>90)直接抛 Invalid LngLat latitude value,不是静默错位
vjmap.Popup setLngLat(lngLat) 同上
vjmap.Text setLngLat(lngLat) 内部包了一层 Marker
vjmap.Symbol data createPointGeoJson/createLineGeoJson → geojson source,零转换(data 原样进 source)
vjmap.Circle data 点符号图层(不是几何圆!半径是像素/样式),不做转换
vjmap.Polygon data 不做转换
vjmap.Polyline data 不做转换
vjmap.PolylineArrow path 直接当 LineString 坐标,不做转换
vjmap.FillExtrusion / vjmap.Heatmap data 不做转换
map.addSource/addLayer 的 geojson data 底层入口,一律渲染经纬度

三、传「CAD 坐标」(内部帮你 map.toLngLat)

对象 入口 内部行为
vjmap.CircleFill center + radius map.toLngLat(getCirclePolygonCoordinates(center, radius,…))——几何在 CAD 空间生成再整体转,radius 是 CAD 单位
vjmap.CircleEdge 同上 同上(只描边)。⚠️ 当前版本运行时损坏:updateData() 调用未打包进产物的 getCirclePolylineCoordinates(min.js 中仅定义 getCirclePolygonCoordinates),addTo 必抛 getCirclePolylineCoordinates is not defined。需描边圆请改用 CircleFill 配透明填充 + 边色,或 Polyline 自算
vjmap.EllipseFill / EllipseEdge center + 轴半径 同上
vjmap.MarkerCluster data[].point 内部 map.toLngLat(point) → project 到屏幕;d.ts 原文注释"传入坐标为CAD地理坐标"
vjmap.DivOverlay bounds 四角 内部 toLngLat → projectEx
vjmap.SvgOverlay 元素 {{x,y}} / bounds 坐标是地理坐标(CAD 空间),内部转像素;{{r}} 长度占位符也是 CAD 单位

updateData/setCenter 与 addTo 走同一条转换路径,约定一致。

MarkerCluster 的 createMarker 是必填回调

缺了直接抛 this.options.createMarker is not a function;且回调里要自己把 CAD 点转成渲染经纬度:

new vjmap.MarkerCluster({
  data: [{ point: cadPt, properties:{...} }],                          // CAD 坐标
  createMarker: d => new vjmap.Marker().setLngLat(map.toLngLat(d.point))  // 自己转
}).addTo(map);

四、快速代码对照(CAD 底图)

const cadPt = [4512345.6, 3456789.0];          // CAD 几何坐标
const ll = map.toLngLat(cadPt);                // 渲染经纬度(无地理意义)

new vjmap.Marker().setLngLat(ll).addTo(map);                      // ✅ 转后传
new vjmap.Popup().setLngLat(ll).setText('x').addTo(map);          // ✅
new vjmap.Symbol({ data: ll, iconImage: 'xx' }).addTo(map);       // ✅
map.addSource('s', { type:'geojson', data: map.toLngLat(fc) });   // ✅ FeatureCollection 整体转(走 cloneDeep,不改原对象)
// ⚠️ 但 map.toLngLat(单个 Feature / 裸 Geometry) 是【原地改原对象】并返回同一对象,
//    重复调用 = 二次转换。详见 projection-api.md「原地修改陷阱」

new vjmap.CircleFill({ center: cadPt, radius: 500 }).addTo(map);  // ✅ 传 CAD,半径是 CAD 单位
new vjmap.MarkerCluster({ data: [{ point: cadPt }], createMarker: d => ... }).addTo(map); // ✅ 传 CAD

new vjmap.Marker().setLngLat(cadPt).addTo(map);                   // ❌ y>90 直接抛 Invalid LngLat
new vjmap.CircleFill({ center: ll, radius: 500 }).addTo(map);     // ❌ 二次转换——会生成几何落到 [-28644,-90] 完全出界