venus-amap
v0.1.6
Published
Amap utils library
Readme
venus-amap
目录:
packages/venus-amap| npm 包名:venus-amap
高德地图(AMap JSAPI v2)工具库,封装自定义重投影底图、矢量线/面图层、MassMarks 海量点管理、动画标注与交互。
特性
- 自定义重投影底图:基于
AMap.TileLayer.Flexible,把以EPSG:4326切片的杭州规自瓦片在GCJ02下逐瓦片重采样拼接,支持暗色/亮色,内置图片缓存。 - MassMarks 海量点:按状态值生成多套样式(默认 + 激活),支持伴生线/面图层、悬停信息窗、动态动画标注。
- 矢量线/面图层:将业务数据组装为
Polyline/Polygon装入OverlayGroup,支持点击高亮。 - 单例地图实例:内部维护全局
instance,其上挂载_massMarksLayers统一管理海量点图层。 - 事件总线:内置
mitt实例emitter。
项目结构
packages/venus-amap/
├── src/
│ ├── base-layer.ts # EPSG:4326 瓦片重投影与自定义底图
│ ├── create-amap.ts # 高德地图单例的创建、获取和销毁
│ ├── emitter.ts # mitt 事件总线
│ ├── layer-utils.ts # 矢量图层、MassMarks 与动画标注
│ ├── types.ts # 地图、图层和业务数据类型
│ └── index.ts # 唯一公共 API 入口
├── test/ # node:test 回归测试
├── package.json # 包入口、依赖和构建脚本
├── tsdown.config.ts # ESM/CJS 与类型声明构建配置
└── README.md # 安装、API 与使用约定安装
pnpm add venus-amap gcoord使用前需在页面中先异步加载高德 JSAPI v2(全局
AMap)。@amap/amap-jsapi-types仅作类型提示(开发依赖)。
快速开始
import { createAMapInstance, addMassMarksLayer, emitter } from 'venus-amap'
const map = createAMapInstance('map-container', {
zoom: 10,
center: [119.72, 29.95],
layerStyle: 'dark'
})
const add = addMassMarksLayer(
(baseUrl) => (name, ext) => `${baseUrl}/${name}${ext}`
)
const layer = add(dataList, {
baseUrl: '/icons',
markerIcon: 'alarm',
markerSize: [32, 32],
statusNum: 5,
isDynamic: true
})
emitter.on('marker-click', (data) => console.log('点位点击:', data))
emitter.on('layer-click', (extData) => console.log('矢量点击:', extData))接口(API)详解
一、地图管理(create-amap.ts)
createAMapInstance(container?, mapConfig?)
创建地图单例(已存在则复用)。默认挂载自定义底图,mapConfig.layerStyle === 'dark' 时用暗色瓦片。创建后会初始化 instance._massMarksLayers = []。
function createAMapInstance(
container?: string, // 默认 'container',地图容器 DOM id
mapConfig?: CustomMapOptions // 见下;含高德 MapOptions + layerStyle
): CustomMap
interface CustomMapOptions extends AMap.MapOptions {
layerStyle?: string // 'dark' 使用暗色底图
}mapConfig 默认值(节选):{ pitch: 0, zoom: 9.25, zooms: [9.25, 20], viewMode: '3D', dragEnable: true, pitchEnable: false, center: [119.72, 29.95], layerStyle: 'dark' }。
未传 mapConfig.layers 时自动创建与 layerStyle 匹配的自定义底图;显式传入 layers 时完全使用调用方图层,不再额外添加默认底图。
const map = createAMapInstance('map', {
zoom: 11,
center: [120.2, 30.3],
layerStyle: 'dark'
})getAMapInstance(container?)
function getAMapInstance(container?: string): CustomMap // 不存在则创建,默认 'container'resetZoomAndCenter(center?)
function resetZoomAndCenter(center?: [number, number]): void // 动画复位到 zoom 9.25resetMap(config?)
function resetMap(config?: {
center?: [number, number]
isClearAll?: boolean
}): void
// 默认 { center: 上次中心, isClearAll: true }清除图层(removeAllLayers)并复位视图。
disposeMap()
function disposeMap(): void // instance.destroy() 后置空instance
let instance: CustomMap // 含 _massMarksLayers?: MassMarks[]二、自定义底图(base-layer.ts)
createBaseImageLayer(baseConfig?, isDark?)
function createBaseImageLayer(
baseConfig?: BaseLayerConfig, // 默认内置 layerConfig(杭州规自暗色,多路 upstream)
isDark?: boolean // 默认 true;false 时把 upstream 中的 '_dark' 去掉
): AMap.TileLayer // 实为 CustomFlexibleLayer,_layerName = 'baseImageLayer'
type BaseLayerConfig = {
tileSize: number
cacheSize: number
resolutions: number[]
origin: [number, number]
upstream: string[]
bounds: [[number, number], [number, number]]
}实现原理:AMap.TileLayer.Flexible 的 createTile 中——根据请求瓦片 XYZ 计算其 WGS84 四至 → GCJ02 → WGS84(gcoord)→ 反算源瓦片行列号与像素偏移 → 按缩放比例从 upstream 拉取源瓦片并 drawImage 拼接到画布;ImgLoader 负责跨域加载,每个图层实例按 cacheSize 独立缓存图片(有限非负整数,最大 5000)。
const base = createBaseImageLayer() // 暗色
base.setMap(map)
// 或在 createAMapInstance 的 mapConfig.layers 中传入三、矢量线/面(layer-utils.ts)
createVectorLineLayer(dataList?, config)
function createVectorLineLayer(
dataList: any[],
config: LineConfig
): AMap.OverlayGroup
type LineConfig = {
key?: string // 坐标字段名,默认 'facilitytrajectory'
width?: number // 线宽,默认 4
isRaw?: boolean // 是否保留原始 options(重置时复原)
openClick?: boolean // 是否点击高亮,默认 true
strokeColor?: string
strokeStyle?: string // 'solid' | 'dashed'
}把数据组装为 Polyline 列表装入 OverlayGroup(_isCustom = true)。openClick 时点击派发 layer-click(载荷为 getExtData())。每个 Polyline 附带 _id / _uuid / _isActive / _isRaw / _options。
createVectorFaceLayer(dataList?, config)
function createVectorFaceLayer(
dataList: any[],
config: {
key?: string // 默认 'coordinates'
fillColor?: string
fillOpacity?: number // 默认 1
strokeColor?: string
strokeWeight?: number
strokeStyle?: string // 默认 'solid'
colorKey?: string // 按字段值取色
colorMap?: Map<any, string>
isRaw?: boolean
openClick?: boolean
}
): AMap.OverlayGroup把数据组装为 Polygon 列表装入 OverlayGroup,点击派发 layer-click。
resetActiveVector(type?)
function resetActiveVector(type?: string): void // 默认 'polygon'重置当前激活的矢量要素:原始要素复原配置、非原始要素从地图移除,并移除 _layerName === 'river-marker' 的附带图层。
四、MassMarks 海量点(layer-utils.ts)
buildMassMarksStyles(getImgUrlFn)
function buildMassMarksStyles(
getImgUrlFn: GetImgUrlFn
): (iconConfig: IconConfig) => AMap.MassMarkersStyleOptions[]
type GetImgUrl = (name: string, ext?: string) => string
type GetImgUrlFn = (baseUrl: string) => GetImgUrl按 statusNum 生成「默认 + 激活」样式数组(长度 statusNum * 2),图标地址按 ${markerIcon}-${i} / ${markerIcon}-${i}-active(.webp)拼接。
createMassMarksLayer(dataList, styleList?, openClick?)
function createMassMarksLayer(
dataList: MassData[],
styleList?: AMap.MassMarkersStyleOptions[],
openClick?: boolean // 默认 true
): AMap.MassMarks创建 AMap.MassMarks(zIndex: 240),openClick 时绑定点击(派发 marker-click)与悬停信息窗。图层会被推入 instance._massMarksLayers,并标记 _isMassMarksLayer、_statusNum、_dataList。
addMassMarksLayer(getImgUrlFn)
function addMassMarksLayer(
getImgUrlFn: GetImgUrlFn
): (
dataList?: MassData[],
iconConfig: IconConfig,
openClick?: boolean
) => AMap.MassMarks
type IconConfig = {
baseUrl: string
markerIcon: string
markerSize: [number, number]
statusNum: number
hasLine?: boolean // 附带折线图层
hasFace?: boolean // 附带多边形图层
isDynamic?: boolean // 激活时附加动画标注
activeScale?: number // 激活图标缩放,默认 1.3
}生成样式 → 创建海量点图层 → 按 hasLine/hasFace 追加伴生矢量图层 → setMap(instance)。
const add = addMassMarksLayer((baseUrl) => (n, e) => `${baseUrl}/${n}${e}`)
add(dataList, {
baseUrl: '/icons',
markerIcon: 'alarm',
markerSize: [32, 32],
statusNum: 5,
hasLine: true
})updateMarksLayersByStatus(checkedStatusList?)
function updateMarksLayersByStatus(checkedStatusList?: any[]): MassData[]按状态字段(优先 _status,仅在其为 null/undefined 时回退 status)过滤各海量点图层数据并 setData,同步显隐该 MassMarks 自己的伴生线图层;返回过滤后的数据集合。
createAnimationMarker(lnglat, config)
function createAnimationMarker(
lnglat: AMap.LngLat,
config: {
alarmLevel: number | string
getAnimationUrl: GetImgUrl
size: [number, number]
}
): AMap.Marker // _isAnimation = true创建动画标注 Marker(图标地址 marker-${alarmLevel}-active.png)。
resetActiveMarker()
function resetActiveMarker(): void把所有激活海量点图层的样式索引复位(style -= _statusNum)并移除动画标注 Marker。
activeMarkerByUid(getAnimationUrl)
function activeMarkerByUid(
getAnimationUrl: GetImgUrl
): (uid: string, setFitView?: boolean) => void高阶函数:先复位激活态,再按 _uuid 在各海量点图层中将该点样式切到激活段(style + _statusNum);setFitView 默认聚焦该点;动态图层会附加动画标注。
const active = activeMarkerByUid((n, e) => `/icons/${n}${e}`)
active('uuid-123', true)removeAllLayers(isClearAll?)
function removeAllLayers(isClearAll?: boolean): void // 默认 true清空并移除所有海量点图层、按需 clearMap(),并移除带 _isCustom 的图层。
五、事件总线(emitter)
import { emitter } from 'venus-amap'| 事件名 | 载荷 | 触发时机 |
| -------------- | ------------------------- | ------------------- |
| layer-click | extData(要素 extData) | 点击矢量线/面要素 |
| marker-click | data | 点击 MassMarks 点位 |
六、类型定义(export * from './types')
主要类型(多为 AMap.* 扩展,附带内部标记):
interface CustomMap extends AMap.Map {
_massMarksLayers?: MassMarks[]
}
interface CustomMapOptions extends AMap.MapOptions {
layerStyle?: string
}
interface MassData extends AMap.MassData {
style?: number
_uuid?: string
lnglat: any
status?: number | string
_status?: number | string
}
interface MassMarks extends AMap.MassMarks {
_uuid?: string
_isCustom?: boolean
_hasLine?: boolean
_hasFace?: boolean
_isActive?: boolean
_statusNum?: number
_isDynamic?: boolean
_hasActive?: boolean
_dataList?: MassData[]
_isMassMarksLayer?: boolean
}
interface Polyline extends AMap.Polyline {
_id?
_uuid?
_isRaw?
_options?
_isActive?
}
interface Polygon extends AMap.Polygon {
_id?
_uuid?
_isRaw?
_options?
_isActive?
}还包括 LngLat、BaseLayerConfig、LineConfig、IconConfig、Marker、TileLayer、OverlayGroup、FlexibleLayerOptions 等。
构建
pnpm --dir packages/venus-amap build # 或仓库根 pnpm build:amap
pnpm --dir packages/venus-amap check:types # tsc --noEmit,目前覆盖 src
pnpm --dir packages/venus-amap test # build + check:types + node:test
pnpm --dir packages/venus-amap dev注意事项
- 依赖全局
AMap:使用前确保 JSAPI v2 已加载完成。 - 单例副作用:先
createAMapInstance/getAMapInstance,再调用其它依赖instance的函数。 - 上游底图地址在
base-layer.ts的layerConfig中配置(默认指向杭州城市大脑服务)。
