geoglobe-3d
v1.3.0
Published
基于 Cesium 的三维地图框架,支持 Vue/React 等前端框架
Maintainers
Readme
geoGlobe3D
基于 Cesium 的三维地图开发框架,提供简洁易用的 API,快速构建 WebGL 三维地球应用。
版本 v1.1.0 · 协议 Apache-2.0 · 依赖 Cesium(内置)
NPM: https://www.npmjs.com/package/geoglobe-3d
目录
架构总览
┌──────────────────────────────────────────────────────────┐
│ geoGlobe3D │
│ │
│ ┌────────────────────────────────────────────────────┐ │
│ │ GeoMap │ │
│ │ ┌──────────┐ ┌──────────┐ ┌──────────────────┐ │ │
│ │ │ Layers │ │ Graphics │ │ Managers │ │ │
│ │ │ │ │ │ │ │ │ │
│ │ │ Imagery │ │ Point │ │ EventManager │ │ │
│ │ │ Terrain │ │ Line │ │ PopupManager │ │ │
│ │ │ Tileset │ │ Polygon │ │ TooltipManager │ │ │
│ │ │ GeoJSON │ │ Circle │ │ │ │ │
│ │ │ KML/CZML │ │ Model │ └──────────────────┘ │ │
│ │ │ Graphic │ │ Wall │ │ │
│ │ │ │ │ Rect │ ┌──────────────────┐ │ │
│ │ └──────────┘ │ Box/... │ │ Controls │ │ │
│ │ └──────────┘ │ │ │ │
│ │ ┌──────────┐ │ NavBar │ │ │
│ │ │ Tools │ │ Navigation │ │ │
│ │ │ Draw │ │ Toolbar │ │ │
│ │ │ Measure │ └──────────────────┘ │ │
│ │ └──────────┘ │ │
│ └────────────────────────────────────────────────────┘ │
│ │
│ ┌──────────────┐ │
│ │ Cesium.js │ │
│ └──────────────┘ │
└──────────────────────────────────────────────────────────┘数据流向:GeoMap 初始化 Cesium Viewer → 图层/图形/控件通过 addTo(map) 挂载 → EventManager 统一派发交互事件 → PopupManager / TooltipManager 响应图形交互。
关键设计:
- 所有坐标统一使用
[经度, 纬度, 高度]度制数组 - 所有颜色支持 CSS 字符串(
'#ff0000'、'rgba(255,0,0,0.5)')或 Cesium.Color 实例 - 异步图层(Imagery / Terrain / Tileset / GeoJSON / KML / CZML)加载完成后触发
'load'事件 - Draw / Measure 使用 Promise API —
await draw.point(),右键结束
安装与构建
# 安装依赖
npm install
# 生产构建
npm run build
# 开发模式(文件监听 + 自动重建)
npm run dev
# 本地预览 http://localhost:8080
npm start快速开始
UMD — 浏览器直接引用
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="dist/Widgets/widgets.css">
<style>html, body, #map { margin: 0; width: 100%; height: 100%; }</style>
</head>
<body>
<div id="map"></div>
<script src="dist/geoglobe.min.js"></script>
<script>
// 创建地图
const map = new geoGlobe.GeoMap('map', {
skyBox: 'space',
camera: { position: [116.4, 39.9, 8000000] }
});
// 添加影像图层
const imagery = new geoGlobe.ImageryLayer({
type: 'xyz',
url: 'https://webst01.is.autonavi.com/appmaptile?x={x}&y={y}&z={z}&style=6'
});
map.addLayer(imagery);
// 在图层上绘制点
const layer = new geoGlobe.GraphicLayer({ id: 'marks' });
map.addLayer(layer);
layer.addGraphic(new geoGlobe.PointGraphic({
position: [116.4, 39.9, 0],
style: { pixelSize: 12, color: '#ff0000' },
popup: '<b>北京</b>',
tooltip: '中国首都'
}));
</script>
</body>
</html>ESM — 模块化导入
import { GeoMap, GraphicLayer, PointGraphic, ImageryLayer } from 'geoglobe-3d';
const map = new GeoMap('map', {
skyBox: 'space',
camera: { position: [116.4, 39.9, 8000000] }
});
const layer = new GraphicLayer({ id: 'marks' });
map.addLayer(layer);
layer.addGraphic(new PointGraphic({
position: [116.4, 39.9, 0],
style: { pixelSize: 12, color: '#ff0000' }
}));Vue 3 + Vite 集成
完整示例项目见
examples/vue3-demo/
1. 安装
npm install geoglobe-3dCesium 已内置于 geoglobe-3d,无需单独安装 cesium。
2. 拷贝静态资源
将 node_modules/geoglobe-3d/dist/ 整个目录拷贝到 public/geoglobe/(包含 JS 产物、Workers、Assets、Widgets、ThirdParty):
# Linux / macOS
cp -r node_modules/geoglobe-3d/dist public/geoglobe
# Windows (PowerShell)
Copy-Item -Recurse -Force "node_modules/geoglobe-3d/dist" "public/geoglobe"推荐在 package.json 中添加脚本自动执行:
{
"scripts": {
"copy-assets": "node scripts/copy-geoglobe-assets.js"
}
}// scripts/copy-geoglobe-assets.js
import { cpSync, existsSync } from 'fs';
import { resolve, dirname } from 'path';
import { fileURLToPath } from 'url';
const __dirname = dirname(fileURLToPath(import.meta.url));
const root = resolve(__dirname, '..');
const src = resolve(root, 'node_modules/geoglobe-3d/dist');
const dest = resolve(root, 'public/geoglobe');
if (!existsSync(src)) {
console.error('找不到 node_modules/geoglobe-3d/dist,请先运行 npm install');
process.exit(1);
}
cpSync(src, dest, { recursive: true });
console.log('已复制 geoglobe-3d/dist -> public/geoglobe');3. 在 index.html 引入 UMD 版本
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>geoGlobe3D Vue3 Demo</title>
<!-- 引入 Cesium 组件样式 -->
<link rel="stylesheet" href="/geoglobe/Widgets/widgets.css" />
</head>
<body>
<div id="app"></div>
<!-- 引入 UMD 版本,注册全局 window.geoGlobe -->
<script src="/geoglobe/geoglobe.js"></script>
<script type="module" src="/src/main.js"></script>
</body>
</html>UMD 版本加载后自动根据 script 标签路径推断
CESIUM_BASE_URL,无需手动设置。
4. Vite 配置
// vite.config.js
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
export default defineConfig({
plugins: [vue()]
});由于 geoglobe 通过
<script>标签引入(非 ESM import),Vite 配置无需额外处理。
5. 地图组件
<!-- src/components/MapView.vue -->
<template>
<div class="map-wrapper">
<!-- 自定义工具栏 -->
<div class="toolbar">
<div class="bar-group">
<span class="label">绘制</span>
<button @click="doDraw('point')">点</button>
<button @click="doDraw('polyline')">线</button>
<button @click="doDraw('polygon')">面</button>
<button @click="doDraw('rectangle')">矩形</button>
<button @click="doDraw('circle')">圆</button>
<button @click="clearDraw()">清除</button>
</div>
<div class="bar-group">
<span class="label">量算</span>
<button @click="doMeasure('distance')">距离</button>
<button @click="doMeasure('area')">面积</button>
<button @click="doMeasure('height')">高度</button>
<button @click="clearMeasure()">清除</button>
</div>
</div>
<!-- 地图容器 -->
<div ref="mapContainer" class="map-container"></div>
</div>
</template>
<script setup>
import { ref, onMounted, onBeforeUnmount } from 'vue';
// geoGlobe 通过 index.html 的 <script> 标签引入,挂载在 window.geoGlobe 上
const { GeoMap, Draw, Measure } = window.geoGlobe;
const mapContainer = ref(null);
let map = null;
let draw = null;
let measure = null;
onMounted(() => {
map = new GeoMap(mapContainer.value, {
skyBox: 'space',
control: {
timeline: false,
animation: false,
baseLayerPicker: false,
homeButton: false,
sceneModePicker: false,
navigationHelpButton: false,
fullscreenButton: false,
toolbar: true, // 底部状态栏
navBar: true, // 左侧导航栏
navigation: false
},
camera: {
position: [116.39, 39.91, 8000000],
heading: 0,
pitch: -90,
roll: 0
}
});
draw = new Draw(map);
measure = new Measure(map);
});
function doDraw(type) {
if (draw && draw[type]) draw[type]();
}
function clearDraw() {
if (draw && draw.clear) draw.clear();
}
function doMeasure(type) {
if (measure && measure[type]) measure[type]();
}
function clearMeasure() {
if (measure && measure.clear) measure.clear();
}
onBeforeUnmount(() => {
if (map && map.destroy) {
map.destroy();
}
});
</script>
<style scoped>
.map-wrapper {
width: 100%;
height: 100%;
position: relative;
}
.map-container {
width: 100%;
height: 100%;
}
</style>6. 运行
npm install
npm run copy-assets # 复制 geoglobe-3d/dist -> public/geoglobe
npm run dev # 启动 Vite 开发服务器注意事项:
- 确保 CSS 高度链完整:
html, body, #app都需设置width: 100%; height: 100%,否则地图容器高度为 0。- 使用
let而非ref()保存地图实例,避免 Vue 的 reactive proxy 深度代理 Cesium 内部对象导致性能问题。- 组件卸载时务必调用
destroy()释放 WebGL 资源。public/geoglobe/目录由脚本生成,建议加入.gitignore。
产物说明
| 文件 | 格式 | Cesium | 适用场景 |
|------|------|--------|----------|
| dist/geoglobe.js | UMD | 内含 | 浏览器 <script> 标签 |
| dist/geoglobe.min.js | UMD (压缩) | 内含 | 生产环境 |
| dist/geoglobe.esm.js | ES Module | 内含 | Webpack / Vite / Rollup |
| dist/geoglobe.cjs.js | CommonJS | 内含 | Node.js / SSR |
| dist/index.d.ts | TypeScript 声明 | — | Vue/React + TS 项目 |
附属资源(需整体部署):
| 目录 | 说明 |
|------|------|
| dist/Workers/ | Cesium Web Worker 文件 |
| dist/Assets/ | 纹理、地形高度等静态资源 |
| dist/Widgets/ | UI 组件样式 |
引用 UMD 版本时,框架自动推断
CESIUM_BASE_URL,无需手动设置。
GeoMap — 核心类
// UMD
const map = new geoGlobe.GeoMap(container, options);
// ESM
import { GeoMap } from 'geoglobe-3d';
const map = new GeoMap(container, options);container:DOM 元素或元素 id 字符串。GeoMap 同时以 Map 别名导出。
构造参数
const map = new GeoMap('map', {
// ─── 底图 ───
baseImagery: 'naturalEarth', // 'naturalEarth'(默认) | 'osm' | 'none' | imageryProvider 实例
// ─── 天空盒 ───
skyBox: 'space', // 'space'(默认) | 'default' | false | { sources, animate, ... }
// ─── 场景 ───
scene: {
sceneMode: SceneMode.SCENE3D, // SCENE3D | SCENE2D | COLUMBUS_VIEW
globe: {
baseColor: Color.BLACK,
depthTestAgainstTerrain: false,
enableLighting: false,
showGroundAtmosphere: true
}
},
// ─── 控件 ───
control: {
// Cesium 原生控件
baseLayerPicker: false, geocoder: false,
homeButton: true, sceneModePicker: true,
navigationHelpButton: true,animation: false,
timeline: false, fullscreenButton: true,
infoBox: false, selectionIndicator: false,
// 扩展控件
navigation: false, // true | false | { compass, zoomControls, distanceLegend }
navBar: false, // true | false | { position, showCompass, showHome, showSceneMode, showZoom }
toolbar: false // true | false
},
// ─── 弹窗 & 提示 ───
popup: true, // true | false | { auto, closeButton, followCamera, offset, className }
tooltip: true, // true | false | { offset, className }
// ─── 地形 ───
terrain: {
enabled: false,
url: undefined // 自定义 CTB URL;不填且 enabled:true 时使用 Cesium World Terrain
},
// ─── Ion Token ───
accessToken: 'your-cesium-ion-token',
// ─── 初始相机 ───
camera: {
position: [116.4, 39.9, 10000000], // [经度, 纬度, 高度(米)]
heading: 0, // 朝向角(度)
pitch: -90, // 俯仰角(度)
roll: 0
}
});图层管理
增删查
| 方法 | 签名 | 返回值 | 说明 |
|------|------|--------|------|
| addLayer | (layer: Layer) | GeoMap | 添加图层 |
| removeLayer | (layer: Layer) | GeoMap | 移除图层 |
| removeLayerById | (id: string) | GeoMap | 按 id 移除 |
| removeAllLayers | () | GeoMap | 移除全部 |
| getLayer | (id: string) | Layer \| undefined | 按 id 查找 |
| getLayerByName | (name: string) | Layer \| undefined | 按 name 查找 |
| getLayers | () | Layer[] | 获取全部(副本) |
| hasLayer | (layer: Layer) | boolean | 是否包含 |
| getLayerCount | () | number | 图层数量 |
排序
| 方法 | 说明 |
|------|------|
| raiseLayer(layer) | 上移一层 |
| lowerLayer(layer) | 下移一层 |
| raiseLayerToTop(layer) | 置顶 |
| lowerLayerToBottom(layer) | 置底 |
| moveLayerTo(layer, index) | 移到指定位置(0 = 最底层) |
显隐
| 方法 | 说明 |
|------|------|
| showLayer(id) | 显示图层 |
| hideLayer(id) | 隐藏图层 |
| toggleLayer(id) | 切换显隐 |
相机与视图
| 方法 | 签名 | 说明 |
|------|------|------|
| flyTo | (position: [lng,lat,h], options?) | 飞行动画。options: { duration, heading, pitch, roll } |
| setView | ([lng,lat,h]) 或 ({ position, heading, pitch, roll }) | 瞬间跳转 |
| setCamera | ({ position?, heading?, pitch?, roll? }) | 设置相机 |
| resetView | () | 复位到初始位置 |
| zoomIn | (amount=2) | 放大 |
| zoomOut | (amount=2) | 缩小 |
| zoomTo | (target, options?) | 飞行到图层/图形范围 |
| setSceneMode | (mode, duration=2) | 切换场景: '3d'/'2d'/'columbus' |
查询
| 方法 | 返回值 | 说明 |
|------|--------|------|
| getCenter() | [lng, lat, h] \| undefined | 视图中心 |
| getCamera() | { position, heading, pitch, roll, height } | 相机姿态 |
| getCurrentExtent() | { west, south, east, north } \| undefined | 视图范围(度) |
// 飞行到北京上空
map.flyTo([116.4, 39.9, 5000], { duration: 2, pitch: -45 });
// 瞬间跳转(两种写法等价)
map.setView([116.4, 39.9, 5000]);
map.setView({ position: [116.4, 39.9, 5000], heading: 0, pitch: -45, roll: 0 });
// 切换到 2D 模式
map.setSceneMode('2d', 2);底图与地形
// 运行时切换底图
map.setBaseImagery('osm');
map.setBaseImagery('naturalEarth');
map.setBaseImagery(customProviderInstance);
map.setBaseImagery('none');
// 运行时切换地形(异步)
await map.setTerrain({ url: 'https://your-terrain-ctb' }); // 自定义 CTB
await map.setTerrain({ ionAssetId: 1 }); // Cesium World Terrain
await map.setTerrain({ enabled: false }); // 关闭地形场景效果
| 方法 | 参数 | 说明 |
|------|------|------|
| setSkyBox(opt) | 'space' \| 'default' \| false \| { sources } | 天空盒 |
| setFog(opts) | { enabled, density, minimumBrightness } | 雾效 |
| setAtmosphere(opts) | { show, lightIntensity, rayleighScaleHeight } | 大气 |
| setSunLight(enabled) | boolean | 太阳光照 |
时钟与时间
| 方法 | 签名 | 说明 |
|------|------|------|
| setClock | (opts) | 配置时钟 |
| getTime | () → string | 获取当前时间 (ISO) |
| setTime | (isoString) | 跳转到指定时间 |
| setTimeSpeed | (multiplier) | 播放速率(负值倒放) |
| startClock | () | 开始 |
| stopClock | () | 暂停 |
setClock 参数:
| 属性 | 类型 | 说明 |
|------|------|------|
| start | string | 开始时间 ISO,如 '2024-01-01T00:00:00Z' |
| stop | string | 结束时间 ISO |
| current | string | 当前时间 ISO |
| multiplier | number | 时间倍率,默认 1 |
| clockRange | string | 'unbounded' / 'clamped' / 'loop' |
| animate | boolean | 是否自动播放 |
map.setClock({
start: '2024-01-01T00:00:00Z',
stop: '2024-12-31T23:59:59Z',
current: '2024-06-01T12:00:00Z',
multiplier: 100,
clockRange: 'loop',
animate: true
});截图与销毁
const base64 = map.screenshot(); // PNG base64
const jpeg = map.screenshot({ type: 'image/jpeg', quality: 0.9 });
map.downloadScreenshot('my-map.png'); // 浏览器下载
map.destroy(); // 销毁地图,释放所有资源图层 API
Layer — 基类
所有图层继承自 Layer,共享以下接口:
构造参数
| 参数 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| id | string | 自动 UUID | 唯一标识 |
| name | string | '' | 名称 |
| show | boolean | true | 可见性 |
公共方法
| 方法 | 说明 |
|------|------|
| addTo(map) | 添加到地图 |
| remove() | 从地图移除 |
| destroy() | 移除并清理事件 |
| setShow(show) / showLayer() / hideLayer() / toggleShow() | 显隐控制 |
| getIndex() | 在 map.layers 中的索引 |
| on(event, cb) / once(event, cb) / off(event, cb?) | 事件监听 |
图层事件:'load'(加载完成)、'error'(加载失败)、'click'。
ImageryLayer — 影像图层
const layer = new ImageryLayer({
id: 'gaode', name: '高德影像',
type: 'xyz',
url: 'https://webst01.is.autonavi.com/appmaptile?x={x}&y={y}&z={z}&style=6'
});
map.addLayer(layer);构造参数(除 Layer 公共参数外)
| 参数 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| type | string | 'xyz' | 类型,见下表 |
| url | string | — | 服务 URL |
| alpha | number | 1.0 | 透明度 (0~1) |
| maximumLevel | number | — | 最大层级 |
| minimumLevel | number | 0 | 最小层级 |
| layer | string | — | WMTS/WMS 图层名 |
| style | string | — | WMTS 样式名 |
| format | string | 'image/png' | 瓦片格式 |
| tileMatrixSetID | string | — | WMTS 矩阵集 |
| layers | string | — | WMS 图层列表 |
| ionAssetId | number | — | Ion 资产 ID |
| color | string | — | 单色图层颜色 |
| rectangle | number[] | — | [west,south,east,north] 度 |
type 取值对照
| type | 底层 Provider | 说明 |
|------|--------------|------|
| 'xyz' | UrlTemplateImageryProvider | XYZ 瓦片 |
| 'tms' | UrlTemplateImageryProvider | TMS 服务(与 xyz 共用) |
| 'osm' | OpenStreetMapImageryProvider | OSM 瓦片 |
| 'wmts' | WebMapTileServiceImageryProvider | WMTS 服务 |
| 'wms' | WebMapServiceImageryProvider | WMS 服务 |
| 'arcgis' | ArcGisMapServerImageryProvider | ArcGIS 服务 |
| 'ion' | IonImageryProvider | Cesium Ion 影像 |
| 'singleTile' | SingleTileImageryProvider | 单张图片 |
| 'singleColor' / 'color' | Canvas 生成 | 纯色覆盖 |
图层调整方法
| 方法 | 说明 |
|------|------|
| setAlpha(v) / setOpacity(v) | 透明度 (0~1) |
| setBrightness(v) | 亮度 (1.0=默认) |
| setContrast(v) | 对比度 |
| setSaturation(v) | 饱和度 (0=灰度) |
| setHue(v) | 色调 |
| setGamma(v) | 伽马 |
| raise() / lower() / raiseToTop() / lowerToBottom() | 排序 |
// WMTS
new ImageryLayer({
type: 'wmts',
url: 'https://example.com/wmts',
layer: 'layerName',
style: 'default',
tileMatrixSetID: 'EPSG:4326'
}).addTo(map);
// WMS
new ImageryLayer({
type: 'wms',
url: 'https://example.com/wms',
layers: 'roads'
}).addTo(map);TerrainLayer — 地形图层
| 参数 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| type | string | 'ellipsoid' | 'ion' / 'cesium' / 'ellipsoid' |
| url | string | — | CTB 地形 URL(cesium 类型必填) |
| ionAssetId | number | 1 | Ion 资产 ID(ion 类型) |
| requestVertexNormals | boolean | false | 请求法线(光照用) |
| requestWaterMask | boolean | false | 请求水面遮罩 |
new TerrainLayer({
type: 'cesium',
url: 'https://your-terrain-ctb-service'
}).addTo(map);TilesetLayer — 3D Tiles
| 参数 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| url | string | — | tileset.json URL |
| ionAssetId | number | — | Ion 资产 ID |
| maximumScreenSpaceError | number | 16 | 最大屏幕空间误差 |
| maximumMemoryUsage | number | 512 | 最大内存 (MB) |
| position | number[] | — | 位置偏移 [lng, lat, height] |
| rotation | object | — | 旋转 { heading, pitch, roll }(度) |
| shadows | boolean | false | 阴影 |
| backFaceCulling | boolean | true | 背面剔除 |
| style | object | — | 3D Tiles Style,转为 Cesium3DTileStyle |
| onClick | Function | — | 点击回调 (picked, click) |
| onReady | Function | — | 加载完成回调 |
方法:flyTo(options?)、raise()、lower()、raiseToTop()、lowerToBottom()
const tileset = new TilesetLayer({
url: 'https://your-server/tileset.json',
maximumScreenSpaceError: 16,
position: [116.4, 39.9, 0],
rotation: { heading: 0, pitch: 0, roll: 0 },
style: { color: "color('white', 0.8)" }
});
map.addLayer(tileset);
tileset.flyTo();GeoJsonLayer
| 参数 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| url | string | — | GeoJSON 文件 URL |
| data | object | — | 内联 GeoJSON 对象 |
| stroke | string | '#ffff00' | 线颜色 |
| strokeWidth | number | 2 | 线宽 |
| fill | string | 'rgba(255,255,0,0.4)' | 填充色 |
| markerSize | number | 48 | 点标记大小 |
| markerColor | string | '#4169E1' | 点标记颜色 |
| clampToGround | boolean | false | 贴地 |
| onClick | Function | — | 点击回调 (entity, click) |
| onLoad | Function | — | 加载回调 (dataSource) |
注意:样式属性在顶层,不嵌套在
style对象中。
方法:getEntities()、flyTo(options?)、raise()、lower()、raiseToTop()、lowerToBottom()
// URL 加载
new GeoJsonLayer({
url: './data/china.geojson',
stroke: '#ff6600',
strokeWidth: 2,
fill: '#ff6600',
clampToGround: true
}).addTo(map);
// 内联数据
new GeoJsonLayer({
data: { type: 'FeatureCollection', features: [...] }
}).addTo(map);GraphicLayer — 图形容器
承载 Graphic 图形对象的容器图层。
| 参数 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| graphics | Array | [] | 初始图形 |
| clustering | object | — | 聚合配置 { enabled, pixelRange, minimumClusterSize } |
| 方法 | 签名 | 说明 |
|------|------|------|
| addGraphic | (graphic) | 添加单个图形 |
| addGraphics | (graphics[]) | 批量添加 |
| removeGraphic | (graphic) | 移除图形 |
| getGraphicById | (id) → BaseGraphic? | 按 id 查找 |
| getGraphics | () → Array | 获取全部(副本) |
| clear / clearGraphics | () | 清空全部 |
| flyTo | (options?) | 飞行到范围 |
const layer = new GraphicLayer({ id: 'marks', name: '标注' });
map.addLayer(layer);
layer.addGraphic(point);
layer.addGraphics([line, polygon]);
layer.removeGraphic(point);
layer.clear();KmlLayer / CzmlLayer
// KML
new KmlLayer({ url: './data/file.kml' }).addTo(map);
// CZML
const czml = new CzmlLayer({ url: './data/scene.czml' });
map.addLayer(czml);
// CZML 增量更新
await czml.process(newCzmlPackets);共享方法:getEntities()、flyTo(options?)、raise()、lower()、raiseToTop()、lowerToBottom()
CzmlLayer 独有方法:process(czmlPacket) — 异步追加/更新 CZML 数据包。
图形 API
BaseGraphic — 公共接口
所有图形继承 BaseGraphic,共享以下构造参数和方法。
构造参数
| 参数 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| id | string | 自动 UUID | 唯一标识 |
| name | string | '' | 名称 |
| show | boolean | true | 可见性 |
| position | number[] | — | 位置 [lng, lat, height] |
| style | object | {} | 样式(各图形不同) |
| attr | object | {} | 自定义属性 |
| popup | string \| Function | — | 弹窗内容(HTML / 返回 HTML 的函数) |
| tooltip | string \| Function | — | 悬浮提示文本 |
| onClick | Function | — | 点击回调 (graphic, event) |
| onMouseover | Function | — | 鼠标进入 (graphic, event) |
| onMouseout | Function | — | 鼠标离开 (graphic) |
公共方法
| 方法 | 签名 | 说明 |
|------|------|------|
| setPosition | (position: number[]) | 更新位置 |
| setShow | (show: boolean) | 显隐 |
| setStyle | (style: object) | 合并更新样式 |
| flyTo | (options?) | 相机飞行到此图形 |
| entity | getter | 底层 Cesium.Entity |
PointGraphic
style
| 属性 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| pixelSize | number | 10 | 像素大小 |
| color | string | '#ff0000' | 颜色 |
| outlineColor | string | — | 描边色 |
| outlineWidth | number | 0 | 描边宽 |
| heightReference | string | — | 'clamp' / 'relative' / 'none' |
| scaleByDistance | number[] | — | [near, nearScale, far, farScale] |
| distanceDisplayCondition | number[] | — | [near, far] |
new PointGraphic({
position: [116.4, 39.9, 0],
style: { pixelSize: 12, color: '#ff0000', outlineColor: '#fff', outlineWidth: 2 },
popup: '<b>北京</b>'
});BillboardGraphic
style
| 属性 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| image | string | — | 图片 URL |
| scale | number | 1.0 | 缩放 |
| width / height | number | — | 像素尺寸 |
| rotation | number | 0 | 旋转角(度) |
| color | string | — | 着色 |
| pixelOffset | number[] | — | [x, y] 像素偏移 |
| horizontalOrigin | string | 'center' | 'center'/'left'/'right' |
| verticalOrigin | string | 'center' | 'center'/'top'/'bottom' |
| sizeInMeters | boolean | — | 以米为单位 |
| heightReference | string | — | 高度参考 |
| scaleByDistance | number[] | — | NearFarScalar |
| distanceDisplayCondition | number[] | — | [near, far] |
new BillboardGraphic({
position: [116.4, 39.9, 0],
style: {
image: './icons/marker.png',
width: 32, height: 32,
verticalOrigin: 'bottom'
}
});LabelGraphic
style
| 属性 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| text | string | '' | 文本 |
| font | string | '14px sans-serif' | CSS 字体 |
| scale | number | 1.0 | 缩放 |
| fillColor | string | '#ffffff' | 填充色 |
| outlineColor | string | '#000000' | 描边色 |
| outlineWidth | number | 1 | 描边宽 |
| showBackground | boolean | false | 显示背景 |
| backgroundColor | string | — | 背景色 |
| backgroundPadding | number[] | — | [x, y] 内边距 |
| labelStyle | string | — | 'fill' / 'outline' / 'fillAndOutline' |
| pixelOffset | number[] | — | [x, y] |
| horizontalOrigin | string | 'center' | 水平对齐 |
| verticalOrigin | string | 'center' | 垂直对齐 |
| heightReference | string | — | 高度参考 |
| scaleByDistance | number[] | — | NearFarScalar |
| distanceDisplayCondition | number[] | — | [near, far] |
new LabelGraphic({
position: [116.4, 39.9, 100],
style: {
text: '北京',
font: '16px Microsoft YaHei',
fillColor: '#ffffff',
outlineColor: '#000000',
outlineWidth: 2
}
});PolylineGraphic
额外构造参数:positions: number[][](顶层,非 style 内)
可在顶层使用 width、color、clampToGround 简写,自动合并到 style。
style
| 属性 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| width | number | 3 | 线宽 |
| color | string | '#ff0000' | 颜色 |
| material | object | — | 线材质(见下) |
| clampToGround | boolean | false | 贴地 |
| depthFailColor | string | — | 深度测试失败时颜色 |
| arcType | string | 'geodesic' | 'geodesic' / 'rhumb' / 'none' |
| zIndex | number | — | 层级 |
| classificationType | string | — | 'terrain' / '3dtiles' / 'both' |
线材质类型
| material.type | 参数 | 效果 |
|---------------|------|------|
| 'dash' | color, gapColor, dashLength | 虚线 |
| 'glow' | color, glowPower | 发光 |
| 'arrow' | color | 箭头 |
| 'outline' | color, outlineColor, outlineWidth | 描边 |
额外方法:setPositions(positions: number[][])
// 纯色线
new PolylineGraphic({
positions: [[116.0, 39.9, 0], [117.0, 39.9, 0]],
style: { width: 5, color: '#ff0000' }
});
// 发光箭头线
new PolylineGraphic({
positions: [[116.0, 39.9, 0], [117.0, 40.5, 0]],
style: { width: 8, material: { type: 'arrow', color: 'cyan' } }
});PolygonGraphic
额外构造参数:positions: number[][](外环),holes: number[][][](内孔,可选)
style
| 属性 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| color | string | 'rgba(255,255,0,0.4)' | 填充色 |
| material | object | — | 面材质 |
| fill | boolean | true | 填充 |
| outline | boolean | true | 描边 |
| outlineColor | string | '#ffff00' | 描边色 |
| outlineWidth | number | 2 | 描边宽 |
| height | number | — | 拉伸底部高度 |
| extrudedHeight | number | — | 拉伸顶部高度 |
| perPositionHeight | boolean | false | 逐顶点高度 |
| clampToGround | boolean | false | 贴地 |
| heightReference | string | — | 高度参考 |
| classificationType | string | — | 分类类型 |
| stRotation | number | — | 纹理旋转(度) |
额外方法:setPositions(positions)、setHoles(holes)
// 半透明多边形
new PolygonGraphic({
positions: [[116,39.5,0],[117,39.5,0],[117,40.5,0],[116,40.5,0]],
style: { color: 'rgba(68,136,255,0.5)', outline: true, outlineColor: '#fff' }
});
// 拉伸体
new PolygonGraphic({
positions: [[116,39.5,0],[117,39.5,0],[117,40.5,0],[116,40.5,0]],
style: { color: '#4488ff', height: 0, extrudedHeight: 500 }
});CircleGraphic
可在顶层使用 radius、color 简写。
style
| 属性 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| radius | number | 1000 | 半径(米) |
| color | string | 'rgba(0,255,0,0.3)' | 填充色 |
| material | object | — | 面材质 |
| fill / outline | boolean | true | 填充/描边 |
| outlineColor | string | '#00ff00' | 描边色 |
| outlineWidth | number | 2 | 描边宽 |
| height / extrudedHeight | number | — | 拉伸高度 |
| clampToGround | boolean | false | 贴地 |
| heightReference | string | — | 高度参考 |
| rotation | number | — | 旋转(度) |
额外方法:setRadius(radius: number)
new CircleGraphic({
position: [116.4, 39.9, 0],
radius: 5000,
style: { color: 'rgba(255,0,0,0.4)', outline: true, outlineColor: '#ff0000' }
});RectangleGraphic
额外构造参数:coordinates: [west, south, east, north](度)
style:与 PolygonGraphic 类似 — color、fill、outline、outlineColor、outlineWidth、height、extrudedHeight、rotation、clampToGround、heightReference、classificationType
额外方法:setCoordinates(coordinates: number[])
new RectangleGraphic({
coordinates: [116.0, 39.5, 117.0, 40.5],
style: { color: 'rgba(255,255,0,0.4)', extrudedHeight: 200 }
});WallGraphic
额外构造参数:positions: number[][]
style
| 属性 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| color | string | 'rgba(255,0,0,0.6)' | 填充色 |
| material | object | — | 面材质 |
| outline | boolean | false | 描边 |
| outlineColor | string | '#ffffff' | 描边色 |
| outlineWidth | number | 1 | 描边宽 |
| maximumHeights | number[] | — | 各顶点最大高度 |
| minimumHeights | number[] | — | 各顶点最小高度 |
额外方法:setPositions(positions: number[][])
new WallGraphic({
positions: [[116.0,39.9,0],[117.0,39.9,0],[117.5,40.5,0]],
style: { maximumHeights: [500,500,500], minimumHeights: [0,0,0], color: 'rgba(0,0,255,0.6)' }
});ModelGraphic
额外构造参数:orientation: { heading, pitch, roll }(度)
style
| 属性 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| url / uri | string | — | glTF/glb URL |
| scale | number | 1.0 | 缩放 |
| minimumPixelSize | number | 64 | 最小像素 |
| maximumScale | number | — | 最大缩放 |
| shadows | boolean | false | 阴影 |
| runAnimations | boolean | true | 播放内嵌动画 |
| silhouetteColor | string | — | 轮廓色 |
| silhouetteSize | number | 2 | 轮廓大小 |
| color | string | — | 着色 |
| colorBlendMode | string | 'highlight' | 'highlight' / 'replace' / 'mix' |
| heightReference | string | — | 高度参考 |
额外方法:setOrientation({ heading, pitch, roll })
new ModelGraphic({
position: [116.4, 39.9, 0],
orientation: { heading: 45, pitch: 0, roll: 0 },
style: { url: './models/car.glb', scale: 1.0, minimumPixelSize: 64 }
});BoxGraphic / CylinderGraphic / EllipsoidGraphic / EllipseGraphic
| 图形 | 定位参数 | 核心 style 属性 |
|------|----------|----------------|
| BoxGraphic | position = 中心 | dimensions: [x, y, z](米,默认 [20,20,40]) |
| CylinderGraphic | position = 底部中心 | length(高,默认100), topRadius(默认20), bottomRadius(默认20), slices |
| EllipsoidGraphic | position = 球心 | radii: [x, y, z](米,默认 [50,50,50]), stackPartitions(32), slicePartitions(32) |
| EllipseGraphic | position = 中心 | semiMajorAxis(5000m), semiMinorAxis(3000m), rotation(度) |
以上四种图形均支持 color、fill、outline、outlineColor、outlineWidth、shadows、heightReference、distanceDisplayCondition 等通用样式。
工具类
Draw — 绘制工具
所有方法返回 Promise。左键操作,右键结束。调用 stop() 中断进行中操作(Promise resolve { cancelled: true })。
const draw = new Draw(map);| 方法 | 返回值 | 操作方式 |
|------|--------|----------|
| draw.point(style?) | { position: [lng,lat,h], entity } | 左键单击 |
| draw.polyline(style?) | { positions: [[lng,lat,h],...], entity } | 左键添加点,右键结束 |
| draw.polygon(style?) | { positions: [...], entity } | 左键添加点(>=3),右键结束 |
| draw.rectangle(style?) | { coordinates: [w,s,e,n], entity } | 左键两次(对角) |
| draw.circle(style?) | { center: [lng,lat,h], radius: 米, entity } | 左键两次(圆心+半径) |
| draw.stop() | Draw | 中断当前操作 |
| draw.clear() | Draw | 清除所有绘制结果 |
| draw.destroy() | void | 释放资源 |
完整示例
const draw = new Draw(map);
// 绘制一个点
const pointResult = await draw.point({ pixelSize: 12, color: 'red' });
console.log('点位:', pointResult.position);
// 绘制多边形
const polyResult = await draw.polygon();
console.log('顶点:', polyResult.positions);
// 右键取消、或用按钮中断
document.getElementById('cancel-btn').onclick = () => draw.stop();
// 清除所有绘制
draw.clear();Measure — 量算工具
与 Draw 类似的 Promise API。
const measure = new Measure(map);| 方法 | 返回值 | 说明 |
|------|--------|------|
| measure.distance() | { distance: 米, positions: [...] } | 距离量算(折线) |
| measure.area() | { area: 平方米, positions: [...] } | 面积量算(多边形,>=3点) |
| measure.height() | { height: 米, position: [lng,lat,h] } | 高度量算(单点) |
| measure.angle() | { angle: 度, positions: [p1,p2,p3] } | 角度量算(三点,p2为顶点) |
| measure.stop() | Measure | 中断当前操作 |
| measure.clear() | Measure | 清除所有量算结果及标注 |
| measure.destroy() | void | 释放资源 |
const measure = new Measure(map);
const dist = await measure.distance();
console.log(`总距离: ${dist.distance.toFixed(2)} 米`);
const area = await measure.area();
console.log(`面积: ${area.area.toFixed(2)} 平方米`);
measure.clear();控件
Navigation
罗盘 + 缩放按钮 + 比例尺(基于 cesium-navigation-es6)。
const map = new GeoMap('map', {
control: {
navigation: true
// 或: navigation: { compass: true, zoomControls: true, distanceLegend: true }
}
});| 方法 | 说明 |
|------|------|
| map.navigation.setNavigationLocked(locked) | 锁定/解锁交互 |
| map.navigation.getNavigationLocked() | 查询锁定状态 |
| map.navigation.getInstance() | 获取底层 CesiumNavigation |
| map.navigation.destroy() | 销毁 |
NavBar
左侧垂直导航栏:罗盘、复位、2D/3D 切换、缩放。
const map = new GeoMap('map', {
control: {
navBar: true
// 或: navBar: { position: 'left', showCompass: true, showHome: true, showSceneMode: true, showZoom: true, zoomFactor: 2 }
}
});| 方法 | 说明 |
|------|------|
| map.navBar.show() / hide() / toggle() | 显隐控制 |
| map.navBar.destroy() | 销毁 |
Toolbar — 状态栏
底部状态栏:实时显示鼠标经纬度、投影坐标、海拔、层级、朝向、俯仰角、视高、FPS、比例尺。
const map = new GeoMap('map', { control: { toolbar: true } });| 方法 | 返回值 | 说明 |
|------|--------|------|
| map.toolbar.show() | Toolbar | 显示 |
| map.toolbar.hide() | Toolbar | 隐藏 |
| map.toolbar.toggle() | Toolbar | 切换 |
| map.toolbar.getInfo() | object | 获取当前状态快照 |
| map.toolbar.destroy() | void | 销毁 |
getInfo() 返回值:
{
lon, lat, // 鼠标经纬度
altitude, // 地形海拔
heading, pitch, // 相机朝向/俯仰(度)
cameraHeight, // 相机高度(米)
level, // 层级 (0-22)
fps // 帧率
}Toolbar 构造选项可精细控制显示项:
| 属性 | 默认 | 说明 |
|------|------|------|
| showLon / showLat | true | 经纬度 |
| showProjection | true | Web Mercator X/Y |
| showAltitude | true | 海拔 |
| showLevel | true | 层级 |
| showHeading / showPitch | true | 朝向/俯仰 |
| showCameraHeight | true | 视高 |
| showFPS | true | FPS |
| showScalebar | true | 比例尺 |
管理器
EventManager — 事件
地图初始化后通过 map.events 访问,统一管理所有交互事件。
map.events.on('leftClick', (e) => {
console.log(e.lonlat); // [lng, lat, height]
console.log(e.entity); // 拾取到的 Entity
console.log(e.pickedObject); // scene.pick() 原始结果
});
map.events.on('mouseMove', (e) => { ... });
map.events.once('leftClick', handler);
map.events.off('leftClick', handler);鼠标事件回调参数
| 属性 | 类型 | 说明 |
|------|------|------|
| type | string | 事件类型名 |
| raw | object | Cesium 原始 movement |
| position | Cartesian2 | 屏幕坐标 |
| pickedObject | object | scene.pick() 结果 |
| entity | Entity | 拾取到的实体 |
| primitive | object | 拾取到的图元 |
| cartesian | Cartesian3 | 世界坐标 |
| lonlat | number[] | [lng, lat, height] |
支持的事件名
鼠标事件:leftClick、leftDoubleClick、leftDown、leftUp、rightClick、rightDown、rightUp、middleClick、middleDown、middleUp、mouseMove、wheel
场景事件:cameraChanged、sceneModeChanged、preRender、postRender、morphComplete、morphStart
PopupManager — 弹窗
通过 map.popup 访问。给图形设置 popup 属性后,左键点击自动弹出。
// 声明式 — 图形自带 popup
new PointGraphic({
position: [116.4, 39.9, 0],
popup: '<b>北京</b><p>中国首都</p>'
});
// 命令式
map.popup.show('<b>自定义弹窗</b>', [116.4, 39.9, 0]);
map.popup.hide();构造选项:
| 属性 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| auto | boolean | true | 自动拦截左键点击 |
| closeButton | boolean | true | 关闭按钮 |
| followCamera | boolean | true | 跟随相机移动 |
| offset | number[] | [0, -10] | 像素偏移 |
| className | string | 'geoglobe-popup' | CSS 类名 |
TooltipManager — 提示
通过 map.tooltip 访问。给图形设置 tooltip 属性后,鼠标悬停自动显示。
new PointGraphic({
position: [116.4, 39.9, 0],
tooltip: '北京市'
});
// 命令式
map.tooltip.show('提示文本', { x: 100, y: 200 });
map.tooltip.hide();构造选项:
| 属性 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| offset | number[] | [14, -14] | 像素偏移 |
| className | string | 'geoglobe-tooltip' | CSS 类名 |
SpaceSkyBox — 天空盒
程序化生成星空背景,支持闪烁和流星效果。全部为静态方法。
通过构造参数配置
const map = new GeoMap('map', {
skyBox: {
animate: true,
speed: 2,
starCount: 800,
meteorInterval: 3000,
meteorSpeed: 1,
maxMeteors: 3
}
});运行时控制
// 天空盒切换
map.setSkyBox('space');
map.setSkyBox('default');
map.setSkyBox(false);
map.setSkyBox({ sources: { positiveX: '...', negativeX: '...', ... } });
// 星星闪烁动画
SpaceSkyBox.startAnimation(map.viewer, { speed: 2, starCount: 800 });
SpaceSkyBox.stopAnimation();
SpaceSkyBox.setRotationSpeed(4);
// 流星效果
SpaceSkyBox.startMeteorAnimation(map.viewer, {
interval: 3000,
speed: 1,
maxMeteors: 3
});
SpaceSkyBox.stopMeteorAnimation();
SpaceSkyBox.setMeteorInterval(5000);create() 选项
| 属性 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| resolution | number | 2048 | 单面纹理分辨率 |
| starCount | number | 9000 | 基础星星数 |
| brightStarCount | number | 30 | 亮星数(带光晕) |
| nebulaIntensity | number | 0.5 | 星云亮度 (0~1) |
| milkyWayIntensity | number | 0.35 | 银河带亮度 (0~1) |
| backgroundColor | string | '#000005' | 背景色 |
常量与枚举
框架封装了常用 Cesium 常量,无需直接引用 Cesium 命名空间:
import {
// 场景 & 渲染
SceneMode, Color, HeightReference,
HorizontalOrigin, VerticalOrigin, LabelStyle,
ClassificationType, ArcType, ShadowMode, ColorBlendMode,
// 坐标 & 几何
Cartesian2, Cartesian3, Cartesian4, Cartographic,
Rectangle, PolygonHierarchy, BoundingSphere,
// 数学 & 变换
CesiumMath, Quaternion, Matrix2, Matrix3, Matrix4,
TranslationRotationScale, HeadingPitchRange, HeadingPitchRoll,
// 可见性
NearFarScalar, DistanceDisplayCondition,
// 材质属性
Material, MaterialProperty, CallbackProperty,
ColorMaterialProperty, ImageMaterialProperty,
CheckerboardMaterialProperty, StripeMaterialProperty, GridMaterialProperty,
PolylineGlowMaterialProperty, PolylineOutlineMaterialProperty,
PolylineDashMaterialProperty, PolylineArrowMaterialProperty,
// 动画/采样
ConstantProperty, SampledProperty, SampledPositionProperty,
TimeIntervalCollectionProperty,
// 时间
JulianDate, TimeInterval, TimeIntervalCollection,
ClockRange, ClockStep,
// 事件
ScreenSpaceEventType, ScreenSpaceEventHandler,
// Primitive API
Resource, Primitive, GeometryInstance, PolygonGeometry, MaterialAppearance,
// 地形
CustomHeightmapTerrainProvider, EllipsoidTerrainProvider
} from 'geoglobe-3d';快速示例:
const red = Color.fromCssColorString('#ff0000');
const pos = Cartesian3.fromDegrees(116.4, 39.9, 100);
const rad = CesiumMath.toRadians(45);实战案例
案例 1 — 加载 GeoJSON + Popup 交互
const map = new GeoMap('map', {
skyBox: 'space',
camera: { position: [104, 35, 5000000] },
control: { toolbar: true, navBar: true }
});
const geojson = new GeoJsonLayer({
url: './data/china.geojson',
stroke: '#ff6600',
strokeWidth: 2,
fill: 'rgba(255,102,0,0.3)',
clampToGround: true,
onClick: (entity) => {
const name = entity.name || '未命名';
map.popup.show(`<b>${name}</b>`, entity.position?.getValue());
}
});
map.addLayer(geojson);
geojson.on('load', () => {
console.log('GeoJSON 加载完成');
geojson.flyTo();
});案例 2 — 3D Tiles + 图形叠加
const map = new GeoMap('map', {
terrain: { enabled: true },
camera: { position: [116.4, 39.9, 3000], pitch: -45 }
});
// 加载三维建筑
const tileset = new TilesetLayer({
url: 'https://your-server/tileset.json',
maximumScreenSpaceError: 8,
style: { color: "color('white', 0.8)" }
});
map.addLayer(tileset);
// 在建筑旁添加标注
const marks = new GraphicLayer({ id: 'marks' });
map.addLayer(marks);
marks.addGraphics([
new BillboardGraphic({
position: [116.4, 39.9, 100],
style: { image: './icons/pin.png', width: 32, height: 32, verticalOrigin: 'bottom' },
popup: '<h3>国贸大厦</h3><p>高度: 330米</p>'
}),
new LabelGraphic({
position: [116.4, 39.9, 350],
style: { text: '国贸大厦', font: '14px Microsoft YaHei', fillColor: '#fff' }
})
]);案例 3 — 绘制 + 量算联动
const draw = new Draw(map);
const measure = new Measure(map);
document.getElementById('btn-draw-polygon').onclick = async () => {
const result = await draw.polygon();
if (!result.cancelled) {
console.log('绘制完成,顶点数:', result.positions.length);
}
};
document.getElementById('btn-measure-dist').onclick = async () => {
const result = await measure.distance();
if (!result.cancelled) {
alert(`总距离: ${(result.distance / 1000).toFixed(2)} km`);
}
};
document.getElementById('btn-clear').onclick = () => {
draw.clear();
measure.clear();
};案例 4 — 时间动画 + CZML 轨迹
const map = new GeoMap('map', {
control: { animation: true, timeline: true }
});
const czml = new CzmlLayer({ url: './data/satellite.czml' });
map.addLayer(czml);
czml.on('load', () => {
czml.flyTo();
map.setClock({
multiplier: 100,
clockRange: 'loop',
animate: true
});
});FAQ
Q: 地图显示黑屏
检查浏览器 WebGL 2.0 支持,确保 dist/ 目录完整部署,查看控制台报错。
Q: 3D Tiles 位置偏移
使用 TilesetLayer 的 position / rotation 参数调整:
new TilesetLayer({
url: '...',
position: [lng, lat, height],
rotation: { heading: 0, pitch: 0, roll: 0 }
});Q: 影像图层跨域报错 服务端需配置 CORS,或通过代理转发请求。
Q: 如何访问底层 Cesium API
const viewer = map.viewer; // Cesium.Viewer
const scene = map.viewer.scene; // Cesium.Scene
const globe = scene.globe; // Cesium.GlobeQ: 页面卸载时资源释放
window.addEventListener('beforeunload', () => map.destroy());Q: ESM 项目 Cesium Worker 路径配置
在 Vite/Webpack 中需配置 CESIUM_BASE_URL 指向 Cesium 静态资源目录。UMD 版本框架自动处理。
项目结构
zgis-cesium/
├── src/
│ ├── index.js # 主入口,统一导出
│ ├── constants/ # 常量与枚举封装
│ ├── core/
│ │ ├── Map.js # GeoMap 核心类
│ │ ├── EventManager.js # 事件管理
│ │ ├── PopupManager.js # 弹窗管理
│ │ ├── TooltipManager.js # 提示管理
│ │ └── SpaceSkyBox.js # 程序化天空盒
│ ├── graphic/ # 14 种图形类
│ ├── layer/ # 8 种图层类
│ ├── tool/ # Draw / Measure
│ ├── control/ # Navigation / NavBar / Toolbar
│ └── utils/ # 工具函数
├── dist/ # 构建产物
├── examples/ # 13 个示例 HTML
├── Build/ # Cesium 本地源(UMD 打包用)
├── rollup.config.js # Rollup 构建配置
└── package.json示例列表
| 文件 | 说明 |
|------|------|
| base.html | 基础示例:Toolbar + 工具栏 |
| advanced.html | 高级功能:图形、图层、工具综合 |
| graphic-layers.html | 各类图形演示 |
| layer-management.html | 图层管理与排序 |
| data-layers.html | GeoJSON / KML / CZML 数据图层 |
| terrain.html | 地形加载 |
| terrain-custom.html | 自定义高度图地形 |
| popup-tooltip.html | Popup 弹窗与 Tooltip 提示 |
| measure-tools.html | 距离、面积、高度、角度量算 |
| time-system.html | 时钟与时间动画系统 |
| camera-scene.html | 相机控制与场景模式切换 |
| imagery-layers.html | 影像图层类型演示 |
| materials.html | Fabric 材质与自定义着色器 |
npm start 后访问 http://localhost:8080。
geoGlobe3D — 让三维地图开发更简单
