Skip to content

地图 Map

createMap 工厂函数和 MapModel 类是标准版 API 的入口,负责地图的创建、配置和生命周期管理。

createMap(工厂函数)

异步工厂函数,创建地图并在返回前完成引擎延迟加载与首帧就绪。

ts
async function createMap(options: MapOptions): Promise<MapModel>;

MapOptions 接口

ts
interface MapOptions {
  target: string | HTMLElement;     // 地图容器 ID 或 DOM 元素
  engine: EngineId;                 // 引擎标识:'ol' | 'maplibre' | 'cesium'
  center?: Coordinate;              // 初始中心 [经度, 纬度]
  zoom?: number;                    // 初始缩放级别
  bearing?: number;                 // 初始方位角(度)
  pitch?: number;                   // 初始俯仰角(度)
  basemap?: string;                 // 底图标识
  style?: string | StyleSpec;       // 地图样式
  maxZoom?: number;                 // 最大缩放
  minZoom?: number;                 // 最小缩放
  bounds?: Extent;                  // 初始视图范围
  controls?: ControlOptions[];      // 初始控件
  layers?: LayerOptions[];          // 初始图层
  sources?: SourceOptions[];        // 初始数据源
  // ... 更多选项
}

示例

ts
import { createMap } from '@gmap/standard';

// 基本创建
const map = await createMap({
  target: 'map-container',
  engine: 'ol',
  center: [116.397, 39.908],
  zoom: 12,
});

// 使用 MapLibre 引擎
const map2 = await createMap({
  target: 'map2',
  engine: 'maplibre',
  style: 'https://demotiles.maplibre.org/style.json',
});

// 使用 Cesium 引擎(3D)
const map3 = await createMap({
  target: 'map3',
  engine: 'cesium',
  center: [116.397, 39.908],
  zoom: 15,
  pitch: 45,
});

MapModel

地图模型,管理地图的所有状态和操作。由 createMap 返回,也可直接实例化。

属性

属性类型说明
engineEngineId当前引擎标识
readyboolean是否就绪

视图控制方法

方法参数返回值说明
setCenter(center)center: Coordinatethis设置中心点
getCenter()Coordinate获取中心点
setZoom(zoom)zoom: numberthis设置缩放级别
getZoom()number获取缩放级别
zoomIn()this放大一级
zoomOut()this缩小一级
setBearing(bearing)bearing: numberthis设置方位角
getBearing()number获取方位角
setPitch(pitch)pitch: numberthis设置俯仰角
getPitch()number获取俯仰角
setView(options)options: { center?, zoom?, bearing?, pitch? }this设置完整视图
getView()ViewState获取当前视图状态
fitBounds(extent, options?)extent: Extent, options?: objectthis适配到指定范围
flyTo(options)options: { center, zoom?, duration?, ... }this飞行动画到目标位置
ts
interface ViewState {
  center: Coordinate;
  zoom: number;
  bearing: number;
  pitch: number;
}

示例

ts
// 基本视图控制
map.setCenter([117.0, 40.0]);
map.setZoom(14);

// 动态获取
const center = map.getCenter();
const zoom = map.getZoom();
console.log(`当前视图: ${center}, zoom=${zoom}`);

// 适配到范围
map.fitBounds([116.0, 39.0, 117.0, 40.0], { padding: 50 });

// 飞行到目标
map.flyTo({
  center: [121.473, 31.230],
  zoom: 15,
  bearing: 30,
  pitch: 60,
  duration: 2000,
});

// 完整视图设置
map.setView({
  center: [116.397, 39.908],
  zoom: 12,
  bearing: 0,
  pitch: 45,
});

const view = map.getView();

图层管理方法

方法参数返回值说明
addLayer(layer, beforeId?)layer: Layer, beforeId?: stringthis添加图层
removeLayer(id)id: stringthis移除图层
getLayer(id)id: stringLayer | undefined获取图层
getLayers()Layer[]获取所有图层
moveLayer(id, beforeId)id: string, beforeId: stringthis移动图层顺序

示例

ts
import { TileLayer, FeatureLayer, RasterTileSource, GeoJsonSource, SimpleRenderer, FillSymbol } from '@gmap/standard';

// 添加栅格瓦片图层
const osmSource = new RasterTileSource({
  url: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png',
});
const osmLayer = new TileLayer({ id: 'osm', source: osmSource });
map.addLayer(osmLayer);

// 添加要素图层
const data = new GeoJsonSource({ id: 'districts', data: districtsGeoJSON });
const featureLayer = new FeatureLayer({
  id: 'districts',
  source: data,
  renderer: new SimpleRenderer({
    symbol: new FillSymbol({ color: '#3388ff', opacity: 0.5 }),
  }),
});
map.addLayer(featureLayer, 'osm'); // 在 osm 图层下方插入

// 获取图层
const layer = map.getLayer('districts');
const allLayers = map.getLayers();
console.log(`共 ${allLayers.length} 个图层`);

// 移动图层
map.moveLayer('districts', 'osm');

// 移除图层
map.removeLayer('districts');

