【开源】Cesium场景效果大全(cesium+vue3+vite+vuex)

Hello大家好,我是日拱一卒的攻城师不浪,专注前端、后端、AI学习、二三维可视化、GIS等学习沉淀,这是2024年输出的第11/100篇文章,欢迎志同道合的朋友一起学习交流;
公众号:攻城师不浪

绿泡泡:brown_7778

视频效果

前言

今天再一次带来我的开源项目Cesium-test,这个项目主要收集了cesium在日常业务开发中常用到的一些场景效果的开发。

项目地址

我用我的廉价服务器给它搭了一个窝,感兴趣的可以点击查看(服务器带宽很低,带这种3D肯定很慢,嫌慢的可以直接看上方视频效果,还有动感的音药噢~)

Cesium-test网址:www.brown77.cn:3389

Cesium

首先,我先来简单介绍一下cesium,可能有的同学还不太了解,毕竟业务可能没有涉及到这块领域。

Cesiumjs

一个开源的JavaScript库,用于在Web浏览器中创建三维地球仪和二维地图。它利用了 WebGL 技术,可以在不需要插件的情况下,为用户提供丰富的交互式三维地理信息可视化体验。

应用领域

通过介绍我们不难看出,这个框架主要应用于二三维可视化以及GIS领域,可以说非常强大。

Cesium-test

cesium-test是我近期开源的一个项目,里面集结了一些常用的业务场景效果,包括:

  1. 粒子效果
  • 下雨
  • 下雪
  • 雾天
  • 火焰
  1. POI点位
  • 基础打点
  • 聚合
  • primitive底层打点(性能佳)
  • primitive聚合(性能佳)
  • 点位动态弹窗
  1. 第三方服务加载
  • xyz瓦片
  • 3D Tiles
  1. 材质
  • 道路闪烁
  • 道路流光效果
  • 辐射圈
  • 圆扩散
  • 四色图
  • 流动的水面
  • 天空盒
  1. 几何
  • 量测
  • 点线面绘制
  • 态势图、箭头
  1. 场景
  • 水淹模拟
  • 热力图
  • 时间轴
  • 遮罩反选(边界)
  1. 分析
  • 天际线分析
  • 高程(限高)分析

其中primitive聚合这个解决方案还被知名开源项目vue-cesium所收纳!

这个开源我目前还没用过,因为我用Cesium比较少,不过看项目里场景效果覆盖的已经很全了,用需要的小伙伴可以用用试试,也欢迎给我反馈。

项目中还封装了一些公共的类以及方法,例如:绘制测量天气类聚合类等等,方便重复使用。

项目初始化

几个关键点:

  • cesium token:必须要有,到cesium官网申请,项目跑起来需要用到的
  • viewer:视角,3D场景中必备
  • 根元素:初始化canvas要用到的根元素
js 复制代码
import { onMounted } from "vue";
import store from "@/store/store.js";
import * as Cesium from "cesium";

// cesium的token,可自行申请
Cesium.Ion.defaultAccessToken =
  "xxx";

