Vue3 + Cesium实战:手把手教你加载GeoJSON绘制中国地图(附完整代码)

张开发
2026/4/21 16:40:20 15 分钟阅读

分享文章

Vue3 + Cesium实战:手把手教你加载GeoJSON绘制中国地图(附完整代码)
Vue3 Cesium实战从零构建中国地图可视化应用在数据可视化领域地理空间信息的呈现一直是极具挑战性和价值的课题。当Vue3的响应式特性遇上Cesium强大的三维地理引擎开发者能够创造出令人惊艳的交互式地图应用。本文将带你完整实现一个中国地图可视化项目涵盖从数据获取到高级定制的全流程。1. 环境搭建与基础配置1.1 创建Vue3项目使用Vite快速初始化项目是当前前端开发的最佳实践npm create vitelatest cesium-china-map --template vue-ts cd cesium-china-map npm install cesium cesium/engine types/cesium --save1.2 Cesium集成配置在vite.config.ts中添加Cesium特殊配置import { defineConfig } from vite import cesium from vite-plugin-cesium export default defineConfig({ plugins: [cesium()], optimizeDeps: { exclude: [cesium/engine] } })1.3 初始化地图容器创建src/components/CesiumViewer.vue基础组件template div idcesium-container classfull-screen/div /template script setup langts import { onMounted } from vue import { Viewer } from cesium onMounted(() { const viewer new Viewer(cesium-container, { terrainProvider: Cesium.createWorldTerrain(), timeline: false, animation: false, baseLayerPicker: false }) }) /script style scoped .full-screen { position: absolute; top: 0; left: 0; width: 100%; height: 100%; } /style2. 获取与处理GeoJSON数据2.1 数据源选择与获取推荐使用阿里云DataV提供的标准GeoJSON数据const CHINA_GEOJSON_URL https://geo.datav.aliyun.com/areas_v3/bound/100000_full.json2.2 数据预处理技巧为提高加载性能建议对原始数据进行优化// 示例简化几何数据 function simplifyGeoJSON(geojson) { return { type: FeatureCollection, features: geojson.features.map(feature ({ ...feature, geometry: simplifyGeometry(feature.geometry, 0.01) })) } }2.3 本地缓存策略实现数据本地存储与更新机制const cacheGeoJSON async (url: string) { const cacheKey geo-${md5(url)} const cached localStorage.getItem(cacheKey) if (cached) { return JSON.parse(cached) } else { const response await fetch(url) const data await response.json() localStorage.setItem(cacheKey, JSON.stringify(data)) return data } }3. 核心地图渲染实现3.1 基础加载实现创建地图加载函数const loadChinaMap async (viewer: Viewer) { try { const dataSource await GeoJsonDataSource.load(CHINA_GEOJSON_URL, { stroke: Color.RED.withAlpha(0.6), fill: Color.SKYBLUE.withAlpha(0.3), strokeWidth: 2, clampToGround: true }) viewer.dataSources.add(dataSource) return dataSource } catch (error) { console.error(加载GeoJSON失败:, error) } }3.2 高级样式定制实现省份差异化渲染const applyRandomStyles (dataSource: GeoJsonDataSource) { const entities dataSource.entities.values entities.forEach(entity { // 随机颜色 entity.polygon.material new ColorMaterialProperty( Color.fromRandom({ red: [0.2, 0.8], green: [0.2, 0.8], blue: [0.2, 0.8], alpha: 0.7 }) ) // 基于省份ID的高度 const height (parseInt(entity.id) % 10) * 50000 entity.polygon.extrudedHeight new ConstantProperty(height) }) }3.3 性能优化技巧针对大数据量渲染的优化方案const optimizePerformance (viewer: Viewer) { // 1. 启用渐进式加载 viewer.scene.globe.enableLighting true // 2. 设置适当的细节层级 viewer.scene.screenSpaceCameraController.maximumZoomDistance 10000000 // 3. 使用WebWorker处理数据 const worker new Worker(./geoWorker.js) worker.postMessage({ action: process, url: CHINA_GEOJSON_URL }) }4. 交互功能增强4.1 省份选择高亮实现鼠标交互反馈const setupSelectionHandler (viewer: Viewer) { const handler new ScreenSpaceEventHandler(viewer.scene.canvas) handler.setInputAction((movement: any) { const picked viewer.scene.pick(movement.endPosition) if (picked picked.id) { // 重置所有实体颜色 viewer.dataSources.forEach(ds { ds.entities.values.forEach(e { e.polygon.material originalColors.get(e) || defaultColor }) }) // 高亮选中实体 picked.id.polygon.material new ColorMaterialProperty( Color.YELLOW.withAlpha(0.9) ) } }, ScreenSpaceEventType.MOUSE_MOVE) }4.2 信息弹窗展示创建动态信息窗口组件template div v-ifshowPopup classcesium-popup :stylepopupStyle h3{{ currentFeature.name }}/h3 p面积: {{ currentFeature.area }} km²/p p人口: {{ currentFeature.population }}万/p /div /template script setup langts import { ref } from vue const showPopup ref(false) const popupStyle ref({}) const currentFeature ref({}) // 在Cesium交互中更新弹窗状态 const updatePopup (position: Cartesian2, feature: any) { currentFeature.value feature popupStyle.value { left: ${position.x 10}px, top: ${position.y 10}px } showPopup.value true } /script4.3 3D地形集成增强地图三维效果const enableTerrain (viewer: Viewer) { viewer.terrainProvider new Cesium.CesiumTerrainProvider({ url: https://assets.agi.com/stk-terrain/world, requestWaterMask: true, requestVertexNormals: true }) viewer.scene.globe.depthTestAgainstTerrain true }5. 高级功能扩展5.1 动态数据可视化实现人口数据的热力图效果const createHeatmap (viewer: Viewer, populationData: any[]) { const instances populationData.map(item { const position Cartesian3.fromDegrees(...item.center) return new GeometryInstance({ geometry: new RectangleGeometry({ rectangle: Rectangle.fromDegrees( item.bbox[0], item.bbox[1], item.bbox[2], item.bbox[3] ), height: item.population * 1000 }), attributes: { color: ColorMaterialProperty.fromColor( Color.fromHsl( (1 - item.population / 5000) * 0.4, 1.0, 0.5, 0.7 ) ) } }) }) viewer.scene.primitives.add(new Primitive({ geometryInstances: instances, appearance: new PerInstanceColorAppearance({ flat: true, translucent: true }) })) }5.2 时间轴动画创建GDP增长动画const setupTimelineAnimation (viewer: Viewer, gdpData: any[]) { const start JulianDate.fromIso8601(2000-01-01) const end JulianDate.fromIso8601(2020-01-01) viewer.timeline.zoomTo(start, end) gdpData.forEach(province { const entity viewer.entities.add({ name: province.name, polygon: { hierarchy: new ConstantProperty(province.boundary), extrudedHeight: new SampledProperty(Number), material: new ColorMaterialProperty( Color.fromHsl(0.6, 1.0, 0.5, 0.7) ) } }) province.yearlyData.forEach((yearData: any) { const time JulianDate.fromIso8601(yearData.year -01-01) entity.polygon.extrudedHeight.addSample(time, yearData.gdp * 1000) }) }) }5.3 多数据源融合结合KML数据展示特殊区域const loadSpecialZones async (viewer: Viewer) { const economicZones await KmlDataSource.load( ./special-zones.kmz, { camera: viewer.scene.camera, clampToGround: true } ) viewer.dataSources.add(economicZones) // 自定义KML样式 economicZones.entities.values.forEach(entity { if (entity.polygon) { entity.polygon.material Color.RED.withAlpha(0.3) entity.polygon.outline true entity.polygon.outlineColor Color.RED } }) }6. 项目部署与优化6.1 构建配置优化调整vite.config.js生产环境配置export default defineConfig({ build: { chunkSizeWarningLimit: 2000, rollupOptions: { output: { manualChunks: { cesium: [cesium] } } } } })6.2 CDN加速策略通过externals减少包体积export default { optimizeDeps: { exclude: [cesium] } }6.3 按需加载实现动态加载Cesium组件const loadCesiumModule async () { const { Viewer } await import(cesium) return Viewer }在大型地理信息项目开发中我经常遇到性能瓶颈问题。通过实践发现将几何数据处理工作转移到WebWorker中配合合理的LOD(Level of Detail)策略能够显著提升大规模地理数据的渲染性能。

更多文章