数据源管理方法

方法参数返回值说明
addSource(source)source: Sourcethis添加数据源
getSource(id)id: stringSource | undefined获取数据源
removeSource(id)id: stringthis移除数据源

示例

ts
import { RasterTileSource, GeoJsonSource } from '@gmap/standard';

const source = new RasterTileSource({
  id: 'my-tiles',
  url: 'https://server/{z}/{x}/{y}.png',
});

map.addSource(source);

const retrieved = map.getSource('my-tiles');
map.removeSource('my-tiles');

底图与样式方法

方法参数返回值说明
setBasemap(basemap)basemap: stringthis切换底图
setStyle(style)style: string | StyleSpecthis设置地图样式
getStyle()StyleSpec获取当前样式

示例

ts
// 切换底图
map.setBasemap('satellite');

// 设置样式
map.setStyle({
  version: 8,
  sources: {
    'my-source': { type: 'geojson', data: myGeoJSON },
  },
  layers: [
    { id: 'my-layer', type: 'fill', source: 'my-source' },
  ],
});

const style = map.getStyle();

控件管理方法

方法参数返回值说明
addControl(control)control: Controlthis添加控件
removeControl(id)id: stringthis移除控件

示例

ts
import { ZoomControl, ScaleBarControl, Legend } from '@gmap/standard';

map.addControl(new ZoomControl({ position: 'top-left' }));
map.addControl(new ScaleBarControl({ position: 'bottom-left' }));
map.addControl(new Legend({ position: 'bottom-right' }));

map.removeControl('ctrl-xxx');

交互管理方法

方法参数返回值说明
addInteraction(interaction)interaction: Interactionthis添加交互
removeInteraction(id)id: stringthis移除交互

查询与选取方法

方法参数返回值说明
pick(pixel, options?)pixel: Pixel, options?: objectPickResult | null像素拾取
boxSelect(bounds)bounds: ExtentFeature[]框选要素
ts
interface PickResult {
  feature: Feature;
  layer: Layer;
  coordinate: Coordinate;
  distance: number;
}

示例

ts
// 像素拾取
map.on('click', (e) => {
  const result = map.pick(e.pixel);
  if (result) {
    console.log('拾取到要素:', result.feature);
    console.log('所在图层:', result.layer.id);
    console.log('点击坐标:', result.coordinate);
  }
});

// 框选
const selected = map.boxSelect([116.3, 39.9, 116.5, 40.0]);
console.log(`选中 ${selected.length} 个要素`);

事件方法

方法参数返回值说明
on(type, handler)type: string, handler: Functionthis绑定事件
once(type, handler)type: string, handler: Functionthis绑定一次性事件
off(type, handler?)type: string, handler?: Functionthis解绑事件
emit(type, data?)type: string, data?: unknownthis触发自定义事件

事件列表

事件回调参数说明
'click'{ pixel, coordinate, feature? }单击
'dblclick'{ pixel, coordinate, feature? }双击
'contextmenu'{ pixel, coordinate }右键
'mousemove'{ pixel, coordinate }鼠标移动
'mouseenter'{ pixel, coordinate, feature? }鼠标进入要素
'mouseleave'{ pixel, coordinate, feature? }鼠标离开要素
'movestart'视图开始移动
'moveend'视图移动结束
'zoomstart'缩放开始
'zoomend'缩放结束
'resize'{ width, height }地图容器尺寸变化
'load'地图加载完成
'error'{ message, error }错误

示例

ts
// 监听点击
map.on('click', (e) => {
  console.log('点击坐标:', e.coordinate);
  if (e.feature) {
    console.log('点击要素:', e.feature.properties);
  }
});

// 监听移动结束
map.once('moveend', () => {
  console.log('视图移动完成');
  const center = map.getCenter();
  console.log('当前中心:', center);
});

// 自定义事件
map.on('data-loaded', (e) => {
  console.log('自定义事件:', e);
});
map.emit('data-loaded', { source: 'my-source' });

// 解绑事件
const handler = (e) => console.log(e);
map.on('click', handler);
map.off('click', handler);

工具方法

方法参数返回值说明
whenReady()Promise<void>等待地图就绪
resize()this手动触发尺寸更新
exportImage(options?)options?: objectPromise<string>导出地图为图片(DataURL)
getStats()object获取地图统计信息
destroy()void销毁地图,释放资源

示例

ts
// 等待就绪
await map.whenReady();
console.log('地图已就绪');

// 导出图片
const imageData = await map.exportImage({
  width: 1920,
  height: 1080,
  format: 'png',
});
// imageData 是 base64 DataURL

// 获取统计
const stats = map.getStats();
console.log(stats);
// { layers: 5, sources: 3, features: 1234, ... }

// 销毁
map.destroy();

引擎切换方法

方法参数返回值说明
switchEngine(engine)engine: EngineIdPromise<void>切换渲染引擎
ts
interface SwitchEngineOptions {
  engine: EngineId;
  preserveState?: boolean;
}

示例

ts
// 从 2D 切换到 3D
await map.switchEngine('cesium');

二三维共存

