JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 546
  • Score
    100M100P100Q93280F
  • License MIT

一个基于cesium的地图工具包,支持使用天地图作为底图资源。用于在web上创建3D地图应用。目前还在开发中,敬请期待~

Package Exports

  • frost-map
  • frost-map/dist/frost-map.esm.js
  • frost-map/dist/frost-map.js

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (frost-map) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

Frost-Map

一个基于 Cesium 的 Vue 3 地图工具包,用于在 Web 上创建 3D 地图应用。

功能特性

  • 🗺️ 地图核心:封装 Cesium Viewer,提供完善的初始化时序控制
  • 🎨 Vue 组件:提供 Vue 3 地图组件,支持响应式绑定和天地图集成
  • 📍 视图控制:支持飞行定位、缩放、视角切换
  • 📐 测量工具:支持距离测量功能
  • ✏️ 绘制工具:支持点、线、多边形绘制
  • 💬 弹窗工具:支持在地图上显示自定义弹窗
  • 🗼 天地图集成:内置天地图底图支持,支持影像、矢量、地形
  • 🏔️ 地形处理:支持自定义地形加载和设置
  • 🎭 环境控制:支持隐藏太阳、月亮、天空盒,开启地下模式
  • 🔄 卷帘效果:支持图层对比卷帘功能
  • 🏗️ 3D Tiles:支持加载 3D 瓦片模型数据
  • 🎛️ 交互控制:支持禁用鼠标操作、事件监听

安装

npm install frost-map

快速开始

在 Vue 项目中使用

<template>
  <div style="width: 100%; height: 600px;">
    <FrostMap 
      :options="mapOptions"
      :tianditu-config="tiandituConfig"
      @ready="onMapReady"
      @error="onMapError"
    />
  </div>
</template>

<script setup>
import { ref } from 'vue';
import { FrostMap } from 'frost-map';

const mapOptions = {
  baseLayerPicker: false,
  creditContainer: document.createElement('div') // 隐藏 creditContainer
};

const tiandituConfig = ref({
  token: 'your-tianditu-token',
  type: 'img',
  enableLabel: true
});

const onMapReady = (mapInstance) => {
  console.log('Map is ready:', mapInstance);
};

const onMapError = (error) => {
  console.error('Map error:', error);
};
</script>

在 JavaScript 中使用

import { MapClass } from 'frost-map';

const map = new MapClass({
  baseLayerPicker: false
});

// 使用 async/await
await map.init('#map-container');

// 设置天地图底图
map.setTiandituImageryProvider({
  token: 'your-tianditu-token',
  type: 'img'
});

console.log('Map ready:', map.getViewer());

API 文档

1. MapClass - 地图核心类

封装 Cesium Viewer,提供地图初始化、销毁等基础操作,支持完善的时序控制。

构造函数

new MapClass(options)
参数 类型 说明
options Object Cesium Viewer 配置选项,默认 { animation: false, timeline: false }

静态方法

方法名 参数 返回值 说明
isCesiumLoaded boolean 检查 Cesium 是否已加载
getCesium Promise|Object|null 获取 Cesium 模块(支持动态导入)
waitForCesium timeout?: number (默认 10000) Promise 等待 Cesium 完全加载
createTiandituImageryProvider options: Object Object|null 创建天地图影像提供者配置

实例方法

