overlay-coords
本文回答: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] 完全出界