@teeechina/teee-map
v0.1.5
Published
基于 maplibre-gl 封装的业务地图 SDK,面向太昌 GIS 业务流提供开箱即用的地图初始化、图层管理、要素状态控制及加密瓦片支持。
Readme
TeeeMap SDK
基于 maplibre-gl 二次封装的铁路业务地图 SDK(
@teeechina/teee-map),面向太昌(TeeChina)GIS 业务流提供开箱即用的地图初始化、图层管理、要素状态控制、铁路联锁可视化及加密瓦片支持。
特性
- 🗺️ 多种地图类型开箱即用:站场平面图(graph)、站场地理图(geom)、GeoJSON 地图、区间地图、混合地图(区间 + 站场)、影像图、人员定位图(RSWP)
- 🚂 铁路要素状态管理:按要素
code维护业务状态(股道封锁、道岔锁闭、信号机灯色等),并自动同步到map.setFeatureState - 🚦 联锁可视化:解析联锁信号协议,驱动信号机 / 道岔 / 电路区段状态展示,支持白光带与控车发令
- 🔒 加密瓦片支持:自动混淆瓦片 XYZ 坐标,支持加密矢量 / 栅格瓦片服务
- 📐 测量工具:距离测量、面积测量
- ✨ 要素交互:点击事件绑定、要素定位、平滑闪烁高亮
- 🎨 Canvas 图标生成:信号机、土挡、脱轨器、通道门、机车等铁路图标动态绘制
- 🧭 坐标工具:EPSG:3857 ↔ WGS84 坐标转换、属性字段兼容、要素偏移、图标垂直股道角度计算
- 💪 TypeScript 支持:完整类型定义与枚举,内置 API 文档生成
技术栈
| 依赖 | 说明 | | --- | --- | | maplibre-gl ^6.0.0 | 底层地图引擎(peer 依赖,需自行安装) | | @turf/turf | 空间计算(bbox、测距、测面积等) | | @mapbox/vector-tile + pbf | 矢量瓦片 PBF 解码 | | tsup / TypeScript | 构建(同时产出 ESM 与 CJS) |
安装
# pnpm(推荐)
pnpm add @teeechina/teee-map maplibre-gl
# npm
npm install @teeechina/teee-map maplibre-glmaplibre-gl 是 peer 依赖,需要与应用同时安装。
快速开始
import { TeeeMap } from '@teeechina/teee-map'
import 'maplibre-gl/dist/maplibre-gl.css'
// 1. 创建地图实例
const teeeMap = new TeeeMap('map-container')
// 2. 创建站场平面图(矢量瓦片服务)
teeeMap.createGraphMap('STATION_CODE', 'https://your-server/wapian/{z}/{x}/{y}.pbf', [
'background', // 背景
'track', // 股道
'signal', // 信号机
'switch', // 道岔
'track_circuit', // 轨道电路区段
'bumper', // 土挡
'insulation', // 绝缘节
'label', // 标注
'prevention' // 防控点
])
// 3. 等待要素缓存就绪后更新业务状态
await teeeMap.whenStashed()
teeeMap.updateFeatureState('TRACK_CODE', { state: 1, visiable: true })
// 4. 使用完毕后销毁
teeeMap.destroy()地图创建方式
TeeeMap 提供以下 create* 方法,按数据来源与用途选择:
| 方法 | 说明 |
| --- | --- |
| createGraphMap(stcode, url, layers) | 站场平面图(矢量瓦片,TMS 方案) |
| createGeomMap(stcode, url, layers) | 站场地理图(矢量瓦片) |
| createGeomEncryptedMap(stcode, url, layers) | 加密站场地理图(自动注入瓦片解密) |
| createGeoJsonStationMap(stationDatas) | GeoJSON 站场平面图(自动 3857 → 4326 转换) |
| createGeoJsonGeomStationMap(stationDatas, showImage) | GeoJSON 站场地理图(可叠加高德影像底图) |
| createGeoJsonRegionMap(regionCode, regionDatas) | GeoJSON 区间平面图 |
| createMixGeoJsonMap(mapDatas) | 混合平面图(区间 + 站场,支持偏移校正) |
| createMixGeoJsonGeomMap(mapDatas, showImage) | 混合地理图(区间 + 站场 + 影像底图) |
| createRasterMap(url) | 影像 / 栅格底图 |
| createEncryptedRasterMap(url) | 加密影像底图 |
| createRSWPMap(url) | 人员定位图(影像底图 + GeoJSON 附源) |
| createSscsGraphMap(url) | 调度集中(SSCS)平面图,配套 setSscsPointState(code, state) |
站场地理图
teeeMap.createGeomMap('STATION_CODE', 'https://your-server/wapian/{z}/{x}/{y}.pbf', [
'background',
'track',
'signal',
'switch',
'track_circuit',
'bumper',
'prevention'
])加密地图
// 加密矢量瓦片:自动混淆瓦片 XYZ 坐标后请求
teeeMap.createGeomEncryptedMap('STATION_CODE', 'https://your-server/wapian/{z}/{x}/{y}.pbf', layers)
// 加密栅格瓦片
teeeMap.createEncryptedRasterMap('https://your-server/wapian/{z}/{x}/{y}.png')GeoJSON 站场平面图
数据可为 GeoJSON.FeatureCollection 对象或数据 URL(fetch 获取)。EPSG:3857 坐标会被自动转换为 WGS84。
await teeeMap.createGeoJsonStationMap([
{ name: 'track', data: trackFeatureCollection }, // 股道
{ name: 'signal', data: 'https://your-server/signal.geojson' }, // 信号机
{ name: 'switch', data: switchFeatureCollection }, // 道岔
{ name: 'track_circuit', data: circuitFeatureCollection }, // 电路区段
{ name: 'bumper', data: bumperFeatureCollection }, // 土挡
{ name: 'insulation', data: insulationFeatureCollection } // 绝缘节
])混合地图(区间 + 站场)
await teeeMap.createMixGeoJsonMap([
{
code: 'REGION_CODE',
type: 'region', // 区间
geojsonData: [
{ name: 'background', data: '...' },
{ name: 'track', data: '...' },
{ name: 'bridge', data: '...' },
{ name: 'tunnel', data: '...' },
{ name: 'region_signal', data: '...' } // 区间信号机
]
},
{
code: 'STATION_CODE',
type: 'station', // 站场
geojsonData: [
{ name: 'background', data: '...' },
{ name: 'track', data: '...' },
{ name: 'signal', data: '...' },
{ name: 'switch', data: '...' }
],
deltaInfo: { deltax: 120, deltay: -80 } // 可选:站场相对区间的坐标偏移
}
])核心能力
要素缓存与就绪等待
地图构建是异步的(source/layer 注册 → 首次 idle → 全量要素缓存)。在缓存就绪前调用状态初始化会静默失效,因此请先等待就绪:
// Promise 风格
await teeeMap.whenStashed(30000) // 默认 30s 超时
// 回调风格
teeeMap.onStashReady(() => {
teeeMap.initGeoJsonState!() // 初始化 GeoJSON 图层业务状态
})相关 API:
stashAllFeature()/stashMixMapAllFeature()— 手动刷新要素缓存fetchAllTiles(zoom?)— 拉取当前范围所有矢量瓦片(PBF 解码),突破querySourceFeatures的视口限制
要素状态管理
所有要素状态按 code 维护在缓存池中,并同步到 map.setFeatureState,图层 paint 可通过 ['feature-state', ...] 表达式驱动渲染:
// 更新状态(兼容矢量瓦片源与 GeoJSON 源)
teeeMap.updateFeatureState('TRACK_CODE', { state: 1, select: true, visiable: true })
// 读取状态
const state = teeeMap.getFeatureState('TRACK_CODE')内置 stateType 定义了常用业务状态字段:state(股道封锁 1 / 停电 2 / 无接触网 3)、select(选中)、visiable(可见)及信号机 / 道岔的 subState1 ~ subState4。
要素查询与定位
// 按图层类型查询全部要素
const signals = teeeMap.queryGeojsonFeatures('signal')
// 按 code + 图层类型查询要素
const feature = teeeMap.getGeojsonLayerFeaturesByCode('SIGNAL_CODE', 'signal')
// 按电路区段 code 列表查询
const circuits = teeeMap.getTrackCircuitFeaturesByCodes(['C1', 'C2'])
// 定位:地图缩放至要素 / 数据范围
teeeMap.locateFeatureByCode('SIGNAL_CODE', 'signal')
teeeMap.locateGeojsonFeature(featureCollection)闪烁高亮
对线 / 点要素添加平滑正弦闪烁动画,动画结束自动清理临时图层:
const cleanup = teeeMap.smoothBlinkFeature('SIGNAL_CODE', 'signal', {
duration: 3000, // 总时长 ms
blinkSpeed: 500, // 闪烁周期 ms
baseColor: [255, 0, 0], // RGB 颜色
minAlpha: 0.3,
maxAlpha: 0.7
})
// 提前终止闪烁
cleanup?.()测量工具
创建任意业务地图后自动挂载 measureTool:
teeeMap.measureTool?.startDistance() // 开始距离测量
teeeMap.measureTool?.startArea() // 开始面积测量
teeeMap.measureTool?.clear() // 清除测量结果联锁可视化
GeoJSON 地图(createGeoJson* / createMixGeoJson*)与平面图(createGraphMap)创建后自动挂载 interLockVisualization,用于解析联锁信号协议并驱动站场状态展示:
const interlock = teeeMap.interLockVisualization
if (!interlock) return
// 初始化绝缘节 → 信号机映射
interlock.initInsulation()
// 处理一帧联锁信号数据
// 协议格式:时间&站码[&厂家信息]&信号机&道岔&区段
interlock.handleSignalData('12:00:00&STATION_CODE&X1:1;X2:2&S1:2;S2:3&C1:1;C2:4')
// 全部信号机灭灯
interlock.turnOffSignals()
// 采集当前状态并发送控车指令
interlock.setSendSignalCallback((dataList) => {
console.log('发送控车指令:', dataList)
})
interlock.sendSignal()联锁模块由三个类构成:
| 类 | 说明 |
| --- | --- |
| InterlockProtocol | 联锁信号协议解析器(时间&站码[&厂家信息]&信号机&道岔&区段) |
| InterLockVisualization | 联锁可视化引擎:状态驱动、白光带计算、控车发令 |
| InterLockInsulation | 绝缘节 ↔ 信号机双向映射管理 |
图层 / 源动态管理
baseTool 在实例化时自动挂载以下方法:
// 源管理
teeeMap.addVectorTileSource('vector-src', 'https://.../{z}/{x}/{y}.pbf')
teeeMap.addRasterTileSource('raster-src', 'https://.../{z}/{x}/{y}.png')
teeeMap.addGeoJsonSource('geojson-src', featureCollection)
teeeMap.updateGeoJsonSource('geojson-src', newFeatureCollection)
teeeMap.getGeoJsonSourceData('geojson-src')
teeeMap.removeSource('geojson-src')
// 图层管理
teeeMap.addGeoJsonLayer('layer-id', 'geojson-src', 'circle', { 'circle-color': '#ff0000' })
teeeMap.updateLayerStyle('layer-id', { 'circle-color': '#00ff00' })
teeeMap.removeLayer('layer-id')
// 要素点击事件(自动处理鼠标指针样式)
teeeMap.onFeatureClick('layer-id', (feature, lngLat) => {
console.log(feature.properties, lngLat)
})源 / 图层工厂
除 TeeeMap 外,也可直接使用工厂类:
import { SourceFactory, LayerFactory, MapForge } from '@teeechina/teee-map'
const source = SourceFactory.graph('https://.../{z}/{x}/{y}.pbf') // 矢量瓦片源
SourceFactory.geojson(data) // GeoJSON 源
SourceFactory.raster(url) // 栅格源
SourceFactory.image(url, coordinates) // 图片源
SourceFactory.video(urls, coordinates) // 视频源
SourceFactory.canvas(canvasId, coordinates) // 画布源
const config = MapForge.geom(stcode, url, layers) // 地图配置
const layersSpec = LayerFactory.geom(config) // 图层样式坐标转换与角度工具
import {
transformGeoJsonFrom3857, // 3857 → 4326
transformGeoJsonProperties, // 属性字段兼容(如 map 与 PG 字段名差异)
offsetFeatureCollection, // 要素整体偏移(混合地图对齐)
getTrackBearing, // 计算点相对股道的方位角
attachTrackAngle // 将点要素图标旋转至垂直股道
} from '@teeechina/teee-map'
attachTrackAngle(map, {
sourceId: 'geojson_prevention',
pointSourceLayer: 'prevention',
trackSourceLayer: 'track',
layerId: 'prevention-symbol',
controlFeatures: preventionFeatures,
angleOffset: 0
})图标生成
内置 Canvas 图标生成器(实例化地图时自动注册全部图标):
import { canvasCreator, imageCreater } from '@teeechina/teee-map'
// 生成全部图标({ id, image } 数组)
const icons = await imageCreater.createAllIcons()
// 单个图标
canvasCreator.createSignalCanvas()
canvasCreator.createBumperCanvas()
canvasCreator.createDerailingStopCanvas()
canvasCreator.createCatenaryEndCanvas()
canvasCreator.createTrackDoorCanvas()
canvasCreator.createLocomotiveImg()枚举与常量
SDK 导出完整的业务枚举与常量:
import {
StationFeatureCodeEnums, // 站场要素代码(股道/道岔/信号机/土挡/...)
InterLockSignalStateEnums, // 联锁信号机状态(红/绿/白/蓝灯)
InterLockCircuitStateEnums, // 联锁电路区段状态(红/白/等效红/灰/绿)
InterLockSwitchlocStateEnums, // 联锁道岔状态(定位/反位/四开位)
BsSignalStateEnums, // 闭塞信号状态
SignalColorEnums, // 信号颜色
PreventionEnums, // 防控点类型
// 常量
INTERLOCK_SIGNAL_MAP,
INTERLOCK_CIRCUIT_MAP,
INTERLOCK_SWITCHLOC_MAP,
BS_SIGNAL_MAP,
INTERLOCK_SIGNAL_COLOR_MAP,
MapColor,
PREVENTION_TYPES
} from '@teeechina/teee-map'常用类型定义:
import type {
LayerType, // 站场图层类型:background/signal/track/track_circuit/bumper/switch/...
RegionLayerType, // 区间图层类型:background/track/bridge/tunnel/region_signal/curve/...
MapParams, // 地图构建参数
MapForgeConfig, // 地图配置
stateType // 要素业务状态
} from '@teeechina/teee-map'开发指南
pnpm dev # 开发模式(tsup 监听构建)
pnpm build # 构建产物(ESM + CJS + 类型声明)
pnpm typecheck # TypeScript 类型检查
pnpm lint # ESLint
pnpm format # Prettier 格式化
pnpm docs # 生成 API 文档(typedoc → docs/api)
pnpm pub # 发布到 npm目录结构
src/
├── index.ts # 包入口(统一导出)
├── core/
│ ├── teeeMap.ts # TeeeMap 主类:地图创建、要素缓存与状态
│ └── mapForge.ts # 地图配置工厂(graph/geom/geojson/raster/rswp/...)
├── modules/
│ ├── layer-factory/ # 图层工厂
│ │ ├── graph-layer/ # 平面图图层(vector)
│ │ ├── geom-layer/ # 地理图图层(vector)
│ │ ├── geojson-layer/ # 平面图图层(GeoJSON)
│ │ ├── geojson-geom-layer/ # 地理图图层(GeoJSON)
│ │ ├── raster-layer/ # 栅格图层
│ │ └── rswp-layer/ # 人员定位图图层
│ ├── source-factory/ # 数据源工厂(vector/raster/geojson/image/video/canvas)
│ ├── tool-factory/ # 工具挂载(base/graph/geojson/encrypt)
│ ├── interlock/ # 联锁模块(协议解析/可视化/绝缘节映射)
│ └── icon-creator/ # Canvas 图标生成(信号机/土挡/机车/...)
├── utils/
│ ├── coordTransform.ts # 坐标转换与属性兼容
│ ├── measure.ts # 测量工具(距离/面积)
│ └── setTrackAngle.ts # 图标垂直股道角度
├── enums/ # 业务枚举
├── constants/ # 颜色映射等常量
└── types/ # 公共类型定义