基础方法
方法名 参数 返回值 说明
init container: HTMLElement|string, extraOptions?: Object Promise<MapClass> 初始化地图
getViewer Cesium.Viewer | null 获取 Cesium Viewer 实例
destroy void 销毁地图实例
setTiandituImageryProvider options: Object void 设置天地图底图
onReady callback: Function void 添加初始化完成回调
getInitStatus Object 获取初始化状态
waitForContainer container, timeout?: number Promise<HTMLElement|null> 等待容器就绪
地图信息
方法名 参数 返回值 说明
getZoom Number 获取当前地图缩放级别
getExtent Array 获取当前三维地图/相机范围 [xmin, ymin, xmax, ymax]
getViewCenter Cesium.Cartesian3|null 获取视角中心点
相机控制
方法名 参数 返回值 说明
flyTo options: Object Promise 地图定位(支持多坐标、包围盒)
flyToHome options?: Object Promise 视角定位默认位置
地形处理
方法名 参数 返回值 说明
createTerrain url: String, options?: Object Terrain 创建地形
setTerrain terrain?: Terrain Terrain 设置地形
terrainLoaded Promise 地形加载完成
图层管理
方法名 参数 返回值 说明
createImageryLayer option: Object, layerOptions?: Object ImageryLayer 创建影像图层
addImageryLayer option: Object, layerOptions?: Object ImageryLayer 添加影像图层
removeImageryLayer imageryLayer: ImageryLayer boolean 删除影像图层
3D Tiles
方法名 参数 返回值 说明
add3DTileset url: String, options?: Object, primitiveOptions?: Object Promise<Cesium3DTileset> 添加 3D 瓦片模型
环境控制
方法名 参数 返回值 说明
hideEnvironment options?: Object void 隐藏地球等环境因素
enableUnderGround bool: Boolean void 是否开启地下模式
openTerrainDepthTest bool: Boolean void 开启地形深度检测
openHDR bool: Boolean void 开启高动态范围渲染
交互控制
方法名 参数 返回值 说明
stopOperation options?: Object void 禁用鼠标操作
startSwipe swipeDom?: HTMLElement void 开启卷帘效果
closeSwipe void 关闭卷帘效果
事件监听
方法名 参数 返回值 说明
listenRenderEvent callback: Function, renderType?: String Function 监听地图渲染事件
listenMouseEvent callback: Function, eventType?: String, keyboardEventModifier?: Number ScreenSpaceEventHandler 监听鼠标事件

init 方法的 extraOptions 参数

参数 类型 默认值 说明
cesiumTimeout number 10000 Cesium 加载超时时间(毫秒)
waitForContainer boolean true 是否等待容器就绪

示例

import { MapClass } from 'frost-map';

const map = new MapClass({
  baseLayerPicker: false,
  fullscreenButton: true
});

// 方式 1:使用 async/await
try {
  await map.init('#map-container', {
    cesiumTimeout: 15000
  });
  
  // 设置天地图底图
  map.setTiandituImageryProvider({
    token: 'your-token',
    type: 'img'
  });
  
  // 设置地形
  const terrain = map.createTerrain('https://assets.agi.com/stk-terrain/world', {
    requestVertexNormals: true,
    requestWaterMask: true
  });
  map.setTerrain(terrain);
  
  // 等待地形加载
  await map.terrainLoaded();
  
  // 飞行到北京
  await map.flyTo({
    lng: 116.4074,
    lat: 39.9042,
    height: 5000
  });
  
  console.log('Map ready:', map.getViewer());
} catch (error) {
  console.error('Map initialization failed:', error);
}

// 页面销毁时
map.destroy();

2. FrostMap - Vue 地图组件

基于 MapClass 封装的 Vue 3 组件,提供响应式地图绑定和天地图集成。

Props

属性名 类型 默认值 说明
options Object {} Cesium Viewer 配置选项
tiandituConfig Object null 天地图配置,设置后自动加载天地图底图
cesiumTimeout Number 10000 Cesium 加载超时时间(毫秒)

Events

事件名 参数 说明
ready mapInstance: MapClass 地图完全初始化完成后触发(包括底图设置)
initialized mapInstance: MapClass Viewer 初始化完成后触发(底图设置前)
error error: Error 初始化失败时触发

方法

方法名 返回值 说明
getMap MapClass | null 获取地图实例
initMap void 重新初始化地图

示例

<template>
  <FrostMap 
    ref="mapRef" 
    :options="options"
    :tianditu-config="tiandituConfig"
    :cesium-timeout="15000"
    @ready="onReady"
    @initialized="onInitialized"
    @error="onError"
  />
</template>

<script setup>
import { ref } from 'vue';
import { FrostMap } from 'frost-map';

const mapRef = ref(null);
const options = {
  timeline: false,
  baseLayerPicker: false,
  creditContainer: document.createElement('div') // 隐藏版权信息
};

const tiandituConfig = ref({
  token: 'your-tianditu-token',
  type: 'vec',
  enableLabel: true
});

const onReady = (map) => {
  console.log('Map fully ready:', map);
};

const onInitialized = (map) => {
  console.log('Viewer initialized:', map);
};

const onError = (error) => {
  console.error('Map error:', error);
};

const getMapInstance = () => {
  return mapRef.value?.getMap();
};
</script>

