# SGS Map SDK API Reference > 本项目同步版本: V2.5.0 > 适用对象: 第三方 H5、大屏、Kiosk、业务前端开发人员 > 发布源保留了 V2.3.0 文档标题和历史 API 注释;实际发行版本以 `package.json` 与 `dist` 产物自报的 2.5.0 为准。本文不表示本项目已经接入或验证 SDK iframe renderer。 本文档按公开 SDK 方法组织,说明初始化参数、事件、常用 API、返回值和错误处理。快速接入请先阅读 `sdk-quickstart.md`,底层通信协议请阅读 `sdk-protocol.md`。 ## 1. 接入入口 ### Script 标签 ```html ``` 如果 SDK 已随 `sgs-frontend-map` 发布到静态目录: ```html ``` ### ESM ```ts import SGSMapSDK from './dist/index.mjs'; const map = new SGSMapSDK({ container: document.getElementById('map-container')!, sdkUrl: 'https://map.example.com/engine/index.html', targetOrigin: 'https://map.example.com', floorId: 1 }); ``` ## 2. 初始化配置 ```ts interface SGSMapSDKOptions { container: string | HTMLElement; sdkUrl?: string; targetOrigin?: string; floorId?: string | number; mapId?: string | number; timeout?: number; readyTimeout?: number; } ``` | 字段 | 必填 | 默认值 | 说明 | |------|------|--------|------| | `container` | 是 | 无 | 地图 iframe 挂载容器,可传 DOM id 或 HTMLElement | | `sdkUrl` | 否 | `/engine/index.html` | 独立发布的 SDK 渲染引擎地址 | | `targetOrigin` | 否 | 从 `sdkUrl` 推导 | `postMessage` 安全通信域,生产环境建议显式填写 | | `floorId` | 否 | `1` | 初始楼层 ID,支持字符串或数字 | | `mapId` | 否 | `1` | 地图 ID,当前由 SDK 实例保存 | | `timeout` | 否 | `5000` | 普通命令超时时间,单位 ms | | `readyTimeout` | 否 | `30000` | 等待 `ENGINE_READY` 的最大时间,单位 ms | 生产环境必须保证 `sdkUrl` 可访问,并且 `targetOrigin` 与 `sdkUrl` 的 Origin 一致。 ## 3. 生命周期 ### `whenReady(): Promise` 等待地图引擎 ready。所有需要基座响应的 API 建议在 ready 后调用。 ```ts await map.whenReady(); await map.changeFloor(2); ``` ### `ready(): Promise` `whenReady()` 的别名。 ### `getIsReady(): boolean` 返回 SDK 是否已收到基座 `ENGINE_READY`。 ### `destroy(): void` 销毁 SDK 实例,清理 iframe、事件监听和所有挂起 Promise。销毁后再调用异步命令会返回 `ERR_DESTROYED`。 ```ts window.addEventListener('beforeunload', () => { map.destroy(); }); ``` ## 4. 状态查询 ### `getCurrentFloor(): string | number` 返回 SDK 当前记录的楼层 ID。 ### `getMapId(): string | number` 返回初始化时设置的 `mapId`。 ### `getVersion(): string` 返回 SDK 版本号;本项目同步的 2.5.0 Bridge 返回 `"2.5.0"`。 ### `getState(): Promise` 向渲染基座查询内部状态。主要用于调试或 Demo 面板。 ```ts const state = await map.getState(); console.log(state); ``` ## 5. 地图控制 ### `changeFloor(floorId, timeout?): Promise<{ success: boolean; floorId: string | number }>` 切换楼层。成功后 SDK 内部当前楼层会同步更新。 ```ts await map.changeFloor(2); ``` ### `focusTo(node): void` 镜头聚焦到 POI、GLB 节点或坐标。 ```ts map.focusTo({ type: 'poiId', value: 10001 }); map.focusTo({ type: 'nodeName', value: 'Hall_Dinosaur' }); map.focusTo({ type: 'coord', floorId: 1, x: 12.5, z: -8.2 }); map.focusTo('Hall_Dinosaur'); ``` `SgsMapNode` 类型: ```ts type SgsMapNode = | { type: 'coord'; floorId: string | number; x: number; z: number; y?: number } | { type: 'poiId'; value: string | number } | { type: 'nodeName'; value: string }; ``` 坐标统一使用 GLB/Three.js 米制坐标,水平面为 `x/z`,高度为 `y`。 ### `resetView(): void` 重置相机视角。 ### `setViewMode(mode): void` 切换 2D/3D 模式。 ```ts map.setViewMode('2d'); map.setViewMode('3d'); ``` ### `highlightPolygon(nodeName): void` 高亮指定 3D 场景节点对应的空间轮廓。 ```ts map.highlightPolygon('Hall_Area_01'); ``` ## 6. 图层控制 ### `toggleLayer(types, visible, timeout?): Promise<{ success: boolean; visibleTypes: string[] }>` 批量控制指定类型图层的显示隐藏。 ```ts await map.toggleLayer(['TOILET', 'ELEVATOR'], true); await map.toggleLayer(['STAIRS'], false); ``` ### `setVisibleLayers(types, timeout?): Promise<{ success: boolean; visibleTypes: string[] }>` 设置当前可见的图层类型列表。 ```ts await map.setVisibleLayers(['TOILET', 'ELEVATOR', 'SERVICE_DESK']); ``` ## 7. 图钉 Marker ### `addMarker(config): void` 添加业务图钉。 ```ts map.addMarker({ id: 'user-location', name: '我的位置', iconUrl: 'https://example.com/avatar.png', position: { x: 10, y: 1.6, z: -5 } }); ``` `MarkerConfig`: ```ts interface MarkerConfig { id: string; name?: string; iconUrl?: string; anchorNodeName?: string; position?: [number, number, number] | { x: number; y: number; z: number }; } ``` ### `removeMarker(markerId): void` 移除指定图钉。 ```ts map.removeMarker('user-location'); ``` ### `clearMarkers(): void` 清空所有业务图钉。 ## 8. 路径规划 ### `planRoute(from, to, options?, timeout?): Promise` 规划路线,兼容字符串节点名和结构化节点。 ```ts const route = await map.planRoute( { type: 'poiId', value: 8001 }, { type: 'poiId', value: 9005 }, { mode: 'walk' } ); if (route.success) { console.log(route.distance, route.duration, route.pathPoints); } ``` 也可传节点名: ```ts await map.planRoute('一楼南卫生间', '生态大展区'); ``` ### `planRouteV2(from, to, options?, timeout?): Promise` 结构化参数版本。当前底层同样发送 `PLAN_ROUTE` 指令。 ```ts await map.planRouteV2( { type: 'coord', floorId: 1, x: 0, z: 0 }, { type: 'coord', floorId: 1, x: 12, z: -6 }, { mode: 'accessible' } ); ``` ### `clearRoute(): void` 清除当前路线。 ```ts map.clearRoute(); ``` `RouteResult` 主要字段: ```ts interface RouteResult { success: boolean; distance: number; duration: number; pathPoints: Array<{ x: number; y: number; z: number }>; computeTimeMs: number; warnings: string[]; errorCode?: string; message?: string; } ``` ## 9. 地图数据 API ### `getManifest(timeout?): Promise` 获取地图 Manifest,包含地图名称、楼层摘要、能力声明和版本信息。 ```ts const manifest = await map.getManifest(); console.log(manifest.mapName, manifest.sdkVersion, manifest.floors); ``` ### `loadFloorBundle(floorId, timeout?): Promise` 一次性加载指定楼层的模型、POI、空间面、讲解点和路网摘要。 ```ts const bundle = await map.loadFloorBundle(1); console.log(bundle.model.modelUrl); console.log(bundle.pois.length, bundle.spaces.length, bundle.guideStops.length); ``` ### `getFloorPois(floorId, timeout?): Promise` 获取指定楼层 POI 列表。 ```ts const pois = await map.getFloorPois(1); pois.forEach(poi => console.log(poi.name, poi.type, poi.position)); ``` ### `getPois(floorCode, timeout?): Promise` 按楼层代码获取 POI 列表。该方法用于兼容既有基座能力,推荐新接入优先使用 `getFloorPois(floorId)`。 ```ts const pois = await map.getPois('L1'); ``` ### `getSpaces(floorId, timeout?): Promise` 获取指定楼层空间面列表。 ```ts const spaces = await map.getSpaces(1); spaces.forEach(space => console.log(space.name, space.boundaryWkt)); ``` ### `getGuideStops(floorId, timeout?): Promise` 获取指定楼层已标定讲解点列表。 ```ts const stops = await map.getGuideStops(1); stops.forEach(stop => console.log(stop.name, stop.audioUrl)); ``` ### `getGuideStopsByHall(hallId, timeout?): Promise` 获取指定展厅下的讲解点列表。 ```ts const stops = await map.getGuideStopsByHall('hall-001'); ``` ### `preloadFloor(floorId, timeout?): Promise<{ cached: boolean }>` 后台预加载指定楼层模型资源,不切换当前视图。 ```ts await map.preloadFloor(2); ``` ### `clearModelCache(): void` 清空客户端模型缓存。 ```ts map.clearModelCache(); ``` ### `getNavigablePlaces(floorId, timeout?): Promise` 获取指定楼层的可导航目的地列表(v2.3.0+)。 ```ts const places = await map.getNavigablePlaces(1); places.forEach(place => console.log(place.name, place.category)); ``` ## 10. 诊断接口 (v2.3.0+) ### `getDiagnostics(timeout?): Promise` 获取地图整体诊断信息,包含所有楼层摘要和汇总统计。用于检查数据完整性和就绪状态。 ```ts const diagnostics = await map.getDiagnostics(); console.log('地图状态:', diagnostics.status); console.log('楼层总数:', diagnostics.summary.floorCount); console.log('POI总数:', diagnostics.summary.poiCount); console.log('可导航目的地总数:', diagnostics.summary.navigablePlaceCount); // 检查警告信息 if (diagnostics.warnings.length > 0) { console.warn('诊断警告:', diagnostics.warnings); } // 遍历楼层摘要 diagnostics.floors.forEach(floor => { console.log(`${floor.floorName}: ${floor.status}, 可导航点=${floor.navigablePlaceCount}`); }); ``` **返回结构**: ```ts interface SgsMapDiagnostics { mapId: string | number; mapName: string; sdkVersion: string; status: 'OK' | 'WARN' | 'ERROR'; floors: SgsFloorDiagnosticsSummary[]; summary: { floorCount: number; modelReadyFloorCount: number; poiCount: number; spaceCount: number; guideStopCount: number; navigablePlaceCount: number; routeNodeCount: number; routeEdgeCount: number; }; warnings: string[]; } ``` ### `getFloorDiagnostics(floorId, timeout?): Promise` 获取单个楼层的详细诊断信息。 ```ts const floorDiag = await map.getFloorDiagnostics(1); console.log('楼层状态:', floorDiag.status); console.log('模型就绪:', floorDiag.modelReady); console.log('路径规划就绪:', floorDiag.routePlanningReady); console.log('POI数量:', floorDiag.poiCount); console.log('可导航目的地:', floorDiag.navigablePlaceCount); ``` **返回结构**: ```ts interface SgsFloorDiagnostics { floorId: string | number; floorCode: string; floorName: string; status: 'OK' | 'WARN' | 'ERROR'; modelReady: boolean; poiCount: number; spaceCount: number; guideStopCount: number; navigablePlaceCount: number; routeNodeCount: number; routeEdgeCount: number; routePlanningReady: boolean; warnings: string[]; } ``` **使用场景**: - 应用启动时检查地图数据是否完整 - 排查路径规划失败原因(检查 routePlanningReady) - 监控数据发布后的就绪状态 - 生成数据健康报告 ## 11. 性能监控 ### `getPerformanceStats(timeout?): Promise` 获取 SDK 与渲染基座的性能统计。v2.3.0 保持合并 SDK 自身耗时与基座返回的模型加载耗时。 ```ts const stats = await map.getPerformanceStats(); console.table({ sdkReady: stats.engineReadyMs, iframeDom: stats.iframeDomReadyMs, manifest: stats.manifestLoadMs, bundle: stats.bundleLoadMs ?? 'N/A', model: stats.modelDownloadAndParseMs, firstRender: stats.firstRenderMs }); ``` 主要字段: | 字段 | 说明 | |------|------| | `sdkCreatedAt` | SDK 实例创建时间戳 | | `iframeDomReadyMs` | iframe DOM 加载完成耗时 | | `engineReadyMs` | 地图引擎 ready 耗时 | | `manifestLoadMs` | Manifest 加载耗时 | | `bundleLoadMs` | Bundle 加载耗时,未触发时可能为空 | | `modelDownloadMs` | 模型下载耗时 | | `modelDownloadAndParseMs` | 模型下载与解析总耗时 | | `modelParseMs` | 模型解析耗时 | | `firstRenderMs` | 首帧渲染耗时 | | `routePlanMs` | 路径规划耗时 | | `dracoUsed` | 是否使用 Draco 压缩模型 | | `fallbackUsed` | 是否使用 fallback 原始模型 | | `currentFloorId` | 当前楼层 ID | ## 11. 事件 SDK 继承事件能力,可通过 `on(eventName, handler)` 监听事件。 ```ts map.on('ready', (info) => { console.log('ready', info.engineVersion, info.protocolVersion); }); map.on('poiClick', (poi) => { console.log('poi clicked', poi.id, poi.name); }); ``` | 事件名 | Payload | 说明 | |--------|---------|------| | `ready` | `{ engineVersion, protocolVersion }` | 基座完全挂载,可安全调用 API | | `poiClick` | `{ id, name, type, floorId?, description? }` | 用户点击 POI | | `floorChanged` | `{ floorId }` | 楼层切换完成 | | `error` | `{ code, message }` | 基座或 SDK 异常 | | `loadError` | `{ type, detail }` | 资源加载异常 | | `routeTransfer` | `{ currentFloorId, targetFloorId, transferType, ... }` | 跨楼层换乘提示 | | `modelLoading` | `{ floorId, modelUrl }` | 模型开始加载 | | `modelReady` | `{ floorId, parseTimeMs }` | 模型解析完成 | | `modelError` | `{ floorId, error, fallbackUsed }` | 模型加载失败 | | `floorBundleReady` | `{ floorId, dataVersion }` | 楼层 Bundle 数据加载完成 | | `routeReady` | `{ routeId, distance, duration }` | 路径规划完成 | ## 12. 常用类型摘要 ### `SgsSdkManifest` ```ts interface SgsSdkManifest { mapId: string | number; mapName: string; sdkVersion: string; protocolVersion: number; dataVersion: string; updatedAt: string; coordinateSystem: string; floors: SgsSdkFloorSummary[]; capabilities: { dracoCompression: boolean; routePlanning: boolean; spatialQuery: boolean; guideStops: boolean; // v2.3.0 新增标准能力字段 mapLoading?: boolean; floorSwitching?: boolean; poiQuery?: boolean; spaceQuery?: boolean; navigablePlaces?: boolean; crossFloorRoute?: boolean; accessibleRoute?: boolean; highlight?: boolean; diagnostics?: boolean; }; } ``` ### `SgsPoi` ```ts interface SgsPoi { id: string | number; name: string; type: string; typeName: string; floorCode: string; position: { x: number; y: number; z: number }; status: 'ACTIVE' | 'INACTIVE'; anchorNodeName?: string | null; description?: string; iconUrl?: string; } ``` ### `SgsSpaceArea` ```ts interface SgsSpaceArea { id: string | number; name: string; type: string; floorId: string | number; boundaryWkt: string; center: { x: number; y: number; z: number }; sourceNodeName?: string; status: 'ACTIVE' | 'INACTIVE'; colorHex?: string; } ``` ### `SgsGuideStop` ```ts interface SgsGuideStop { id: string | number; name: string; type: string; floorId: string | number; position: { x: number; y: number; z: number }; targetType: string; targetId?: string | number; audioUrl?: string; coverImageUrl?: string; description?: string; status: 'ACTIVE' | 'INACTIVE'; hallId?: string | number; hallName?: string; } ``` 完整类型以 `dist/index.d.ts` 为准。 ## 13. 错误处理 所有 Promise API 失败时会 reject 一个 `{ code, message }` 结构。 ```ts try { await map.changeFloor(999); } catch (err) { console.warn(err.code, err.message); } ``` | 错误码 | 说明 | |--------|------| | `ERR_TIMEOUT` | 命令响应超时 | | `ERR_READY_TIMEOUT` | ready 超时,基座未发出 `ENGINE_READY` | | `ERR_NOT_READY` | SDK ready 失败后继续调用命令 | | `ERR_DESTROYED` | SDK 实例已销毁 | | `ERR_IFRAME_LOAD` | iframe 加载失败 | | `ERR_UNAUTHORIZED` | Origin 校验失败 | | `ERR_UNSUPPORTED` | 当前基座不支持该命令 | | `ERR_NO_PATH` | 路径规划无可达路线 | | `ERR_FLOOR_NOT_FOUND` | 楼层不存在或未发布 | | `ERR_NETWORK` | 网络或接口异常 | ## 14. 废弃方法 以下方法保留签名用于兼容旧接入方,新项目不要使用: | 方法 | 状态 | 替代方案 | |------|------|----------| | `getReleaseManifest()` | 已废弃,返回 `ERR_UNSUPPORTED` | `getManifest()` | | `getModelResources()` | 已废弃,返回 `ERR_UNSUPPORTED` | `loadFloorBundle()` | | `getLayerTree()` | 已废弃,返回 `ERR_UNSUPPORTED` | 暂无 | | `loadMockReleaseRoute()` | 已废弃,返回 `ERR_UNSUPPORTED` | `planRoute()` | ## 15. 第三方接入检查清单 - 页面中存在 SDK 挂载容器,且容器有稳定宽高。 - `sdkUrl` 可在浏览器直接访问,并能加载独立发布的 `/engine/index.html`。 - `targetOrigin` 与 `sdkUrl` 的 Origin 一致。 - 所有地图控制 API 在 `await map.whenReady()` 后调用。 - 坐标统一使用 GLB/Three.js 米制坐标,水平面为 `x/z`。 - 页面卸载时调用 `map.destroy()`。 - 生产发布时 SDK、Engine 与后端 Manifest 的 `sdkVersion` 必须保持兼容;本次 Bridge 为 `2.5.0`,上线前需验证 `/engine/index.html` 真实加载 SDK Engine 并完成 `HELLO` -> `ENGINE_READY`。