onMounted(() => {
  init();
});
const init = () => {
  const viewer = new Cesium.Viewer("cesiumContainer", {
    infoBox: false,
    timeline: false, // 是否显示时间线控件
    // 图层插件
    imageryProvider: new Cesium.ArcGisMapServerImageryProvider({
      url: "https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer",
    }),
    // 地形插件
    terrainProvider: new Cesium.CesiumTerrainProvider({
      url: "http://data.marsgis.cn/terrain",
    }),
  });

相机

3D场景中必备的相机,当你在上一步初始化成功viewer之后,就可以在viewer中拿到相机实例了。

js 复制代码
const store = useStore()
const { viewer } = store.state


viewer.camera.flyTo({
  // 从以度为单位的经度和纬度值返回笛卡尔3位置。
  destination: Cesium.Cartesian3.fromDegrees(120.36, 36.09, 40000),
  orientation: {
    // heading:默认方向为正北,正角度为向东旋转,即水平旋转,也叫偏航角。
    // pitch:默认角度为-90,即朝向地面,正角度在平面之上,负角度为平面下,即上下旋转,也叫俯仰角。
    // roll:默认旋转角度为0,左右旋转,正角度向右,负角度向左,也叫翻滚角
    heading: Cesium.Math.toRadians(0.0), // 正东,默认北
    pitch: Cesium.Math.toRadians(-90), // 向正下方看
    roll: 0.0, // 左右
  },
  duration: 3, // 飞行时间(s)
})

几何图形

在3D场景中,每一个元素小品实例都是由几何元素所构成渲染的,例如:线等。

聚合打点

这个需求其实应该在大部分业务项目中都会遇到,属于一个高频知识点,但是在碰到上万甚至是上十万的点位进行聚合的时候,我发现极大一部分人都会遇到性能上的问题,官方貌似并没有出手解决这个问题,而且我之前在网上找解决方案也很难找到。

后来我就自己倒腾了好几天,终于研发出一个还不错的解决方案。

其实官方是有现成的entity聚合类的:EntityCluster,但是这个类在碰到大批量点位的时候,性能卡的一批,因为entity是基于primitive的一个封装,而primitive才是底层的几何类,它的性能才是最优的。

因此我就按照这个思路,心想能不能仿照EntityCluster的源码以及它的算法:KDBush,去构建一个primitiveCluster大类呢,功夫不负有心人,最终还真让我实现了,在项目的src\utils\cesiumCtrl\primitiveCluster.js里。

但是我发现虽然封装好了这个类,但是还是有很多人不会用,所以怎么用也是个技术活哈哈。

js 复制代码
const billboardsCollection = viewer.scene.primitives.add(
  new Cesium.BillboardCollection()
);
let billboardsCollectionCombine = new Cesium.BillboardCollection();

let primitivesCollection = null;
let primitives = null;

const formatClusterPoint = (features) => {
  primitivesCollection = new Cesium.PrimitiveCollection();
  billboardsCollectionCombine = new Cesium.BillboardCollection();
  var scene = viewer.scene;
  let primitivecluster = null;
  primitivecluster = new PrimitiveCluster();

  //与entitycluster相同设置其是否聚合 以及最大最小值
  primitivecluster.enabled = true;
  primitivecluster.pixelRange = 60;
  primitivecluster.minimumClusterSize = 2;

  //后面设置聚合的距离及聚合后的图标颜色显示与官方案例一样
  for (let i = 0; i < features.length; i++) {
    const feature = features[i];
    const coordinates = feature.geometry.coordinates;
    const position = Cesium.Cartesian3.fromDegrees(
      coordinates[0],
      coordinates[1],
      2000
    );

    // 带图片的点
    billboardsCollectionCombine.add({
      image: "/images/mark-icon.png",
      width: 32,
      height: 32,
      position,
    });
  }
  primitivecluster._billboardCollection = billboardsCollectionCombine;
  // 同时在赋值时调用_initialize方法
  primitivecluster._initialize(scene);

  primitivesCollection.add(primitivecluster);
  primitives = viewer.scene.primitives.add(primitivesCollection);

  primitivecluster.clusterEvent.addEventListener(
    (clusteredEntities, cluster) => {
      // 关闭自带的显示聚合数量的标签
      cluster.label.show = false;
      cluster.billboard.show = true;
      cluster.billboard.verticalOrigin = Cesium.VerticalOrigin.BOTTOM;

      // 根据聚合数量的多少设置不同层级的图片以及大小
      cluster.billboard.image = combineIconAndLabel(
        "/images/school-icon.png",
        clusteredEntities.length,
        64
      );
      // cluster.billboard.image = "/images/school-icon.png";
      cluster.billboard._imageHeight = 60;
      cluster.billboard._imageWidth = 60;
      cluster.billboard._dirty = false;
      cluster.billboard.width = 40;
      cluster.billboard.height = 40;
    }
  );
  return primitivecluster;
};

有了这个类,就再也不怕大批量点位渲染卡顿的烦恼啦!

项目思考

其实别看cesium也是一个js框架,但是说实话,对一个没接触过三维的或者GIS方向的前端(比如我)来说,上手还是有一定难度的,因为它里面包含了太多的专业知识需要我们去一一攻坚。

并且,cesium封装了大量的类,毛估大概有几百个!一开始看到密密麻麻的API的时候,头瞬间就大了一圈。

而且,如果想要更好地运用 CesiumJS,不止要会一些三维的知识,学习一定的地理信息系统(GIS)知识也是有一定必要的。例如:

  1. 地理坐标系统:了解地理坐标系统(如 WGS 84、GCS、PCS 等)的基本概念和区别,以及如何在 CesiumJS 中正确设置和转换坐标系统。

  2. 地图投影:理解地图投影的原理和不同类型的地图投影(如墨卡托投影、Web墨卡托投影等),以及它们如何在 CesiumJS 中应用。

  3. 地理数据格式:熟悉常见的地理数据格式,如 GeoJSON、KML、GPX、Shapefile 等,以及如何在 CesiumJS 中加载和处理这些数据格式。

  4. 矢量数据和栅格数据:了解矢量数据(如点、线、面)和栅格数据(如卫星图像、地形数据)的区别及其在 CesiumJS 中的应用方式。

  5. 空间分析:掌握基本的空间分析概念,如缓冲区分析、叠加分析、网络分析等,这有助于你在 CesiumJS 中进行更复杂的地理信息处理。

  6. 地图符号化:理解如何在 CesiumJS 中对地图元素进行符号化,包括设置样式、颜色、图标等,以提高地图的可读性和美观性。

  7. 图层管理:了解如何在 CesiumJS 中管理和操作图层,包括添加、移除、显示和隐藏图层,以及调整图层顺序和透明度。

  8. API 和 SDK 使用:熟悉 CesiumJS 提供的 API 和 SDK,了解如何使用它们来定制地图功能和创建交互式应用。

  9. 性能优化:掌握一些性能优化的技巧,如数据简化、级别细节(LOD)、视锥体剔除等,以确保 CesiumJS 应用在不同设备上都能流畅运行。

  10. 三维建模和动画:了解基本的三维建模和动画原理,这可以帮助你在 CesiumJS 中创建更丰富的三维场景和动画效果。

  11. 实时数据集成:了解如何将实时数据(如传感器数据、社交媒体信息等)集成到 CesiumJS 应用中,以提供动态更新的地理信息服务。

最后

这个项目我已开源,也欢迎感兴趣的小伙伴能够加入进来,一起参与共建(目前还是有一定的star基础的🤭)

开源地址:github.com/tingyuxuan2...

如果觉得项目对你有帮助,希望可以随手点一个star,激励我去开源更多优秀的代码。

如果有在做数字孪生或者GIS方面的同学也可以加我交流:brown_7778,我拉你进交流群。

如果觉得文章对你有帮助,也欢迎一键三连👏👏👏,你的鼓励是支持我持续原创下去的动力~

相关推荐
修己xj6 小时前
Anki:让记忆更高效、更智能的开源力量
开源
冬奇Lab12 小时前
一天一个开源项目(第17篇):ViMax - 多智能体视频生成框架,导演、编剧、制片人全包
开源·音视频开发
一个处女座的程序猿14 小时前
AI之Agent之VibeCoding:《Vibe Coding Kills Open Source》翻译与解读
人工智能·开源·vibecoding·氛围编程
一只大侠的侠15 小时前
React Native开源鸿蒙跨平台训练营 Day16自定义 useForm 高性能验证
flutter·开源·harmonyos
cs阿坤dn15 小时前
SumperMap超图镶嵌数据集导入及处理流程--二维地图瓦片
gis
IvorySQL15 小时前
PostgreSQL 分区表的 ALTER TABLE 语句执行机制解析
数据库·postgresql·开源
一只大侠的侠16 小时前
Flutter开源鸿蒙跨平台训练营 Day11从零开发商品详情页面
flutter·开源·harmonyos
一只大侠的侠16 小时前
React Native开源鸿蒙跨平台训练营 Day18自定义useForm表单管理实战实现
flutter·开源·harmonyos
一只大侠的侠16 小时前
React Native开源鸿蒙跨平台训练营 Day20自定义 useValidator 实现高性能表单验证
flutter·开源·harmonyos
晚霞的不甘17 小时前
Flutter for OpenHarmony 可视化教学:A* 寻路算法的交互式演示
人工智能·算法·flutter·架构·开源·音视频