3. ViewController - 视图控制器

提供相机控制功能,如飞行定位、缩放、视角切换等。

构造函数

new ViewController(viewer)
参数 类型 说明
viewer Cesium.Viewer Cesium Viewer 实例

方法

方法名 参数 返回值 说明
flyTo position: Object, options?: Object Promise 飞行到指定位置(带动画)
setView position: Object, options?: Object void 设置视图位置(无动画)
zoomIn distance?: number (默认 1000) void 放大视图
zoomOut distance?: number (默认 1000) void 缩小视图
getCurrentPosition Object | null 获取当前相机位置
lookAt target: Object, offset?: Cartesian3 void 看向指定目标

参数说明

position / target 对象结构:

属性 类型 说明
longitude number 经度
latitude number 纬度
height number (可选) 高度(米),默认 10000

flyTo options:

属性 类型 默认值 说明
duration number 3 飞行持续时间(秒)
maximumHeight number 10000 最大飞行高度

示例

import { MapClass, ViewController } from 'frost-map';

const map = new MapClass();
await map.init('#map-container');

const viewer = map.getViewer();
const viewController = new ViewController(viewer);

// 飞行到北京
await viewController.flyTo({
  longitude: 116.4074,
  latitude: 39.9042,
  height: 5000
}, {
  duration: 2
});

// 放大
viewController.zoomIn(500);

// 获取当前位置
const pos = viewController.getCurrentPosition();
console.log(pos); // { longitude, latitude, height }

// 看向目标
viewController.lookAt({
  longitude: 116.4074,
  latitude: 39.9042
});

4. CesiumMeasure - 测量工具

提供距离测量功能,支持鼠标交互绘制测量线。

构造函数

new CesiumMeasure(viewer)
参数 类型 说明
viewer Cesium.Viewer Cesium Viewer 实例

方法

方法名 参数 返回值 说明
start type?: string (默认 'distance') void 开始测量
stop void 停止测量
clear void 清除测量结果

使用说明

  1. 调用 start() 开始测量
  2. 左键点击地图添加测量点
  3. 鼠标移动预览测量线
  4. 右键点击结束测量

示例

import { MapClass, CesiumMeasure } from 'frost-map';

const map = new MapClass();
await map.init('#map-container');

const viewer = map.getViewer();
const measure = new CesiumMeasure(viewer);

// 开始测量
measure.start();

// 测量完成后停止
// measure.stop();

// 清除测量线
// measure.clear();

5. CesiumDrawer - 绘制工具

支持在地图上绘制点、线、多边形。

构造函数

new CesiumDrawer(viewer)
参数 类型 说明
viewer Cesium.Viewer Cesium Viewer 实例

方法

方法名 参数 返回值 说明
start mode?: string (默认 'point') void 开始绘制
finishDrawing void 完成绘制
clear void 清除所有绘制内容

绘制模式

模式 说明
point 绘制点,每次点击添加一个点
polyline 绘制折线,需要至少 2 个点
polygon 绘制多边形,需要至少 3 个点

使用说明

  1. 调用 start(mode) 开始绘制
  2. 左键点击地图添加点
  3. 鼠标移动预览绘制结果
  4. 右键点击结束绘制

示例

import { MapClass, CesiumDrawer } from 'frost-map';

const map = new MapClass();
await map.init('#map-container');

const viewer = map.getViewer();
const drawer = new CesiumDrawer(viewer);

// 绘制点
drawer.start('point');

// 绘制线
// drawer.start('polyline');

// 绘制多边形
// drawer.start('polygon');

// 清除所有绘制
// drawer.clear();

6. Popup - 弹窗工具

用于在地图上显示自定义弹窗信息。

构造函数

new Popup(viewer)
参数 类型 说明
viewer Cesium.Viewer Cesium Viewer 实例

方法

方法名 参数 返回值 说明
show position: Cartesian3, content: string, options?: Object void 显示弹窗
hide void 隐藏弹窗

参数说明

options 对象:

属性 类型 默认值 说明
showCloseButton boolean true 是否显示关闭按钮
disablePointerEvents boolean true 是否禁用指针事件
disableZoomOnClick boolean true 是否禁用点击缩放

示例

import { MapClass, Popup } from 'frost-map';

const map = new MapClass();
await map.init('#map-container');