map.enterCoexistence(engineId, options)

进入二三维共存模式,创建辅助引擎与当前引擎并存。

  • engineId — 辅助引擎 ID(如 'cesium''openlayers''maplibre'
  • optionsCoexistenceOptions 配置
typescript
const coex = await map.enterCoexistence('cesium', {
  mode: 'over-map',        // 'over-map' | 'side-by-side'
  cameraSync: true,         // 自动同步相机
  pauseInteractions: true,  // 暂停主引擎交互
});

map.exitCoexistence()

退出共存模式,销毁辅助引擎。

typescript
map.exitCoexistence();

map.toggle3D()

切换辅助引擎的显示/隐藏。

typescript
map.toggle3D();
const coex = map.getCoexistence();
console.log(coex?.isEnabled()); // true or false

map.getCoexistence()

获取共存管理器实例(如果处于共存模式)。

typescript
const coex = map.getCoexistence();
if (coex) {
  coex.setMode('side-by-side');
  coex.on('toggle', ({ enabled }) => { ... });
}

CoexistenceOptions

属性类型默认值说明
mode'over-map' | 'side-by-side'共存模式
targetSecondarystring | HTMLElementside-by-side 模式的容器
cameraSyncbooleantrue是否自动同步相机
syncDirection'primary-to-secondary' | 'secondary-to-primary' | 'bidirectional''bidirectional'同步方向
pauseInteractionsbooleantrue是否暂停主引擎交互
refreshPrimaryAfterMoveEndOnlybooleanfalse只在相机停止后同步主引擎

CoexistenceManager

方法说明
toggle()切换辅助引擎启用/禁用
enable()启用辅助引擎
disable()禁用辅助引擎
setMode(mode)切换共存模式
getState()获取当前状态
isEnabled()是否已启用
getPrimaryAdapter()获取主引擎适配器
getSecondaryAdapter()获取辅助引擎适配器
on(type, handler)监听事件(togglemode-change
off(type, handler?)移除监听
destroy()销毁所有资源

完整示例

ts
import {
  createMap,
  TileLayer, FeatureLayer, GraphicsLayer,
  RasterTileSource, GeoJsonSource,
  SimpleRenderer, FillSymbol, LineSymbol,
  ZoomControl, ScaleBarControl, Legend, SearchControl,
  DrawInteraction, MeasureInteraction,
  Popup,
  Style,
} from '@gmap/standard';

// 1. 创建地图
const map = await createMap({
  target: 'map',
  engine: 'ol',
  center: [116.397, 39.908],
  zoom: 12,
});

// 2. 添加底图
const osmSource = new RasterTileSource({
  url: 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
  subdomains: ['a', 'b', 'c'],
});
map.addLayer(new TileLayer({ id: 'osm', source: osmSource }));

// 3. 添加数据图层
const data = new GeoJsonSource({
  id: 'districts',
  data: districtsGeoJSON,
  cluster: true,
  clusterRadius: 50,
});

const layer = new FeatureLayer({
  id: 'districts',
  source: data,
  renderer: new SimpleRenderer({
    symbol: new FillSymbol({ color: '#3388ff', opacity: 0.6 }),
  }),
});
map.addLayer(layer);

// 4. 添加控件
map.addControl(new ZoomControl({ position: 'top-left' }));
map.addControl(new ScaleBarControl({ position: 'bottom-left' }));
map.addControl(new Legend({ position: 'bottom-right', layer }));
map.addControl(new SearchControl({
  position: 'top-center',
  onSelect: (result) => map.flyTo({ center: result.location, zoom: 15 }),
}));

// 5. 添加绘制交互
const draw = new DrawInteraction({ mode: 'polygon' });
map.addInteraction(draw);
draw.on('drawend', (e) => console.log('绘制完成:', e.feature));

// 6. 添加量算交互
const measure = new MeasureInteraction({ mode: 'distance' });
map.addInteraction(measure);

// 7. 事件监听
map.on('click', (e) => {
  const result = map.pick(e.pixel);
  if (result) {
    new Popup()
      .setPosition(result.coordinate)
      .setContent(`<strong>${result.feature.properties.name}</strong>`)
      .open();
  }
});

// 8. 视图操作
map.flyTo({ center: [121.473, 31.230], zoom: 15, duration: 2000 });

// 9. 导出
const image = await map.exportImage();

// 10. 清理
// map.destroy();

MapModel 与核心类型

类型来源说明
MapModel@gmap/core地图模型
Layer@gmap/core图层基类
Source@gmap/core数据源基类
Feature@gmap/core要素
EngineRegistry@gmap/core引擎注册表
MockAdapter@gmap/core模拟适配器(测试用)
ViewSync@gmap/core多视图同步
Coordinate@gmap/core[lng, lat][lng, lat, alt]
Pixel@gmap/core[x, y]
Extent@gmap/core[west, south, east, north]
ViewState@gmap/core视图状态
PickResult@gmap/core拾取结果
EngineId@gmap/core'ol' | 'maplibre' | 'cesium'

四川省交通运输综合地理服务平台 地图开发框架