尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
Cesium@1.138中实现交互式折线绘制与编辑工具类
/** * Cesium 交互式折线绘制与编辑工具类 */ class PolylineDrawer { /** * param {Object} Cesium - Cesium 命名空间对象 * param {Cesium.Viewer} viewer - Cesium Viewer 实例 * param {Object} options - 可选配置项 * param {Function} options.onFinish - 绘制完成时的回调函数 * param {Function} options.onEdit - 编辑完成拖拽结束时的回调函数接收最新坐标数组 * param {Cesium.Color} options.lineColor - 折线颜色 * param {Cesium.Color} options.pointColor - 顶点颜色 */ constructor(Cesium, viewer, options {}) { this.Cesium Cesium; this.viewer viewer; this.onFinish options.onFinish || (() {}); this.onEdit options.onEdit || (() {}); this.lineColor options.lineColor || this.Cesium.Color.YELLOW.withAlpha(0.8); this.pointColor options.pointColor || this.Cesium.Color.RED; // 内部状态 this.positions []; this.floatingPoint null; this.pointEntities []; this.polylineEntity null; this.handler null; this.isDrawing false; this.isEditing false; // 拖拽状态变量 this.draggedPointIndex null; this.editHandler null; } /** * 开始绘制 */ start() { if (this.isDrawing) return; // 重置状态 this.positions []; this.pointEntities []; this.floatingPoint null; this.isDrawing true; this.isEditing false; // 禁用 Cesium 默认的双击聚焦行为 this.viewer.cesiumWidget.screenSpaceEventHandler.removeInputAction( this.Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK ); // 创建动态折线 Entity this.polylineEntity this.viewer.entities.add({ polyline: { positions: new this.Cesium.CallbackProperty(() { if (this.positions.length 0) return []; return this.floatingPoint ? this.positions.concat([this.floatingPoint]) : this.positions; }, false), width: 2, material: this.lineColor, clampToGround: true, }, }); // 绑定绘制事件 this.handler new this.Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas); this._bindDrawEvents(); } /** * 绑定绘制阶段的交互事件 * private */ _bindDrawEvents() { // 左键点击添加顶点 this.handler.setInputAction((click) { const cartesian this.viewer.scene.pickPosition(click.position); if (!cartesian) return; this.positions.push(cartesian); const point this.viewer.entities.add({ position: cartesian, point: { pixelSize: 6, color: this.pointColor, outlineColor: this.Cesium.Color.WHITE, outlineWidth: 2, disableDepthTestDistance: Number.POSITIVE_INFINITY, }, }); this.pointEntities.push(point); }, this.Cesium.ScreenSpaceEventType.LEFT_CLICK); // 鼠标移动更新预览点 this.handler.setInputAction((movement) { if (this.positions.length 0) return; const p this.viewer.scene.pickPosition(movement.endPosition); if (p) this.floatingPoint p; }, this.Cesium.ScreenSpaceEventType.MOUSE_MOVE); // 结束绘制逻辑双击左键 / 单击右键 const finish () this.finish(); this.handler.setInputAction(finish, this.Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK); this.handler.setInputAction(finish, this.Cesium.ScreenSpaceEventType.RIGHT_CLICK); } /** * 结束绘制并自动进入编辑模式 */ finish() { if (!this.isDrawing) return; this.floatingPoint null; this.isDrawing false; // 销毁绘制事件监听 if (this.handler) { this.handler.destroy(); this.handler null; } console.log(✅ 绘制完成最终坐标点数量:, this.positions.length); this.onFinish(this.positions); // 绘制完成后自动进入编辑模式 this._startEditing(); } /** * 开启拖拽编辑模式 * private */ _startEditing() { if (this.isEditing || this.pointEntities.length 0) return; this.isEditing true; this.editHandler new this.Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas); // 1. 鼠标按下判断是否点中了顶点并【禁用相机交互】 this.editHandler.setInputAction((click) { const picked this.viewer.scene.pick(click.position); if (this.Cesium.defined(picked) picked.id) { const index this.pointEntities.indexOf(picked.id); if (index ! -1) { this.draggedPointIndex index; this.viewer.scene.canvas.style.cursor move; // 核心修复拖拽开始时禁用默认的屏幕空间相机控制器 this.viewer.scene.screenSpaceCameraController.enableInputs false; } } }, this.Cesium.ScreenSpaceEventType.LEFT_DOWN); // 2. 鼠标移动如果正在拖拽则实时更新顶点坐标 this.editHandler.setInputAction((movement) { if (this.draggedPointIndex null) return; // 使用 globe.pick 获取地球表面的三维坐标配合 clampToGround 效果更好 const ray this.viewer.camera.getPickRay(movement.endPosition); const cartesian this.viewer.scene.globe.pick(ray, this.viewer.scene); if (cartesian) { // 更新内存中的坐标数组 this.positions[this.draggedPointIndex] cartesian; // 核心优化使用 CallbackProperty 动态更新位置避免拖拽时的视觉卡顿 this.pointEntities[this.draggedPointIndex].position new this.Cesium.CallbackProperty( () cartesian, false ); } }, this.Cesium.ScreenSpaceEventType.MOUSE_MOVE); // 3. 鼠标抬起结束拖拽【恢复相机交互】触发编辑回调 this.editHandler.setInputAction(() { if (this.draggedPointIndex ! null) { this.draggedPointIndex null; this.viewer.scene.canvas.style.cursor ; // 核心修复拖拽结束时恢复默认的屏幕空间相机控制器 this.viewer.scene.screenSpaceCameraController.enableInputs true; console.log(✏️ 顶点编辑完成最新坐标:, this.positions); this.onEdit(this.positions); } }, this.Cesium.ScreenSpaceEventType.LEFT_UP); } /** * 清除当前绘制的所有实体 */ clear() { this.pointEntities.forEach((e) this.viewer.entities.remove(e)); this.pointEntities []; this.positions []; this.floatingPoint null; } /** * 完全销毁工具实例 */ destroy() { // 退出编辑模式 this.isEditing false; if (this.editHandler) { this.editHandler.destroy(); this.editHandler null; } this.viewer.scene.canvas.style.cursor ; // 确保相机控制器被恢复 this.viewer.scene.screenSpaceCameraController.enableInputs true; // 退出绘制模式 if (this.handler) { this.handler.destroy(); this.handler null; } this.clear(); if (this.polylineEntity) { this.viewer.entities.remove(this.polylineEntity); this.polylineEntity null; } } } export default PolylineDrawer;使用const d new PolylineDrawer(Cesium, viewer); d.start();
RELATED

相关推荐

TDI线阵相机 vs 标准线阵相机:5大维度对比与弱光高速场景选型

TDI线阵相机 vs 标准线阵相机:5大维度对比与弱光高速场景选型

TDI线阵相机 vs 标准线阵相机:5大维度对比与弱光高速场景选型在工业检测领域,当面临弱光环境或高速运动物体的成像需求时,传统线阵相机往往难以满足要求。此时,TDI(时间延迟积分)线阵相机凭借其独特的多级信…

📅 2026/10/18 10:37:38
AI辅助Sprint Planning数据驱动实战:从拍脑袋到可预测交付

AI辅助Sprint Planning数据驱动实战:从拍脑袋到可预测交付

AI辅助Sprint Planning数据驱动实战:从拍脑袋到可预测交付 一、Sprint Planning为什么总是失控? Sprint Planning的本质是对不确定性的管理。产品经理拿出一堆需求,工程师估算时间,然后Sprint执行到一半,所有人发现估少…

📅 2026/10/6 12:40:12
穿透式监管怎么做?三层数据穿透方法讲清楚

穿透式监管怎么做?三层数据穿透方法讲清楚

最近几年,很多集团企业都在推进穿透式监管。监管平台建了,数据中台建了,经营驾驶舱也建了。但真正出了风险事件,很多管理者还是会遇到同一个问题:报表很多,指标更多。可问题到底出在哪?很难第一…

📅 2026/10/7 7:10:47
MORE NEWS

更多资讯

📰

漯河 电工证怎么考

漯河电工证怎么考值不值得考 证书过期了不知道怎么复审延期,别慌,今天咱们就来聊聊漯河电工证怎么考、值不值得考,还教你怎么搞定复审问题,别再踩坑。 ### 电工证过期了怎么办?复审流程全知道 电工证过期了很多人不知道该怎么办,实际上,…

📰

城建电工证报名点丢了怎么补办 良心建议帮你理清楚

城建电工证报名点丢了怎么补办 良心建议帮你理清楚 之前考的证在外省能不能转过来?这个问题困扰了不少人,特别是像你在驻马店从事水利工程的电工,很多时候需要跨区域工作,证件的转接问题就成了“卡脖子”的难题。其实,很多人并不清楚,城建电工证不仅可…

📰

川沙镇电工证培训怎么准备考前押题

川沙镇电工证培训怎么准备考前押题 实操考试心里没底怕挂科?川沙镇电工证培训的考生大多都经历过这个阶段。尤其是像低压电工、高压电工这类实操性强的工种,很多学员担心操作不规范、步骤不清晰,影响考试成绩。而考前押题恰恰是提高通过率的重要方式,下面…

📰

深圳中级电工证考题怎么考?学历不高也能全国通用?

深圳中级电工证考题怎么考?学历不高也能全国通用? 你是不是也担心自己学历不高,考不了深圳中级电工证?别急,下面这些真实经验告诉你,只要准备到位, 全国通用 的中级电工证照样能拿到手,还能让你在电工行业里吃得开。…

📰

济南低压电工证在哪考2026河南最新政策下怎么准备不白交钱

济南低压电工证在哪考2026河南最新政策下怎么准备不白交钱 怕考不过白交培训费?2026河南最新政策下,济南低压电工证在哪考成了很多学员最关心的问题。别再被培训机构忽悠,也别再为考试发愁。这篇文章从漯河培训机构学员的真实经历出发,帮你理清考…

📰

常高技报考电工证怎么转异地?郑州报考避坑指南

常高技报考电工证怎么转异地?郑州报考避坑指南 学历不高怕报不上名?常高技报考电工证的小伙伴,别慌!很多人担心自己学历不够,报不了名,其实只要材料准备齐全、流程走对,学历低也能顺利报考。尤其是在郑州,很多小伙伴都在这里踩过坑,比如材料不全、培…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