const viewer = map.getViewer();
const popup = new Popup(viewer);

// 创建位置
const position = Cesium.Cartesian3.fromDegrees(116.4074, 39.9042, 0);

// 显示弹窗
popup.show(position, '<h3>Hello World</h3><p>This is a popup</p>');

// 隐藏弹窗
// popup.hide();

7. mapConfig - 地图配置

包含默认的 Cesium Viewer 配置选项和相机位置。

配置项

{
  // 默认 Viewer 配置
  defaultOptions: {
    animation: false,
    baseLayerPicker: true,
    fullscreenButton: true,
    geocoder: true,
    homeButton: true,
    infoBox: true,
    sceneModePicker: true,
    selectionIndicator: true,
    timeline: false,
    navigationHelpButton: false,
    navigationInstructionsInitiallyVisible: false
  },
  
  // 默认相机位置(北京)
  defaultCameraPosition: {
    longitude: 116.4074,
    latitude: 39.9042,
    height: 10000
  },
  
  imageryProvider: null,  // 影像图层提供者
  terrainProvider: null   // 地形提供者
}

示例

import { mapConfig, MapClass, ViewController } from 'frost-map';

// 使用默认配置
const map = new MapClass(mapConfig.defaultOptions);
await map.init('#map-container');

// 使用默认相机位置
const viewController = new ViewController(map.getViewer());
viewController.flyTo(mapConfig.defaultCameraPosition);

天地图集成

frost-map 内置天地图底图支持,使用 UrlTemplateImageryProvider 正确解析天地图 REST API。

配置选项

选项 类型 默认值 说明
token string - 天地图 token(必填)
type string 'img' 底图类型:img(影像), vec(矢量), ter(地形)
enableLabel boolean true 是否显示标注层

获取天地图 Token

  1. 访问 天地图官网
  2. 注册账号并登录
  3. 进入控制台 -> 我的应用 -> 创建应用
  4. 获取 Token

使用示例

Vue 组件方式:

<FrostMap 
  :options="{ baseLayerPicker: false }"
  :tianditu-config="{
    token: 'your-token',
    type: 'img',
    enableLabel: true
  }"
/>

JavaScript 方式:

const map = new MapClass({ baseLayerPicker: false });
await map.init('#map-container');
map.setTiandituImageryProvider({
  token: 'your-token',
  type: 'img'
});

高级功能

地形处理

// 创建并设置地形
const terrain = map.createTerrain('https://assets.agi.com/stk-terrain/world', {
  requestVertexNormals: true,    // 加载地形光照
  requestWaterMask: true         // 加载水面区域
});
map.setTerrain(terrain);

// 等待地形加载完成
await map.terrainLoaded();
console.log('Terrain loaded');

图层管理

// 添加自定义影像图层
const layer = map.addImageryLayer({
  type: 'UrlTemplate',
  url: 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
  subdomains: ['a', 'b', 'c']
}, {
  show: true
});

// 添加支持 GCJ02 坐标系的图层
const gcj02Layer = map.addImageryLayer({
  type: 'UrlTemplate',
  url: 'your-gcj02-tile-url',
  sr: 'GCJ02'  // 自动转换为 WGS84
});

// 删除图层
map.removeImageryLayer(layer);

3D Tiles 加载

// 添加 3D 瓦片模型
const tileset = await map.add3DTileset('path/to/your/tileset', {
  height: 0,                    // 自动贴地
  splitDirection: 'LEFT',       // 分屏方向
  maximumScreenSpaceError: 16,  // 屏幕空间误差
  debugShowBoundingVolume: false,
  style: {
    color: 'color("#ff0000")'
  }
});

环境控制

// 隐藏环境元素
map.hideEnvironment({
  showSun: false,
  showMoon: false,
  showSkyBox: false,
  showSkyAtmosphere: false,
  showGlobe: true
});

// 开启地下模式
map.enableUnderGround(true);

// 开启地形深度检测
map.openTerrainDepthTest(true);

// 开启高动态范围渲染
map.openHDR(true);

交互控制

// 禁用鼠标操作
map.stopOperation({
  rotate: false,
  tilt: false,
  zoom: false
});

// 开启卷帘效果
const swipeDom = document.querySelector('.swipe-container');
map.startSwipe(swipeDom);

// 关闭卷帘效果
map.closeSwipe();

