bounds-parse
本文回答:
svc.openMap成功但res.bounds读不到 / 投影建立失败 —— bounds 格式解析错。
一、症状
const res = await svc.openMap({ mapid: 'xxx' });
console.log(res.bounds);
// 字符串 "[0,0,1000,2000]"(带方括号,minX,minY,maxX,maxY)
const prj = new vjmap.GeoProjection(JSON.parse(res.bounds)); // 传数组 / {min,max} 普通对象
// TypeError: this.mapExtent.width is not a function
// res.bounds 为 undefined(openMap 失败)时:Cannot read properties of undefined (reading 'width')
二、根因
res.bounds 是带方括号的字符串 "[minX,minY,maxX,maxY]";GeoProjection 只认 GeoBounds 实例(或这种字符串,构造内部会 fromString),数组 / 普通对象都会在 setExtent 里调 .width() 时崩:
| 形式 | 来源 | 如何解析 |
|---|---|---|
"[0,0,1000,2000]" |
服务端返回(openMap 的 res.bounds) |
vjmap.GeoBounds.fromString(res.bounds) |
"0,0,1000,2000" |
无方括号(如 GeoBounds.toString() 产物) |
同上(fromString 自动补 [] 再 JSON.parse) |
GeoBounds 对象 |
已解析 | 直接传 GeoProjection |
undefined |
openMap 失败 | 先查 res.error |
注意:GeoBounds.fromString 要求扁平四元素数组——"[[0,0],[1000,2000]]" 这种嵌套对会抛 param is not array length four string。
三、健壮解析
let mapExtent = vjmap.GeoBounds.fromString(res.bounds); // 官方统一姿势
const prj = new vjmap.GeoProjection(mapExtent);
四、openMap 返回结构
const res = await svc.openMap({ mapid: 'xxx', mapopenway: vjmap.MapOpenWay.GeomRender });
// res = {
// error?: string, // 失败时带上
// bounds?: string, // "[minX,minY,maxX,maxY]"
// mapid, ... (元数据)
// }
bounds 是 openMap 成功后保证有的字段(字符串)。响应里没有 ext_geomrect 字段。
五、建议代码模板
const svc = new vjmap.Service(url, token);
const res = await svc.openMap({ mapid, mapopenway: vjmap.MapOpenWay.GeomRender });
if (res.error) throw new Error('openMap 失败:' + res.error);
// GeoBounds.fromString 同时兼容 "x1,y1,x2,y2" 与 "[x1,y1,x2,y2]"
const mapExtent = vjmap.GeoBounds.fromString(res.bounds);
const prj = new vjmap.GeoProjection(mapExtent);
const map = new vjmap.Map({ container: 'map' });
map.attach(svc, prj);
await map.onLoad();
补充:new vjmap.GeoProjection(res.bounds) 在运行时也能工作——构造函数内部判断 typeof extent === 'string' 时会自动 GeoBounds.fromString。但 d.ts 只声明 GeoBounds 类型,TS 工程建议显式转换。
六、验证 bounds 正确性
console.log('bounds:', mapExtent);
// GeoBounds { min: GeoPoint{x,y}, max: GeoPoint{x,y} }
console.log(mapExtent.toString()); // "0,0,1000,2000"
- min / max 都有 x / y
- max > min
- 不是全 0 或 NaN
坐标一般是 CAD 内部坐标;如果 max - min = 0 → 图是空的或 bounds 读错。
七、为什么投影需要 bounds
GeoProjection 用 bounds 决定:
- 地图 0/0 经纬度对应 CAD 哪个点
- 每 meter 对应多少 CAD 单位
bounds 不对 → 整张图位置 / 比例尺错。
八、空白地图也需要 bounds
// 必须传 GeoBounds 实例——{min:{x,y},max:{x,y}} 普通对象会抛 this.mapExtent.width is not a function
const prj = new vjmap.GeoProjection(vjmap.GeoBounds.fromArray([0, 0, 1000, 1000]));
const map = new vjmap.Map({ container: 'map' });
map.attach(null, prj); // 不连后端
空白地图自己定 bounds。
九、动态改 bounds
用 map.updateMapExtent(newBounds)(收字符串 / 数组 / GeoBounds)重建投影,再 map.fitMapBounds();不必 map.remove 重建。注意它只换投影、不换瓦片源——要切到另一张 CAD 图用 map.switchMap。
十、常见坑
res.bounds直接 JSON.parse:得到的是扁平[x1,y1,x2,y2]数组,GeoProjection用不了;必须GeoBounds.fromString或 new GeoProjection 传原字符串。- 写成嵌套
[[0,0],[1000,2000]]:fromString要扁平四元素,嵌套对会抛param is not array length four string。 - 复制粘贴:某些示例用
bounds: res.bounds直接;不通用,按本文模板兜底。 - 空白地图 bounds 太大:几百万的范围 → 精度损失;限制在合理范围。
- bounds 的 Y 轴方向:vjmap 通常 Y 向上;传反了图上下翻转。
相关
- 打开图 → open-map/open-dwg
- 投影 → open-map/bounds-and-projection
- 坐标转换 → coord/overview