保姆级教程:在Vue3 + Vite + TS项目中,用Cesium 1.107加载天地图(附完整代码和TK申请避坑)

张开发
2026/4/11 21:16:10 15 分钟阅读

分享文章

保姆级教程:在Vue3 + Vite + TS项目中,用Cesium 1.107加载天地图(附完整代码和TK申请避坑)
Vue3 Vite TS 项目集成 Cesium 与天地图全流程实战指南第一次在 Vue3 项目中尝试集成 Cesium 和天地图时我花了整整两天时间才让地图正常显示。那些看似简单的配置参数背后藏着不少新手容易踩的坑。本文将带你从零开始用最直观的方式掌握这套技术栈的核心要点。1. 环境准备与项目初始化在开始之前确保你的开发环境满足以下条件Node.js 16.x 或更高版本npm 8.x 或 yarn 1.22.xVS Code 或其他现代 IDE创建一个全新的 Vite Vue3 TypeScript 项目npm create vitelatest cesium-tianditu-demo --template vue-ts cd cesium-tianditu-demo npm install接下来安装 Cesium 相关依赖npm install cesium types/cesium vite-plugin-cesium -D关键配置在vite.config.ts中添加 Cesium 插件import { defineConfig } from vite import vue from vitejs/plugin-vue import cesium from vite-plugin-cesium export default defineConfig({ plugins: [vue(), cesium()] })提示使用 vite-plugin-cesium 可以自动处理 Cesium 的静态资源路径问题比手动配置更可靠。2. 天地图 TK 申请与权限管理天地图服务需要 Access Key简称 TK才能调用。申请过程中有几个容易忽略的细节访问天地图开放平台并完成注册在应用管理中创建新应用时服务类型选择浏览器端填写正确的白名单域名开发环境可暂时使用localhost申请成功后你会在应用详情页看到类似这样的 TK7a3a8b9c0d1e2f3g4h5i6j7k8l9m0n注意测试阶段每日调用限额为 10 万次正式上线前需申请商用授权。3. Cesium 核心集成与 Vue3 组件封装在src/components下创建CesiumViewer.vue组件script setup langts import { onMounted, onUnmounted, ref } from vue import { Viewer } from cesium const props defineProps{ tiandituKey: string }() const viewerContainer refHTMLDivElement() let viewer: Viewer | null null onMounted(() { if (!viewerContainer.value) return viewer new Viewer(viewerContainer.value, { animation: false, baseLayerPicker: false, fullscreenButton: false, vrButton: false, geocoder: false, homeButton: false, infoBox: false, sceneModePicker: false, selectionIndicator: false, timeline: false, navigationHelpButton: false, shouldAnimate: true, imageryProvider: false // 禁用默认影像 }) // 移除默认的版权信息 viewer.cesiumWidget.creditContainer.style.display none }) onUnmounted(() { viewer?.destroy() }) /script template div refviewerContainer classcesium-container/div /template style scoped .cesium-container { width: 100%; height: 100vh; } /style这个基础组件实现了干净的 Viewer 初始化移除了不必要的控件自动内存管理组件卸载时销毁实例TypeScript 类型安全4. 天地图 WMTS 服务深度解析天地图提供多种图层服务每种都有特定的 URL 结构和参数服务类型图层代码URL 路径格式矢量底图vec/vec_w/wmtsjpeg矢量注记cva/cva_w/wmtsjpeg影像底图img/img_w/wmtsjpeg影像注记cia/cia_w/wmtsjpeg在组件中添加图层加载方法const addTiandituLayer (type: vec | cva | img | cia) { if (!viewer) return const layerMap { vec: { name: 矢量底图, path: vec_w }, cva: { name: 矢量注记, path: cva_w }, img: { name: 影像底图, path: img_w }, cia: { name: 影像注记, path: cia_w } } const { name, path } layerMap[type] viewer.imageryLayers.addImageryProvider( new WebMapTileServiceImageryProvider({ url: http://t0.tianditu.gov.cn/${path}/wmts?servicewmtsrequestGetTileversion1.0.0LAYER${type}tileMatrixSetwTileMatrix{TileMatrix}TileRow{TileRow}TileCol{TileCol}styledefaultformattilestk${props.tiandituKey}, layer: tdt_${type}_layer, style: default, format: image/jpeg, tileMatrixSetID: w, maximumLevel: 18 }) ) }关键参数说明tileMatrixSetw使用 Web Mercator 投影{TileMatrix}动态替换为当前缩放级别maximumLevel: 18限制最大缩放级别避免无效请求5. 完整实现与性能优化将各部分组合起来最终的组件使用示例script setup langts import CesiumViewer from ./components/CesiumViewer.vue const tiandituKey 你的天地图TK /script template CesiumViewer :tiandituKeytiandituKey / /template性能优化建议图层加载策略优先加载矢量底图体积小按需加载注记图层使用show属性控制图层显隐内存管理onUnmounted(() { viewer?.scene?.primitives.removeAll() viewer?.imageryLayers.removeAll() viewer?.destroy() })错误处理viewer.scene.imageryLayers.layerAdded.addEventListener(layer { layer.imageryProvider.errorEvent.addEventListener(err { console.error(图层加载错误:, err) }) })6. 常见问题解决方案问题1地图显示空白控制台报 CORS 错误解决方案确保 TK 已正确配置检查浏览器控制台是否有权限错误尝试更换t0.tianditu.gov.cn为t1-t6的其他服务器问题2缩放时地图闪烁或加载不全解决方案viewer.scene.globe.maximumScreenSpaceError 1.5 viewer.scene.preloadAnimatedImagery false问题3TypeScript 类型报错解决方案确保安装了types/cesium在tsconfig.json中添加{ compilerOptions: { types: [cesium] } }7. 高级应用自定义图层与交互实现点击地图获取坐标信息const handler new ScreenSpaceEventHandler(viewer.scene.canvas) handler.setInputAction((movement: any) { const cartesian viewer.camera.pickEllipsoid( movement.position, viewer.scene.globe.ellipsoid ) if (cartesian) { const cartographic Cartographic.fromCartesian(cartesian) const longitude Math.toDegrees(cartographic.longitude) const latitude Math.toDegrees(cartographic.latitude) console.log(经度: ${longitude.toFixed(6)}, 纬度: ${latitude.toFixed(6)}) } }, ScreenSpaceEventType.LEFT_CLICK)添加自定义 WMS 服务viewer.imageryLayers.addImageryProvider( new WebMapServiceImageryProvider({ url: https://demo.mapserver.org/cgi-bin/wms, layers: cities, parameters: { transparent: true, format: image/png } }) )8. 项目结构与最佳实践推荐的项目结构/src /components CesiumViewer.vue # 主地图组件 MapControls.vue # 地图控制组件 LayerManager.vue # 图层管理组件 /composables useCesium.ts # Cesium 相关逻辑 useTianditu.ts # 天地图相关逻辑 /utils cesiumHelper.ts # 工具函数 App.vue main.ts代码分割建议将 Cesium 初始化逻辑放入composables/useCesium.ts天地图服务相关代码放入composables/useTianditu.tsUI 控制相关逻辑放入对应组件// useCesium.ts 示例 export default function useCesium(container: RefHTMLDivElement) { const viewer shallowRefViewer | null(null) onMounted(() { viewer.value new Viewer(container.value, { /* 配置 */ }) }) onUnmounted(() { viewer.value?.destroy() }) return { viewer } }

更多文章