Cesium上建立风场动态粒子效果 您所在的位置:网站首页 cesium右键事件 Cesium上建立风场动态粒子效果

Cesium上建立风场动态粒子效果

2023-03-11 22:21| 来源: 网络整理| 查看: 265

初学 使用Canvas + NCEP数据创建动态风场效果 封装基于Cesium的canvas渲染风场API

集成npm插件 https://www.npmjs.com/package/cesium-windy-canvas npm i cesium-windy-canvas -S github传送门 gitee传送门 甲、需要准备一个canvas与Cesium初始化后的图层

Cesium初始化后的图层详见:vue3.0+vite+Cesium使用记录

讲解过程

1、先初始化Cesium 2、提供NCEP风场数据 详见 cesium-windy-canvas/mock20万行风场数据,直接复制即可 3、在进行CanvasWindy初始化 CanvasWindy详见 cesium-windy-canvas 4、设置风场必要参数 5、非常简单的创建具有动态粒子效果的风场

CanvasWindy(data, params); 复制代码 乙、设置Cesiumwindy参数params 参数名参数解释类型默认值viewerCesium初始化后赋值变量Objectnullcanvas风场画布DOMnullcanvasContextcanvas上下文DOMparams.canvas.getContext('2d')canvasWidth画布宽度Number300canvasHeight画布高度Number180speedRate风前进速度Number100extent风场绘制地图范围Array[]particlesNumber粒子总数Number20000maxAge每个粒子的最大生存周期Number120frameTime每秒刷新次数Number100lineWidth粒子线条宽度Number1initExtent风场初始范围Array[]calc_speedRate根据speedRate参数计算经纬度步进长度Array[0, 0]windField风场网格Objectnullparticles风场粒子存储Array[]animateFramerequestAnimationFrame事件句柄,用来清除操作Objectnullisdistory是否进行销毁boolfalsewindyColor风场颜色集合(根据风速不同设置不同颜色)classnew WindyColor()****### 丙、初始化风场粒子

在初始化Cesiumwindy构造函数时,需要传入风场数据,以及相应的参数 执行构造函数时自动执行init()进行粒子创造

丁、讲解根据风速设置不同粒子颜色

在初始化粒子中有一个画线的操作,在画线过程中进行颜色赋值 在使用this.particles对所有粒子遍历进行画轨迹操作

创建粒子

/// randomParticle生成随机粒子 /// CanvasParticle() 粒子参数 this.particles.push(this.randomParticle(new CanvasParticle())); 复制代码 CanvasParticle参数解析 参数名参数解释类型默认值lng粒子初始经度度nulllat粒子初始纬度度nulltlng粒子下一步将要移动的经度,这个需要计算得来度nulltlat粒子下一步将要移动的y纬度,这个需要计算得来度nullx粒子初始x位置Numbernully粒子初始y位置Numbernullage粒子生命周期计时器,每次-1Numbernullspeed粒子移动速度Numbernullcolor粒子颜色Stringnull 给粒子赋值颜色

1、在生成随机粒子时根据风速计算不同颜色 this.windyColor.getWindColor(particle.speed) 详细见Cesiumwindy源码第333行 2、画粒子轨迹线时进行画布粒子颜色添加 this.canvasContext.strokeStyle = particle.color this.canvasContext.stroke(); 详见Cesiumwindy源码第244行

戊、至此风场粒子效果已经完成后续操作注意如下

1、粒子效果完成之后不会随着地图缩放变换,需要在操作之后重新进行渲染 (1)、电脑屏幕缩放 需要进行onresize监听

