Vue3+Cesium动态交互绘制圆形工具:原理、代码与工程实践
在三维 GIS 项目里最常遇到的一类需求不是“展示一个圆”而是“让用户在地图上自己画一个圆”用来圈定选址地块、信号覆盖范围、缓冲区分析区域甚至是做简单的态势标绘。市面上关于 Cesium 绘制圆的资料很多但多数只停留在“调用 entity.ellipse 显示一个静态圆”的层面。真正到交互绘制、动态半径刷新、样式控制、清理与复用这些环节时资料往往很零散。本文基于 Vue3 Cesium 完整梳理一套 Circle 绘图工具实现方案。你可以把它直接集成到业务项目中也可以理解其原理后迁移到 Rectangle、Polygon、箭头线等其他绘图工具。文章会从底层概念讲起先解释 Cesium 里“圆”的本质再介绍静态圆如何绘制然后实现完整的鼠标在场景上拉圆动态交互。代码覆盖事件监听、回调属性、相机控制、结果清理等关键部分并附带常见问题和工程建议。建议读者先跟着代码跑通一个最小 Demo再结合自己的业务字段去扩展。1. 背景与核心概念1.1 Cesium 中“圆”的本质Ellipse 的特例很多初学者会去搜索“Cesium Circle”但真正到了 API 层面会发现Cesium Entity 中没有一个专门的circle属性。平时说的圆在 Cesium 内部是用ellipse表示椭圆来实现的只要让椭圆的长半轴semiMajorAxis和短半轴semiMinorAxis相等呈现出来的就是一个标准的圆。圆心的位置由 Entity 的position决定这个位置是一个Cartesian3类型对应 WGS84 坐标系下的一个三维坐标点。而半轴semiMajorAxis和semiMinorAxis的单位都是米不是像素也不是经纬度差值。这意味着当你在北京画一个半径 500 米的圆在东京画同样半径的圆虽然视觉上经纬度跨度可能略有差异但实际物理半径是等长的都代表 500 米。理解这一步很关键因为所有动态绘制圆的代码本质上都是在“动态修改半轴值”。当用户按下鼠标确定圆心后鼠标在地图上拖出多远那段距离就会换算成半径再同时赋给semiMajorAxis和semiMinorAxisCesium 就会自动重绘新的圆形。1.2 动态交互绘制的三个核心部件如果要实现“按下鼠标起点、拖拽出半径、松开鼠标完成画圆”这样的绘图工具需要掌握三个核心部件第一个是ScreenSpaceEventHandler它负责监听用户在屏幕上的鼠标操作。由于我们是在三维球上绘图不能直接拿DOM的click事件来算坐标而是要把浏览器屏幕坐标交给 Cesium 换算成球面坐标所以使用handler.setInputAction来注册左键点击、鼠标移动、右键点击等事件。第二个是绘图状态机。动态绘制工具不能只是“每次点击就画一个圆”否则用户拖拽鼠标的过程中圆形不会跟随变化。项目中通常定义一个状态字段来记录当前是否处于绘制中例如_isDrawing。第一次左键进入“绘制中”鼠标移动时实时更新半径第二次左键完成绘制右键取消当前绘制。这套状态机几乎适用于所有矢量绘图形状。第三个是CallbackProperty。它允许 Entity 的某个属性在每帧渲染时动态变化。我们不需要在鼠标移动时反复删除旧圆再创建新圆而是把ellipse.semiMajorAxis与ellipse.semiMinorAxis定义为CallbackProperty每次回调返回当前半径变量。这样既保证了实时刷新效果又避免了频繁操作 Entity 列表带来的性能和事件泄漏隐患。1.3 常见应用场景Circle 绘图工具在三维 GIS 项目中有大量落地场景。最常见的包括信号覆盖分析让技术人员在电子地图上画出基站覆盖范围地块圈选业务人员通过画圆将某个区域临时标记出来再进入下一步审批流程风险影响范围评估例如通过一个圆框选地质灾害影响半径以及态势标绘在军事或应急场景中用圆表示集结区域、观察范围或管制作业半径。了解真实业务场景后再去看绘图工具设计就不会认为 Circle 只是简简单单的几何体。它会牵扯到工具开关、绘制模式、结果数据、撤销重绘和样式风格等多个环节。这也是为什么很多人觉得“画个圆很简单”但真正做业务功能时仍然要花不少时间的原因。2. 环境准备与版本说明2.1 创建 Vue3 Vite 项目并安装 Cesium为了便于展示工程化用法本文示例采用 Vue3 Vite 作为前端工程基础。如果你的项目是原生 HTML、React 或者其他框架核心代码也可以直接复用只需要把CircleDrawTool类所在的模块引入方式改成对应框架的写法即可。先创建一个 Vite 项目npm create vitelatest cesium-circle-demo -- --template vue进入项目目录并安装依赖cd cesium-circle-demo npm install npm install cesiumCesium 作为一个大型三维引擎在构建工具中的资源处理方式会随着版本变化而不同。如果项目运行后在控制台看到 Cesium 的Workers、Assets、Widgets等静态资源加载 404 报错通常需要配置CESIUM_BASE_URL或者把node_modules/cesium/Build/Cesium下的相关资源目录复制到public/cesium下。不过这一问题属于工程接入范畴不影响本文后面绘图逻辑的理解建议以你当前使用的 Cesium 版本官方文档为准。为了代码能正常创建三维场景还需要准备一个 Cesium ion token。可以去 Cesium ion 官网注册后创建一个 token然后在代码中设置import * as Cesium from cesium; Cesium.Ion.defaultAccessToken 替换成你自己的token;如果没有配置 tokenViewer 默认加载的在线底图可能会失败。你可以换成自己项目中的离线瓦片服务也可以先确保能访问 Cesium ion 再继续后续示例。2.2 初始化 Viewer在一个 Vue 组件中初始化 Viewer 的代码通常放在onMounted生命周期中。因为此刻 DOM 容器已经渲染完成才能把 Cesium 场景挂载到对应的div上。先准备一个占满全屏的容器template div refcesiumContainer classcesium-container/div /template style scoped .cesium-container { width: 100%; height: 100vh; margin: 0; padding: 0; } /style然后在组件脚本中初始化import { ref, onMounted } from vue; import * as Cesium from cesium; const cesiumContainer ref(null); let viewer null; onMounted(() { if (!cesiumContainer.value) return; viewer new Cesium.Viewer(cesiumContainer.value, { animation: false, timeline: false, baseLayerPicker: false, geocoder: false, homeButton: false, sceneModePicker: false, navigationHelpButton: false, fullscreenButton: false, }); // 将视角定位到北京 viewer.camera.setView({ destination: Cesium.Cartesian3.fromDegrees(116.391, 39.907, 15000), }); });这里关闭了大部分默认控件是为了让界面更聚焦于绘图工具。如果你希望保留右上角的工具按钮把对应选项设为true或不传即可。2.3 规划代码结构绘图功能如果全部写进组件里代码会很臃肿也不便于其他页面复用。本文采用独立工具类的设计思路最终项目结构如下src/ ├── components/ │ └── CircleMap.vue ├── utils/ │ └── drawCircleTool.js └── main.jsdrawCircleTool.js
上一篇/下一篇内容由系统自动关联
返回资讯列表 →