2026/1/20 9:43:29
网站建设
项目流程
网站设计网站建设网站制作,免费人脉推广官方软件,wordpress 默认文本编辑器,自动优化网站建设电话在 WebGIS 领域#xff0c;二维地图已无法满足复杂的空间分析需求 —— 三维地球#xff08;3D Globe#xff09;能直观展示地理要素的空间位置、高度关系和地形特征。Cesium.js 是目前最主流的开源三维地球开发框架#xff0c;支持高精度地形、影像和矢量要素渲染#xf…在 WebGIS 领域二维地图已无法满足复杂的空间分析需求 —— 三维地球3D Globe能直观展示地理要素的空间位置、高度关系和地形特征。Cesium.js 是目前最主流的开源三维地球开发框架支持高精度地形、影像和矢量要素渲染而 Turf.js 则专注于空间分析算法无需后端依赖即可完成缓冲区、距离计算、空间关系判断等核心操作。本文将通过三维缓冲区分析实战案例带你掌握 Turf.js 与 Cesium.js 的结合使用方法实现 “二维空间分析 三维可视化” 的完整流程覆盖从环境搭建到三维要素渲染的全链路。一、技术栈说明框架Vue3Composition API script setup三维可视化Cesium.jsv1.118核心能力三维地球渲染、地理实体管理、相机控制空间分析Turf.jsturf/turf v7核心 APIpoint、bufferUI 组件库Element Plus滑块、按钮、卡片样式Less模块化样式管理核心功能三维地球初始化、中心点标记、动态缓冲区生成Turf.js 计算、缓冲区三维渲染、相机定位到目标区域二、环境搭建关键步骤Cesium.js 的环境配置与常规前端库不同需注意资源加载和 Token 配置1. 安装依赖# 1. 初始化Vue3项目如需新建 npm create vitelatest cesium-turf-demo -- --template vue cd cesium-turf-demo npm install # 2. 安装核心依赖 npm install turf/turf element-plus element-plus/icons-vue cesium --save npm install less less-loader --save-dev # 3. 配置CesiumVite专属解决资源加载问题 npm install vite-plugin-cesium --save-dev2. Vite 配置vite.config.jsCesium 依赖大量静态资源如瓦片、CSS、WebAssembly需通过插件配置import { defineConfig } from vite import vue from vitejs/plugin-vue import cesium from vite-plugin-cesium // 引入Cesium插件 export default defineConfig({ plugins: [vue(), cesium()], // 注册插件 server: { open: true, // 启动时自动打开浏览器 port: 3000 } })3. Cesium Token 配置Cesium Ion影像 / 地形服务需要 Token可前往Cesium 官网免费申请本文提供测试 Token仅供演示。三、核心功能实现三维缓冲区分析组件1. 组件完整代码可直接复用template div classthree-d-geo-fence div classheader h2TurfjsCesium.js三维地球中的空间分析实战/h2 /div div classcontainer !-- 左侧控制面板 -- div classcontrol-panel el-card classbox-card template #header div classcard-header span参数设置/span /div /template !-- 缓冲区半径滑块 -- div classform-item span classlabel缓冲区半径 (km): {{ bufferRadius }}/span el-slider v-modelbufferRadius :min1 :max500 changeupdateBuffer stylemargin-top: 8px / /div !-- 定位按钮 -- div classform-item el-button typeprimary clickflyToLocation 定位到目标/el-button /div !-- 信息展示 -- div classinfo p 中心点坐标: [{{ centerPoint[0] }}, {{ centerPoint[1] }}] /p p分析结果: 已生成 {{ bufferRadius }}km 缓冲区/p /div /el-card /div !-- Cesium三维地球容器 -- div idcesiumContainer classcesium-container/div /div /div /template script setup import { onMounted, ref, onBeforeUnmount } from vue; import * as Cesium from cesium; import cesium/Build/Cesium/Widgets/widgets.css; // 引入Cesium样式 import * as turf from turf/turf; // --- 1. Cesium配置 --- // Cesium Ion Token测试用生产环境请替换为自己的Token Cesium.Ion.defaultAccessToken eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJjODAxMzY4Ny0wZDQ4LTQzZTAtYTFjOC04NTczZmU1MGYxNGEiLCJpZCI6MTI2MjgzLCJpYXQiOjE3NjY3MzAyMjN9.7VIKK31vj39k3Mbp4MxSxNAzOE3ggDo-n4zJPatzkkE; // --- 2. 状态管理 --- const viewer ref(null); // Cesium Viewer实例 const bufferRadius ref(50); // 缓冲区半径默认50km const centerPoint ref([116.3974, 39.9093]); // 中心点坐标北京天安门 let bufferEntity null; // 缓冲区实体 let centerEntity null; // 中心点实体 // --- 3. 生命周期钩子 --- // 组件挂载时初始化Cesium onMounted(() { initCesium(); }); // 组件卸载时销毁Cesium实例防止内存泄漏 onBeforeUnmount(() { if (viewer.value) { viewer.value.destroy(); // 销毁Viewer实例 viewer.value null; } }); // --- 4. 核心方法初始化Cesium三维地球 --- const initCesium () { // 创建Cesium Viewer实例 viewer.value new Cesium.Viewer(cesiumContainer, { terrainProvider: new Cesium.EllipsoidTerrainProvider(), // 禁用地形简化演示 // 隐藏不必要的控件简化界面 animation: false, // 动画控件 timeline: false, // 时间轴 geocoder: false, // 地理编码搜索框 homeButton: false, // 主页按钮 sceneModePicker: false, // 2D/3D切换按钮 baseLayerPicker: false, // 图层选择器 navigationHelpButton: false, // 帮助按钮 infoBox: false, // 信息弹窗 selectionIndicator: false, // 选择指示器 shouldAnimate: false, // 禁用地球自转/动画 }); // 强制关闭时钟动画防止地球自转 viewer.value.clock.shouldAnimate false; // 隐藏版权信息演示用生产环境建议保留 viewer.value._cesiumWidget._creditContainer.style.display none; // 添加中心点标记 addCenterPoint(); // 初始化缓冲区 updateBuffer(); // 相机定位到目标区域 flyToLocation(); }; // --- 5. 核心方法添加中心点标记 --- const addCenterPoint () { // 移除旧的中心点实体防止重复 if (centerEntity) { viewer.value.entities.remove(centerEntity); } // 创建中心点实体 centerEntity viewer.value.entities.add({ position: Cesium.Cartesian3.fromDegrees( centerPoint.value[0], // 经度 centerPoint.value[1] // 纬度 ), // 点样式配置 point: { pixelSize: 10, // 像素大小 color: Cesium.Color.RED, // 填充色 outlineColor: Cesium.Color.WHITE, // 轮廓色 outlineWidth: 2, // 轮廓宽度 }, // 标签配置 label: { text: 中心点, // 标签文字 font: 14pt sans-serif, // 字体 style: Cesium.LabelStyle.FILL_AND_OUTLINE, // 填充轮廓 outlineWidth: 2, // 轮廓宽度 verticalOrigin: Cesium.VerticalOrigin.BOTTOM, // 垂直对齐底部 pixelOffset: new Cesium.Cartesian2(0, -9), // 像素偏移避免遮挡点 }, }); }; // --- 6. 核心方法生成并渲染缓冲区Turf.js Cesium --- const updateBuffer () { // 步骤1使用Turf.js生成二维缓冲区核心空间分析逻辑 const point turf.point(centerPoint.value); // 创建Turf点要素 const buffered turf.buffer( point, // 中心点 bufferRadius.value, // 半径 { units: kilometers } // 单位公里 ); // 步骤2移除旧的缓冲区实体防止重复渲染 if (bufferEntity) { viewer.value.entities.remove(bufferEntity); } // 步骤3解析Turf生成的GeoJSON坐标转换为Cesium格式 // Turf.buffer返回Polygoncoordinates[0]为外环坐标 const coordinates buffered.geometry.coordinates[0]; // 扁平化坐标数组[lon1, lat1, lon2, lat2, ...]Cesium要求格式 const cesiumPositions coordinates.flat(); // 步骤4在Cesium中创建缓冲区多边形实体 bufferEntity viewer.value.entities.add({ polygon: { // 多边形轮廓从经纬度数组创建 hierarchy: new Cesium.PolygonHierarchy( Cesium.Cartesian3.fromDegreesArray(cesiumPositions) ), // 填充样式 material: Cesium.Color.RED.withAlpha(0.3), // 红色半透明 outline: true, // 显示轮廓 outlineColor: Cesium.Color.RED, // 轮廓色 height: 0, // 高度0表示贴地 }, }); }; // --- 7. 核心方法相机定位到目标区域 --- const flyToLocation () { // 根据缓冲区半径计算相机距离保证能看到完整缓冲区 const range bufferRadius.value * 1000 * 4; // 半径(米) * 4倍 // 相机飞行到目标位置 viewer.value .flyTo(centerEntity, { duration: 2.0, // 飞行时长秒 offset: new Cesium.HeadingPitchRange( Cesium.Math.toRadians(0.0), // 航向0表示正北 Cesium.Math.toRadians(-90.0), // 俯仰角-90表示垂直向下 range // 相机到目标的距离米 ), }) .then((result) { if (result) { console.log(相机定位完成); } }); }; /script style scoped langless .three-d-geo-fence { height: 100vh; // 占满视口高度 display: flex; flex-direction: column; overflow: hidden; .header { padding: 10px 20px; background-color: #f5f7fa; border-bottom: 1px solid #e4e7ed; h2 { margin: 0; font-size: 18px; color: #303133; font-weight: 600; } } .container { flex: 1; position: relative; overflow: hidden; .control-panel { position: absolute; top: 20px; left: 20px; z-index: 100; // 确保在三维地球上方 width: 300px; .box-card { background: rgba(255, 255, 255, 0.9); // 半透明白色背景 border: 1px solid #e4e7ed; } .card-header { font-weight: 600; color: #303133; } .form-item { margin-bottom: 15px; } .label { display: block; margin-bottom: 5px; font-weight: 600; color: #606266; font-size: 14px; } .info { margin-top: 20px; padding-top: 10px; border-top: 1px dashed #e4e7ed; color: #606266; font-size: 14px; line-height: 1.6; } } .cesium-container { position: absolute; inset: 0; // 等同于top/right/bottom/left: 0 width: 100%; height: 100%; } } } /style2. 核心代码深度解析1Turf.js 与 Cesium 的核心衔接逻辑// 1. Turf.js生成二维缓冲区地理坐标系 const point turf.point(centerPoint.value); // [lng, lat] const buffered turf.buffer(point, bufferRadius.value, { units: kilometers }); // 2. 坐标格式转换Turf GeoJSON → Cesium Cartesian3 const coordinates buffered.geometry.coordinates[0]; // Polygon外环坐标 const cesiumPositions coordinates.flat(); // 扁平化数组 [lon1, lat1, lon2, lat2...] const hierarchy new Cesium.PolygonHierarchy( Cesium.Cartesian3.fromDegreesArray(cesiumPositions) // 经纬度转笛卡尔坐标 ); // 3. Cesium渲染三维多边形 bufferEntity viewer.value.entities.add({ polygon: { hierarchy: hierarchy, material: Cesium.Color.RED.withAlpha(0.3), outline: true } });Turf.js 职责专注于空间分析算法缓冲区计算输出标准 GeoJSONCesium 职责将 GeoJSON 坐标转换为三维笛卡尔坐标渲染为可视化实体核心转换Cesium.Cartesian3.fromDegreesArray()是经纬度地理坐标系转笛卡尔坐标三维空间坐标系的关键 API。2Cesium 实体管理核心Cesium 通过Entity实体管理地理要素核心规则唯一标识每个实体创建后需保存引用便于后续移除 / 更新避免重复更新缓冲区时先移除旧实体再创建新实体样式配置point配置点要素的大小、颜色、轮廓label配置文字标签的位置、字体、对齐方式polygon配置多边形的填充色、轮廓、高度height: 0表示贴地。3相机控制核心flyTo是 Cesium 相机控制的核心 API参数说明viewer.value.flyTo(centerEntity, { duration: 2.0, // 飞行时长秒 offset: new Cesium.HeadingPitchRange( 0, // 航向0正北顺时针为正 Cesium.Math.toRadians(-90), // 俯仰角-90垂直向下看 range // 相机到目标的距离米 ) });距离计算range 半径(km) * 1000 * 4保证相机距离足够远能完整显示缓冲区俯仰角-90°表示垂直向下2D 视角0°表示水平3D 视角可根据需求调整。4性能优化要点销毁实例组件卸载时调用viewer.destroy()释放内存防止内存泄漏禁用动画关闭shouldAnimate和时钟动画避免不必要的性能消耗简化地形使用EllipsoidTerrainProvider椭球体地形替代默认地形减少渲染压力隐藏控件移除不必要的 UI 控件降低 DOM 渲染开销。四、功能效果演示1. 基础效果启动项目后页面显示三维地球自动定位到北京天安门区域地球中心显示红色中心点标记标注 “中心点”中心点周围显示 50km 半径的红色半透明缓冲区多边形左侧控制面板可调整缓冲区半径1~500km调整后缓冲区实时更新点击 “定位到目标” 按钮相机会重新飞行到目标区域适配新的缓冲区大小。2. 交互效果操作效果拖动滑块调整半径缓冲区大小实时变化信息区显示当前半径点击 “定位到目标”相机平滑飞行到中心点上方完整显示缓冲区鼠标操作地球可旋转、缩放、平移三维地球查看缓冲区的三维效果3. 关键参数示例半径 50km缓冲区覆盖北京市主城区半径 100km缓冲区覆盖北京市 部分周边城市天津、廊坊半径 500km缓冲区覆盖华北大部分区域北京、天津、河北、山东、山西等。五、代码仓库地址完整代码已上传至 Gitee可直接克隆运行https://gitee.com/tang-yunyan-syp/turfjs-vue3-demo.git六、专栏地址本文已同步至 CSDN 专栏可查看更多 Turf.js 实战内容https://blog.csdn.net/m0_72065108/article/details/155226062?spm1001.2014.3001.5501七、实战拓展方向更多空间分析功能距离计算计算两个点在三维地球中的实际距离空间关系判断判断点是否在缓冲区内Turf.jsbooleanPointInPolygon要素裁剪结合 Turf.js 的bboxClip裁剪三维多边形多要素分析加载多个点批量生成缓冲区并渲染。三维效果增强地形贴合启用 Cesium 地形服务让缓冲区贴合真实地形高度设置给缓冲区设置高度如height: 1000实现三维围栏样式自定义支持缓冲区颜色、透明度、轮廓宽度的动态调整动态效果添加缓冲区的显隐动画、颜色渐变效果。交互能力扩展点选功能点击地球任意位置将中心点移动到点击位置导入导出支持导入 GeoJSON 点要素导出缓冲区 GeoJSON多区域对比同时显示多个中心点的缓冲区支持切换 / 隐藏测量工具添加距离 / 面积测量工具验证缓冲区大小。性能优化批量渲染使用Primitive替代Entity优化大量要素的渲染性能层级加载根据相机距离动态调整缓冲区的精度远小近大异步加载空间分析逻辑放入 Web Worker避免阻塞主线程。八、常见问题排查Cesium 初始化失败原因未配置vite-plugin-cesium或 Token 无效解决方案检查vite.config.js是否注册 Cesium 插件替换为有效 Token。缓冲区不显示原因坐标格式错误Turf 为[lng, lat]Cesium 同理解决方案确保坐标顺序为 “经度在前纬度在后”检查coordinates.flat()是否正确扁平化数组。地球自转 / 抖动原因未禁用shouldAnimate或时钟动画解决方案设置viewer.value.clock.shouldAnimate false并禁用地形动画。相机定位不准确原因range值过小或俯仰角设置不当解决方案增大range倍数如改为 5 倍调整俯仰角为-90°垂直向下。组件卸载后内存泄漏原因未调用viewer.destroy()解决方案在onBeforeUnmount钩子中销毁 Cesium 实例清空实体引用。总结本文通过 Turf.js Cesium.js 的结合实现了 “二维空间分析 三维可视化” 的核心能力掌握了 Cesium.js 的基础配置、实体管理、相机控制等核心技能实现了 Turf.js 空间分析结果缓冲区到 Cesium 三维实体的转换完成了可交互的三维缓冲区分析组件支持参数调整、实时更新、相机定位梳理了两者结合的核心逻辑和性能优化要点为复杂三维空间分析打下基础。