事件监听

// 监听渲染事件
const removeRenderListener = map.listenRenderEvent((scene, time) => {
  console.log('Frame rendered:', time);
}, 'postRender');

// 监听鼠标点击事件
const mouseHandler = map.listenMouseEvent((event) => {
  const position = map.getViewer().scene.pickPosition(event.position);
  console.log('Clicked position:', position);
}, 'LEFT_CLICK');

完整示例

<template>
  <div class="map-container">
    <FrostMap 
      ref="mapRef" 
      :options="options"
      :tianditu-config="tiandituConfig"
      @ready="onMapReady"
    />
    
    <!-- 控制按钮 -->
    <div class="controls">
      <button @click="flyToBeijing">飞行到北京</button>
      <button @click="startMeasure">开始测量</button>
      <button @click="drawPolygon">绘制多边形</button>
      <button @click="showPopup">显示弹窗</button>
      <button @click="toggleUnderground">地下模式</button>
      <button @click="add3DTiles">加载3D模型</button>
    </div>
  </div>
</template>

<script setup>
import { ref } from 'vue';
import { 
  FrostMap, 
  ViewController, 
  CesiumMeasure, 
  CesiumDrawer, 
  Popup,
  mapConfig 
} from 'frost-map';

const mapRef = ref(null);
let viewController = null;
let measure = null;
let drawer = null;
let popup = null;
let undergroundMode = false;

const options = {
  ...mapConfig.defaultOptions,
  baseLayerPicker: false
};

const tiandituConfig = ref({
  token: 'your-tianditu-token',
  type: 'img',
  enableLabel: true
});

const onMapReady = (map) => {
  const viewer = map.getViewer();
  
  viewController = new ViewController(viewer);
  measure = new CesiumMeasure(viewer);
  drawer = new CesiumDrawer(viewer);
  popup = new Popup(viewer);
  
  // 设置地形
  const terrain = map.createTerrain('https://assets.agi.com/stk-terrain/world', {
    requestVertexNormals: true
  });
  map.setTerrain(terrain);
};

const flyToBeijing = () => {
  viewController?.flyTo(mapConfig.defaultCameraPosition);
};

const startMeasure = () => {
  measure?.start();
};

const drawPolygon = () => {
  drawer?.start('polygon');
};

const showPopup = () => {
  const position = Cesium.Cartesian3.fromDegrees(
    mapConfig.defaultCameraPosition.longitude,
    mapConfig.defaultCameraPosition.latitude,
    0
  );
  popup?.show(position, '<h3>北京</h3><p>中国首都</p>');
};

const toggleUnderground = () => {
  const map = mapRef.value?.getMap();
  if (map) {
    undergroundMode = !undergroundMode;
    map.enableUnderGround(undergroundMode);
  }
};

const add3DTiles = async () => {
  const map = mapRef.value?.getMap();
  if (map) {
    await map.add3DTileset('path/to/your/tileset', {
      height: 0
    });
  }
};
</script>

<style scoped>
.map-container {
  width: 100%;
  height: 100vh;
  position: relative;
}

.controls {
  position: absolute;
  top: 20px;
  left: 20px;
  z-index: 100;
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
}

.controls button {
  padding: 10px 20px;
  background: white;
  border: 1px solid #ccc;
  border-radius: 4px;
  cursor: pointer;
}

.controls button:hover {
  background: #f5f5f5;
}
</style>

依赖说明

由于 cesiumvue 被配置为外部依赖(externals),使用时需要确保在项目中正确引入:

通过 CDN 引入

<script src="https://cdn.jsdelivr.net/npm/vue@3/dist/vue.global.js"></script>
<script src="https://cesium.com/downloads/cesiumjs/releases/1.100/Build/Cesium/Cesium.js"></script>
<link href="https://cesium.com/downloads/cesiumjs/releases/1.100/Build/Cesium/Widgets/widgets.css" rel="stylesheet">

通过 npm 安装

npm install cesium vue

通过 public 静态资源引入(推荐)

  1. 将 Cesium 放在 public/cesium 目录
  2. index.html 中引入:
<script src="/cesium/Cesium.js"></script>
<link href="/cesium/Widgets/widgets.css" rel="stylesheet">
<script>window.CESIUM_BASE_URL = '/cesium/';</script>

许可证

MIT License