window.onresize = resizeCanvas; const resizeCanvas = () => { /// windycanvas = document.getElementById('windycanvas') 画布 if (windycanvas == null) return; windycanvas.width = window.innerWidth; windycanvas.height = cesiumRef.value?.clientHeight; if (windy) { // 重新设置画布大小 // eslint-disable-next-line no-underscore-dangle windy._resize(windycanvas.width, windycanvas.height); } }; 复制代码

(2)、地图缩放 地图缩放时需要对鼠标事件,滚轮事件进行监听 参考vue3.0+vite+Cesium使用记录中监听viewer操作事件讲解 伪代码

handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas); // 鼠标滚动、旋转后是否需要重新生成风场---如果需要,打开以下注释--旋转或者移动到北半球的时候计算会有问题 handler.setInputAction(() => { clearTimeout(refreshTimer); ...设置风场隐藏 refreshTimer = setTimeout(() => { if (windy) { windy.extent = ...获取当前三维窗口左上、右上、左下、右下坐标集合; windy.redraw(); } ...设置风场显示 }, 200); }, Cesium.ScreenSpaceEventType.WHEEL); // 鼠标左键、右键按下 handler.setInputAction(() => { mouseDown = true; }, Cesium.ScreenSpaceEventType.LEFT_DOWN); handler.setInputAction(() => { mouseDown = true; }, Cesium.ScreenSpaceEventType.RIGHT_DOWN); // 鼠标移动 handler.setInputAction(() => { if (mouseDown) { ...设置风场隐藏 mouseMove = true; } }, Cesium.ScreenSpaceEventType.MOUSE_MOVE); // 鼠标左键、右键抬起 handler.setInputAction(() => { if (mouseDown && mouseMove) { if (windy) { windy.extent = globalExtent; windy.redraw(); } } ...设置风场显示 mouseDown = false; mouseMove = false; }, Cesium.ScreenSpaceEventType.LEFT_UP); handler.setInputAction(() => { if (mouseDown && mouseMove) { if (windy) { windy.extent = globalExtent; windy.redraw(); } } ...设置风场显示 mouseDown = false; mouseMove = false; }, Cesium.ScreenSpaceEventType.RIGHT_UP); 复制代码

解释: ...设置风场显示:在鼠标操作以及滚轮操作后将渲染后的风场重新进行展示,属于display操作 ...设置风场隐藏:在鼠标操作以及滚轮操作时将画布进行隐藏

(3)、监听当前地球操作,时刻计算窗口坐标进行globalExtent赋值

viewer.scene.postRender.addEventListener(() => { getCesiumExtent(); }); 复制代码 // 获取当前三维窗口左上、右上、左下、右下坐标 const getCesiumExtent = () => { const canvaswidth = window.innerWidth; const canvasheight = cesiumRef.value?.clientHeight || 0 - 50; // eslint-disable-next-line camelcase const left_top_pt = new Cesium.Cartesian2(0, 0); // eslint-disable-next-line camelcase const left_bottom_pt = new Cesium.Cartesian2(0, canvasheight); // eslint-disable-next-line camelcase const right_top_pt = new Cesium.Cartesian2(canvaswidth, 0); // eslint-disable-next-line camelcase const right_bottom_pt = new Cesium.Cartesian2(canvaswidth, canvasheight); const pick1 = viewer.scene.globe.pick(viewer.camera.getPickRay(left_top_pt), viewer.scene); const pick2 = viewer.scene.globe.pick(viewer.camera.getPickRay(left_bottom_pt), viewer.scene); const pick3 = viewer.scene.globe.pick(viewer.camera.getPickRay(right_top_pt), viewer.scene); const pick4 = viewer.scene.globe.pick(viewer.camera.getPickRay(right_bottom_pt), viewer.scene); if (pick1 && pick2 && pick3 && pick4) { // 将三维坐标转成地理坐标---只需计算左下右上的坐标即可 const geoPt1 = viewer.scene.globe.ellipsoid.cartesianToCartographic(pick2); const geoPt2 = viewer.scene.globe.ellipsoid.cartesianToCartographic(pick3); // 地理坐标转换为经纬度坐标 const point1 = [(geoPt1.longitude / Math.PI) * 180, (geoPt1.latitude / Math.PI) * 180]; const point2 = [(geoPt2.longitude / Math.PI) * 180, (geoPt2.latitude / Math.PI) * 180]; // console.log(point1,point2); // 此时说明extent需要分为东西半球 if (point1[0] > point2[0]) { globalExtent = [point1[0], 180, point1[1], point2[1], -180, point2[0], point1[1], point2[1]]; } else { globalExtent = [point1[0], point2[0], point1[1], point2[1]]; } } else { globalExtent = []; } }; 复制代码 己、相关文档 vue3.0+vite+Cesium使用记录 cesium-windy-canvas源码 cesium轨迹讲解


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有