唯杰地图 logo唯杰地图
VJMAP
EN

bounds-parse

vjmap/references/trouble/bounds-parse.md 4.6 KB118 行
原文

本文回答: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。

十、常见坑

  1. res.bounds 直接 JSON.parse:得到的是扁平 [x1,y1,x2,y2] 数组,GeoProjection 用不了;必须 GeoBounds.fromString 或 new GeoProjection 传原字符串。
  2. 写成嵌套 [[0,0],[1000,2000]]:fromString 要扁平四元素,嵌套对会抛 param is not array length four string。
  3. 复制粘贴:某些示例用 bounds: res.bounds 直接;不通用,按本文模板兜底。
  4. 空白地图 bounds 太大:几百万的范围 → 精度损失;限制在合理范围。
  5. bounds 的 Y 轴方向:vjmap 通常 Y 向上;传反了图上下翻转。

相关