应急指挥&污染扩散模拟 | Cesium 多边形动态扩散墙实战教程(附源码)

大家好,我是日拱一卒的攻城师不浪,致力于前沿科技探索,摸索小而美工作室。这是2025年输出的第7/100篇文章。

今天咱们来聊聊如何在Cesium中实现一个动态多边形扩散效果,源码请文末自取。

这种效果在应急指挥污染扩散模拟甚至游戏场景中都非常实用。本文将从代码实战出发,带你手撕实现逻辑!

效果预览

🎯 应用场景:当技术遇上业务

  • 应急指挥 :模拟火灾、洪水等灾害的扩散范围,所以不止有辐射圈哦。

  • 环境监测:动态展示污染物扩散趋势。

实现原理

多边形扩散圈效果的核心是通过动态几何形状材质透明度渐变实现,具体分为以下两个部分:

1.1 动态多边形生成

  • 顶点计算 :根据中心点、边数(edge)和当前半径(currentRadius),计算正多边形顶点坐标。每个顶点的位置通过极坐标公式 (x = r*cosθ, y = r*sinθ) 确定,再转换为三维空间坐标。

  • 实时更新 :使用Cesium的CallbackProperty属性,逐帧更新多边形半径和高度,实现扩散动画。当半径超过设定值或高度降为0时,参数重置,形成循环效果。

1.2 材质渐变效果

  • 透明度控制 :在GLSL着色器中,通过fract(st.t)获取纹理坐标的垂直分量,实现从底部到顶部的透明度渐变。公式 material.alpha = color.a * (1.0 - fract(st.t)) * 0.8 使得高度越高越透明。

核心代码分析

动态多边形类 WallRegularDiffuse

javascript 复制代码
// 实时更新多边形顶点(WallPolygonDiffuse.js)
positions: new Cesium.CallbackProperty(() => {
  this._currentRadius += (this._radius * this._speed) / 1000.0;
  this._currentHeight -= (this._height * this._speed) / 1000.0;
  
  // 参数重置逻辑
  if (this._currentRadius > this._radius || this._currentHeight < 0) {
    this._currentRadius = this._minRadius;
    this._currentHeight = this._height;
  }
  
  return this._getPositions(...);
}, false)
  • 功能:每帧更新半径和高度,超出范围后重置,形成循环动画。

  • 关键点CallbackProperty是Cesium的动态属性机制,允许属性值随时间变化。

简单来说,这就是一个**"呼吸循环"**:每次渲染时增大半径、减小高度,超出阈值后重置,形成无限循环的扩散动画。

顶点生成方法 _getPositions

javascript 复制代码
// 扩散正多变形的边数
this._edge = options.edge || 64;
let modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(...);
for (let i = 0; i < edge; i++) {
  let angle = (i / edge) * Cesium.Math.TWO_PI;
  let point = new Cesium.Cartesian3(x * currentRadius, y * currentRadius, currentHeight);
  positions.push(Cesium.Matrix4.multiplyByPoint(modelMatrix, point));
}
  • 功能:将局部坐标转换为世界坐标,生成闭合多边形(首尾顶点需要重复)。

自定义材质类 WallDiffuseMaterialProperty

着色器代码(核心)

glsl 复制代码
// 透明度渐变逻辑(WallDiffuseMaterialProperty.js)
material.alpha = color.a * (1.0 - fract(st.t)) * 0.8;
  • 解释st.t表示纹理的垂直坐标(0到1),fract(st.t)取其小数部分,实现从下到上透明度递减。

材质定义

javascript 复制代码
Cesium.Material._materialCache.addMaterial(
  Cesium.Material.WallDiffuseMaterialType, {
    fabric: {
      source: `uniform vec4 color; ...`, // 上述GLSL代码
      uniforms: { color: new Cesium.Color(...) }
    },
    translucent: true // 启用透明度
  }
);
  • 功能:将自定义材质注册到Cesium材质系统,供实体调用。

关键参数说明

参数名 作用
edge 控制多边形的边数(>=3)
speed 扩散速度(值越大动画越快)
radius/height 最大扩散半径和初始高度
minRadius 重置时的最小半径(循环起点)

总结

通过结合Cesium的动态属性机制和自定义着色器,我们实现了多边形扩散圈这一复杂视觉效果。此方案可扩展应用于雷达扫描、灾害范围模拟等场景。

核心思想是动态几何+材质控制,大家也可调整参数或修改着色器代码实现更多变种效果。

最后

【源码地址】:github.com/tingyuxuan2...

【预览地址】tingyuxuan2302.github.io/cesium-vue3...

如果开源对您有帮助,希望可以给一个star,鼓励我们开源更多!

不会Cesium的基础,也很难做出更高级的效果,所以可以了解下不浪的教程《Cesium从入门到实战》将Cesium的知识点进行串联,让不了解Cesium的小伙伴拥有一个完整的学习路线,并最终完成一个智慧城市的完整项目,课程也在不断更新迭代中,想了解+作者:brown_7778(备注来意)。
有需要进可视化&Webgis交流群可以加我:brown_7778(备注来意)。

相关推荐
LYFlied1 天前
【每日算法】LeetCode 84. 柱状图中最大的矩形
前端·算法·leetcode·面试·职场和发展
Bigger1 天前
Tauri(21)——窗口缩放后的”失焦惊魂”,游戏控制权丢失了
前端·macos·app
Bigger1 天前
Tauri (20)——为什么 NSPanel 窗口不能用官方 API 全屏?
前端·macos·app
bug总结1 天前
前端开发中为什么要使用 URL().origin 提取接口根地址
开发语言·前端·javascript·vue.js·html
一招定胜负1 天前
网络爬虫(第三部)
前端·javascript·爬虫
Shaneyxs1 天前
从 0 到 1 实现CloudBase云开发 + 低代码全栈开发活动管理小程序(13)
前端
半山烟雨半山青1 天前
微信内容emoji表情包编辑器 + vue3 + ts + WrchatEmogi Editor
前端·javascript·vue.js
码途潇潇1 天前
Vue 事件机制全面解析:原生事件、自定义事件与 DOM 冒泡完全讲透
前端·javascript
zmirror1 天前
Monorepo 在 Docker 中的构建方案方案
前端
用户47949283569151 天前
node_modules 太胖?用 Node.js 原生功能给依赖做一次大扫除
前端·后端·node.js