ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Cesium圆绘制工具:从Ellipse原理到动态交互实现

Cesium圆绘制工具:从Ellipse原理到动态交互实现 在 Cesium 项目里“圆”可能是我见过开发频率最高的图元之一。很多业务场景都会先画一个半径范围雷达扫描范围、风电场影响圈、安全警戒区、通勤圈、地块覆盖范围等。最初我习惯把圆心和半径写成常量直接塞进一个ellipse但等到需求变成“让业务人员在三维场景里自己动态绘制一个圆”时事情就变得不太一样了鼠标点哪、半径怎么算、预览怎么实时更新、取消和完成如何区分、圆是贴地还是贴模型这些细节如果没处理好后期会一直返工。这篇文章就以Cesium 绘图工具 - Circle为切入点从底层的EllipseGraphics概念讲到一套可直接复用的交互工具实现覆盖圆心拾取、动态半径计算、实时预览、完成回调以及后续如何接 Vue3 项目或把结果转成 GeoJSON。新手可以直接拿来学习有一定经验的开发者也可以把里面的交互状态机抽取出来扩展成矩形、多边形、高德箭头线等其他绘图工具。1. 认识 Cesium 中的 Circle 绘图1.1 Circle 的本质是 EllipseCesium 没有专门的CircleGraphics这样一个类你可能会在中文文档或英文文档里找不到“Circle”这个独立 API。通常我们说的“画圆”在 Cesium Entity API 里实际上是用椭圆图元ellipse实现的只要让椭圆的semiMajorAxis长半轴和semiMinorAxis短半轴相等它在视觉上就是一个标准圆。viewer.entities.add({ position: Cesium.Cartesian3.fromDegrees(116.3913, 39.9075), ellipse: { semiMajorAxis: 5000, // 长半轴单位米 semiMinorAxis: 5000, // 短半轴单位米 material: Cesium.Color.CYAN.withAlpha(0.4), outline: true, outlineColor: Cesium.Color.WHITE, outlineWidth: 2 } });如果你只想画一个空心的圆形“边界线”不需要填充面可以设置fill: false当然也可以保留半透明填充这在业务上通常更清晰。1.2 为什么不能直接传一个“像素半径”或“经纬度半径”很多刚开始接触 Cesium 的同学会把“圆的大小”想象成屏幕上多少像素或者把半径理解成经纬度差值。但 Cesium 的三维场景是建立在椭球体模型上的所以ellipse.semiMajorAxis和semiMinorAxis的单位都是米圆心位置的坐标系是 Cartesian3世界坐标而不是单纯的经纬度。也就是说如果我们想得到一个真实的 5 公里范围圆前提是拿到一个真实的空间距离 5000 米。如果直接从屏幕上两点之间通过百分比换算半径很容易在地图缩放级别不同时得到完全不一致的结果比如在北京和在赤道附近同样拖动 100 像素实际代表的半径可能差好几倍。1.3 Circle 的常见应用场景雷达探测范围展示用一个半透明圆表示雷达最大探测距离。规划禁入区在 GIS 场景中给操作员提供绘制圆形禁飞区、禁入区的能力。影响半径分析加油站服务半径、学校通勤半径、商业选址影响范围等。风电或光伏项目覆盖圈围绕风机的噪音影响范围、生态红线范围。三维可视化教学帮助初学 Cesium 的人理解坐标拾取、椭圆体计算、CallbackProperty 动态更新等核心概念。从架构上讲Circle 是最容易实现的绘图工具非常适合作为编码入门案例。理解它之后再去看 Cesium 中如何实现矩形、多边形、圆柱体、可视域分析、雷达光波甚至自定义线材质很多思路都是同构的。2. 环境准备与基础工程搭建2.1 技术栈版本说明我下面给出的示例基于原生 HTML JavaScript 本地 Cesium 包重点演示绘图工具本身的代码不依赖任何框架。如果你使用的是 Vue3 Vite只需要把绘图工具类单独抽成 JS 文件在生命周期函数里创建Viewer和工具实例即可核心逻辑完全一致。Cesium 本身迭代速度比较快不同小版本的 API 会有细微差异。因此本文不写死某一个固定版本号请以你项目中实际安装的 Cesium 包为准建议使用较新的 1.x 稳定版本。在本地运行时请确保能通过静态资源路径访问到 Cesium 的Cesium.js和widgets.css。2.2 最小可运行页面为了便于完全复现我先搭建一个最基础的index.html。!DOCTYPE html html langzh-CN head meta charsetUTF-8 / titleCesium Circle Draw Tool/title style html, body, #cesiumContainer { width: 100%; height: 100%; margin: 0; overflow: hidden; } .toolbar { position: absolute; top: 20px; left: 20px; z-index: 999; background: rgba(255, 255, 255, 0.9); padding: 10px 16px; border-radius: 6px; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2); } .toolbar button { padding: 6px 14px; cursor: pointer; } /style link relstylesheet href./node_modules/cesium/Build/Cesium/Widgets/widgets.css / !-- 如果你的 Cesium 不是通过 npm 安装请改成实际静态资源路径 -- script window.CESIUM_BASE_URL ./node_modules/cesium/Build/Cesium/; /script script src./node_modules/cesium/Build/Cesium/Cesium.js/script script src./src/drawCircleTool.js/script /head body div idcesiumContainer/div div classtoolbar button iddrawCircleBtn绘制圆形/button button idclearCircleBtn清空/button /div script Cesium.Ion.defaultAccessToken 在这里填入你的 Cesium Ion Token; const viewer new Cesium.Viewer(cesiumContainer, { baseLayerPicker: false
返回列表