Frost-Map一个基于 Cesium 的 Vue 3 地图工具包,用于在 Web 上创建 3D 地图应用。
功能特性
🗺️ 地图核心 :封装 Cesium Viewer,提供完善的初始化时序控制
🎨 Vue 组件 :提供 Vue 3 地图组件,支持响应式绑定和天地图集成
📍 视图控制 :支持飞行定位、缩放、视角切换
📐 测量工具 :支持距离测量功能
✏️ 绘制工具 :支持点、线、多边形绘制
💬 弹窗工具 :支持在地图上显示自定义弹窗
🗼 天地图集成 :内置天地图底图支持,支持影像、矢量、地形
🏔️ 地形处理 :支持自定义地形加载和设置
🎭 环境控制 :支持隐藏太阳、月亮、天空盒,开启地下模式
🔄 卷帘效果 :支持图层对比卷帘功能
🏗️ 3D Tiles :支持加载 3D 瓦片模型数据
🎛️ 交互控制 :支持禁用鼠标操作、事件监听
安装 快速开始 在 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
};
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
} ) ;
await map. init ( '#map-container' ) ;
map. setTiandituImageryProvider ( {
token : 'your-tianditu-token' ,
type : 'img'
} ) ;
console. log ( 'Map ready:' , map. getViewer ( ) ) ; API 文档 1. MapClass - 地图核心类封装 Cesium Viewer,提供地图初始化、销毁等基础操作,支持完善的时序控制。
构造函数
参数
类型
说明
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
监听鼠标事件
参数
类型
默认值
说明
cesiumTimeout
number
10000
Cesium 加载超时时间(毫秒)
waitForContainer
boolean
true
是否等待容器就绪
示例import { MapClass } from 'frost-map' ;
const map = new MapClass ( {
baseLayerPicker : false ,
fullscreenButton : true
} ) ;
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
};
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) ;
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
清除测量结果
使用说明
调用 start() 开始测量
左键点击地图添加测量点
鼠标移动预览测量线
右键点击结束测量
示例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 ( ) ;
5. CesiumDrawer - 绘制工具支持在地图上绘制点、线、多边形。
构造函数
参数
类型
说明
viewer
Cesium.Viewer
Cesium Viewer 实例
方法
方法名
参数
返回值
说明
start
mode?: string (默认 'point')
void
开始绘制
finishDrawing
无
void
完成绘制
clear
无
void
清除所有绘制内容
绘制模式
模式
说明
point
绘制点,每次点击添加一个点
polyline
绘制折线,需要至少 2 个点
polygon
绘制多边形,需要至少 3 个点
使用说明
调用 start(mode) 开始绘制
左键点击地图添加点
鼠标移动预览绘制结果
右键点击结束绘制
示例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' ) ;
用于在地图上显示自定义弹窗信息。
构造函数
参数
类型
说明
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>' ) ;
7. mapConfig - 地图配置包含默认的 Cesium 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
访问 天地图官网
注册账号并登录
进入控制台 -> 我的应用 -> 创建应用
获取 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
} ) ;
const gcj02Layer = map. addImageryLayer ( {
type : 'UrlTemplate' ,
url : 'your-gcj02-tile-url' ,
sr : 'GCJ02'
} ) ;
map. removeImageryLayer ( layer) ; 3D Tiles 加载
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>
依赖说明由于 cesium 和 vue 被配置为外部依赖(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 安装 通过 public 静态资源引入(推荐)
将 Cesium 放在 public/cesium 目录
在 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