开源!Cesium楼体分层抽屉动画技术揭秘,智慧城市必备技能

370 阅读4分钟

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

效果预览

楼层动画.gif

在智慧城市、建筑信息模型(BIM)、室内导航等领域,楼层展开动画可以说是非常常见的一种功能需求了。

所以,今天我们来看一下在Cesium中,如何实现的楼层展开与合并的动画功能。

源码请文末领取,还包含了Threejs的智慧园区(楼层动画展开)的源码

应用场景

  1. 建筑信息可视化:通过展开楼层,可以直观展示建筑内部结构和各楼层的分布情况。

  2. 紧急疏散演练:在消防安全培训中,可以清晰展示建筑的疏散通道和紧急出口位置。

  3. 室内导航:展开楼层后,用户可以更容易理解从一个楼层到另一个楼层的路径。

  4. 设施管理:对于物业管理人员,可以更直观地查看各楼层设备设施的分布状况。

  5. 房地产展示:销售人员可以通过展开楼层向潜在买家展示整栋建筑的结构和户型。

实现原理

该功能的实现原理核心在于通过调整三维模型的高度位置来实现楼层的展开与合并效果。具体来说:

  1. 模型分层:将建筑模型分为多个楼层和一个楼顶,每个部分作为独立的Entity添加到Cesium场景中。

  2. 位置控制:通过修改每个楼层实体的position属性,调整其高度来实现展开和合并效果。

  3. 数据记录:使用数组记录每个楼层的原始位置信息,便于后续进行位置变换。

核心代码解析

1. 初始化楼层

function initFloor() {
  if (!viewer) return;

  viewer.entities.removeAll();
  floorArr = [];

  const floor = parseInt(floorNum.value);

  // 创建楼层
  for (let i = 0; i < floor; i++) {
    const position = Cesium.Cartesian3.fromDegrees(x, y, i * 3);
    const entity = viewer.entities.add({
      position: position,
      model: {
        uri: "//data.mars3d.cn/gltf/mars/floor/floor.glb",
        scale: 1,
      },
    });

    floorArr.push({
      pos: [x, y, i * 3],
      entity: entity,
    });
  }

  // 创建楼顶
  const position1 = Cesium.Cartesian3.fromDegrees(x, y, floor * 3);
  const entity1 = viewer.entities.add({
    position: position1,
    model: {
      uri: "//data.mars3d.cn/gltf/mars/floor/top.glb",
      scale: 1,
    },
  });

  floorArr.push({
    pos: [x, y, floor * 3],
    entity: entity1,
  });
}

这段代码是楼层展开功能的基础。它主要做了以下几件事:

  • 清除场景中已有的实体并重置楼层数组

  • 根据用户输入的楼层数量(floorNum),循环创建楼层模型

  • 每个楼层模型在垂直方向上间隔3个单位高度

  • 使用floorArr数组记录每个楼层的原始坐标和对应的实体对象

  • 最后创建楼顶,并同样将其添加到floorArr

2. 楼层展开功能

function openFloorModel() {
  for (let i = 0; i < floorArr.length; i++) {
    const element = floorArr[i];
    element.entity.position = Cesium.Cartesian3.fromDegrees(
      element.pos[0],
      element.pos[1],
      element.pos[2] * 2
    );
  }
}

展开功能的核心是将每个楼层的高度值(element.pos[2])乘以2,使楼层之间的间距变大,从而实现展开效果。这里的关键点是:

  • 遍历floorArr数组中的每个楼层

  • 保持楼层的经纬度不变,只修改高度值

  • 使用Cesium.Cartesian3.fromDegrees方法将经纬度高度转换为Cesium中的三维坐标

3. 楼层合并功能

function closeFloorModel() {
  for (let i = 0; i < floorArr.length; i++) {
    const element = floorArr[i];
    element.entity.position = Cesium.Cartesian3.fromDegrees(
      element.pos[0],
      element.pos[1],
      element.pos[2] / 1
    );
  }
}

合并功能则是将楼层恢复到原始位置,这里虽然代码中使用了element.pos[2] / 1(实际上相当于不变),但原理是将每个楼层恢复到初始化时的高度位置。

4. 楼层抽出动画

楼层抽屉式动画抽出

楼层抽出动画原理,其实主要就是动态修改楼层entity的x,y坐标位置,再结合浏览器的requestAnimationFrame方法,添加缓动动画即可。

这部分功能暂时还未开放,放在了我的Cesium教程

总结

OK,以上就是在Cesium中实现楼层展开与合并的一个技术方案与思路,实际业务过程中,我们就可以让建模师把楼层分成单独的entity,然后我们去控制楼层的位置摆放,进而实现动画效果。

源码】:github.com/jiawanlong/…

不浪的Cesium案例集合】:github.com/tingyuxuan2…

不浪的Three智慧园区开源】:github.com/tingyuxuan2…

如果开源对您有帮助,也欢迎帮我们点一个免费的star,以鼓励和支持我们开源更多案例!

如有任何问题或需要进一步探讨,欢迎在评论区留言交流!

想系统学习Cesium的小伙伴儿,可以了解下不浪的教程《Cesium从入门到实战》,将Cesium的知识点进行串联,让不了解Cesium的小伙伴拥有一个完整的学习路线,并最终完成一个智慧城市的完整项目,课程最近也更新了不少新内容,想了解+作者:brown_7778(备注来意)。

有需要进可视化&Webgis交流群可以加我:brown_7778(备注来意)。