Cesium - 从未如此优雅地管理 Entity(实体)

539 阅读2分钟

当我接收到前人的代码时,我内心是崩溃的。当我看到无数entity被挂载window下以方便传递,entity.id被指定为“类型-后端返回的id”时,我想是时候提前40年退休了,因为处理这种屎山无异于屎里淘金。

  • 神说,要优雅————

  • 于是我在文档里发现了 EntityCollection

不说怪话,今天来谈谈EntityCollection,实际上是对 syncEntityCollection 的介绍。

介绍

或许大家已经尝试过使用 EntityCollection 对entity进行管理,但是对于需要分类的情况,即使是EntityCollection也很难办。因为他只是提供了一种扁平的数据结构(也就是其内部使用的数组)。而 Cesium use 的 syncEntityCollection 给出了一种很有意思的思路:在扁平化数据结构的基础上拓展为树形结构。

简单来说,syncEntityCollection 方法将一个 EntityCollection 同步到另一个 EntityCollection。大白话说起来没什么用,直接上代码:

const collection = new Cesium.EntityCollection()

syncEntityCollection(viewer.entities, collection) // 将 collection 同步到 viewer.entities

这样在对collection进行增删操作时,这些操作都会被同步到viewer.entities,因为viewer.entities也是一个EntityCollection。

const entity = collection.add({})
viewer.entities.contains(entity) // true

collection.remove(entity)
viewer.entities.contains(entity) // false

syncEntityCollection 提供了一种简写,如果没有传递第二个参数,那么会自动创建一个空的集合,同步到目标集合后返回:

const newCollection = syncEntityCollection(viewer.entities)

这种同步是可以多个数量的,既可以向多个EntityCollection同步,也可以被多个EntityCollection同步

const c1 = new Cesium.EntityCollection()
const c2 = syncEntityCollection(c1)

const c3 = new Cesium.EntityCollection()

syncEntityCollection(viewer.entities, c2)
syncEntityCollection(viewer.entities, c3)

接下来是最精彩的地方。因为collection本身也是一个EntityCollection,因此他也可以被同步:

// 没看明白没关系,见下图
const together = syncEntityCollection(viewer.entities)

const syncTo = () => syncEntityCollection(together)

const layers = syncTo()
const others = syncTo()

上面这段代码看起来像这样:

1.png

有了这种方案,你可以完全无视entity管理本身带来的复杂度,举个例子:

实战

你的项目中需要管理图层,因此有个图层集合:

const layers = syncEntityCollection(viewer.entities)

图层中存在一个小姐姐类型,用来表示所有小姐姐。你的小姐姐有很多,所以可以用EntityCollection来管理:

const city = syncEntityCollection(layers)
const food = syncEntityCollection(layers)
// ...
const beauty = syncEntityCollection(layers)

然而你的小姐姐还要分正室、侧室、后宫。。。因此小姐姐们也要用EntityCollection管理:

const wife = syncEntityCollection(beauty)
const concubine = syncEntityCollection(beauty)
// ...

终于可以好好把小姐姐放进集合里管理了:

const wifeA = wife.add({
  position: xxx
})

const concubineB = concubine.add({
  position: yyy
})

代码看起来很简单,对吧?你只需要妥善管理其层级即可,最终看起来像这样:

2.png

在必要的时候,可以隐藏所有的wife: wife.show = false

也可以直接隐藏所有的妹子 beauty.show = false

报告完毕!