(精品)cesium-绘制动态线(解决闪烁)的进击研究教程

本文详细介绍了在Cesium中实现动态线绘制的方法,包括解决动态线闪烁问题和纹理贴图效果,适用于墙体绘制等场景。通过具体代码示例,展示了如何响应鼠标点击和移动事件,实现连续线绘制并保持良好的视觉效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前因后果

最近项目中,需要绘制墙体,测试了cesium提供的诸多entity,发现都死在了贴纹理阶段;最后妥协于使用wall实体进行墙体的绘制.期间解决了纹理贴图效果,高程遮挡,动态绘制线路闪烁等问题,鉴于动态线绘制闪烁比较典型(相当于解决了点,线,面,盒子…等所有实体的动态改变问题及纹理贴图问题),这里记录一下,供大家参考.

效果图先行

1 动态线带闪烁效果
在这里插入图片描述2 连续线绘制带闪烁
在这里插入图片描述3 带纹理的墙
在这里插入图片描述

动态线绘制

思路

鼠标点击时,生成线实体–>鼠标移动式,控制线坐标

代码及效果图
var line = undefined; //全局线对象
        var linearr = []; //线的坐标存储
        //鼠标点击事件监听
        handler.setInputAction(function (event) {
            //获取世界坐标点    
            var pick = viewer.camera.getPickRay(event.position);
            var cartesian = scene.globe.pick(pick, viewer.scene);
            //如果世界坐标点存在
            if (cartesian) {
                
                //添加一个线对象 
                if (!line) {
                    linearr.push(cartesian)
                    line = viewer.entities.add({
                        polyline: {
                            positions:new Cesium.CallbackProperty(function () {         
                              return linearr;
                            }, false),
                            width: 3,
                            material: Cesium.Color.RED,
                            clampToGround: true,
                        }
                    })
                }
            }
        }, Cesium.ScreenSpaceEventType.LEFT_CLICK)
        //鼠标移动事件监听
        handler.setInputAction(function (event) {
          var pick = viewer.camera.getPickRay(event.endPosition);
          var cartesian = scene.globe.pick(pick, viewer.scene);
          if (cartesian) {
            if(line){
              //考虑在鼠标移动的一瞬间,linearr应该增加一个坐标点,当再次移动时,该坐标点应该更换
              linearr[1]=cartesian;               
            }
          }
        },Cesium.ScreenSpaceEventType.MOUSE_MOVE);

在这里插入图片描述

动态线连续绘制

思路

我们已经完成了线跟随鼠标移动时的效果,接下来,我们要进行推论
推论1:点击鼠标时,能够线路绘制
推论2:线路跟随鼠标进行连续创建

代码及效果图

针对上述两种条件推演,贴上如下代码
(1) 首先是推论2
代码;

 var line = undefined; //全局线对象
        var linearr = []; //线的坐标存储
        //鼠标点击事件监听
        handler.setInputAction(function (event) {
            //获取世界坐标点    
            var pick = viewer.camera.getPickRay(event.position);
            var cartesian = scene.globe.pick(pick, viewer.scene);
            //如果世界坐标点存在
            if (cartesian) {
                
                //添加一个线对象 
                if (!line) {
                    linearr.push(cartesian)
                    line = viewer.entities.add({
                        polyline: {
                            positions:new Cesium.CallbackProperty(function () {         
                              return linearr;
                            }, false),
                            width: 3,
                            material: Cesium.Color.RED,
                            clampToGround: true,
                        }
                    })
                }
            }
        }, Cesium.ScreenSpaceEventType.LEFT_CLICK)
        //鼠标移动事件监听
        handler.setInputAction(function (event) {
          var pick = viewer.camera.getPickRay(event.endPosition);
          var cartesian = scene.globe.pick(pick, viewer.scene);
          if (cartesian) {
            if(line){
              //考虑在鼠标移动的一瞬间,linearr应该增加一个坐标点,当再次移动时,该坐标点应该更换
              linearr[linearr.length]=cartesian;               
            }
          }
        },Cesium.ScreenSpaceEventType.MOUSE_MOVE);

在这里插入图片描述(2) 推论1验证
代码:

var line = undefined; //全局线对象
        var linearr = []; //线的坐标存储
        //鼠标点击事件监听
        handler.setInputAction(function (event) {
            //获取世界坐标点    
            var pick = viewer.camera.getPickRay(event.position);
            var cartesian = scene.globe.pick(pick, viewer.scene);
            //如果世界坐标点存在
            if (cartesian) {
                linearr.push(cartesian)
                //添加一个线对象 
                if (!line) {                   
                    line = viewer.entities.add({
                        polyline: {
                            positions:new Cesium.CallbackProperty(function () {         
                              return linearr;
                            }, false),
                            width: 3,
                            material: Cesium.Color.RED,
                            clampToGround: true,
                        }
                    })
                }
            }
        }, Cesium.ScreenSpaceEventType.LEFT_CLICK)
        //鼠标移动事件监听
        handler.setInputAction(function (event) {
          var pick = viewer.camera.getPickRay(event.endPosition);
          var cartesian = scene.globe.pick(pick, viewer.scene);
          if (cartesian) {
            if(line){
              debugger;
              //考虑在鼠标移动的一瞬间,linearr应该增加一个坐标点,当再次移动时,该坐标点应该更换
              linearr[linearr.length-1]=cartesian;      
              console.log(linearr) ;        
            }
          }
        },Cesium.ScreenSpaceEventType.MOUSE_MOVE);

在这里插入图片描述

结论

贴图部分目前cesium做的还是不够好,所以需要我们自己通过业务逻辑去组织

### 实现 Vue-Cesium 实时绘制轨迹线 为了在 `vue-cesium` 中实现实时绘制轨迹线功能,可以参照以下方法: #### 安装依赖库 首先确保已经安装了必要的开发工具和库。对于 Vue3 项目而言,全局安装 `@vue/cli` 是必需的操作[^3]。 ```bash npm install -g @vue/cli ``` 接着创建新的 Vue 项目并选择合适的预设选项来初始化项目结构: ```bash vue create cesium-learning ``` 进入新创建的项目文件夹内继续操作: ```bash cd cesium-learning ``` #### 引入 Cesium 库 由于直接引入整个 Cesium 可能会增加打包体积,在现代前端构建工具的支持下推荐按需加载的方式引入特定模块。不过这里简化处理,通过 CDN 或者 npm 方式快速集成基本版本即可满足需求。 如果采用 NPM 形式的安装,则执行如下命令获取最新稳定版Cesium包及其样式资源: ```bash npm install cesium --save ``` 编辑项目的入口 HTML 文件(通常是 public/index.html),加入 Cesium 提供的地图容器 div 并设置其宽高属性以便显示地图视图;同时也可以在此处添加指向官方托管服务端提供的 CSS 资源链接以应用默认主题风格。 #### 编写组件逻辑 接下来定义一个名为 `RealtimeTrack.vue` 的单文件组件用于承载核心业务代码片段。该组件内部维护着一条由多个时间戳标记的位置点构成的时间序列数据集,并利用这些离散采样点构造出连续变化的空间曲线效果展示给用户查看。 ```html <template> <div id="cesiumContainer"></div> </template> <script setup lang="ts"> import * as Cesium from 'cesium'; import './Widgets/Cesium.css'; // 初始化 Viewer 对象实例化地球仪控件 const viewer = new Cesium.Viewer('cesiumContainer', { terrainProvider: Cesium.createWorldTerrain(), }); let positions = []; let timeStamps = []; function addPosition(longitude, latitude, height) { let cartographic = Cesium.Cartographic.fromDegrees( longitude, latitude, height ); positions.push(Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, cartographic.height)); timeStamps.push(new Date().toISOString()); } setInterval(() => { // 模拟每隔一秒向路径上追加随机坐标位置 const lon = Math.random() * 360 - 180; const lat = Math.random() * 180 - 90; const hgt = Math.random() * 5e3; addPosition(lon, lat, hgt); }, 1000); setTimeout(() => { drawPath(); }, 5000); async function drawPath(){ await sleep(5000); var property = new Cesium.SampledPositionProperty(); for (var i = 0; i < positions.length; ++i){ property.addSample(timeStamps[i],positions[i]); } viewer.entities.add({ name : "Trajectory Line", position : property, path : { resolution : 1, material : new Cesium.PolylineGlowMaterialProperty({ glowPower : 0.2, color : Cesium.Color.RED.withAlpha(0.7) }), width : 4 } }); viewer.zoomTo(viewer.entities); } function sleep(ms:number):Promise<void> { return new Promise(resolve=> setTimeout(resolve,ms)) } </script> <style scoped> #csmContainer { width: 100%; height: calc(100vh - 2rem); border: none; } </style> ``` 上述代码实现了每秒钟往三维空间里新增一个随机分布的数据节点,并最终形成一段动态演化的飞行航迹线条图形对象呈现在界面上让用户直观感受物体移动过程中的时空演变规律特性[^4]。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

李卓书

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值