官方教材中提到,Primitive API
主要适用于图形渲染开发者,Entity API
则适用于数据驱动的可视化,而Entity API
的底层则使用了Primitive API
。下面我们将通过cesium的源码探究当添加entity
对象时,是如何在底层调用对应的Primitive API
,创建相应的primitive
对象。
这篇文章中,我们将先从viewer初始化开始,探究各个对象之间的关系以及其相互之间的相应关系。
这是下文中涉及到的类的类图,从中可以清晰的了解各个对象之间的关系,接下来我们结合代码来仔细讲解。
viewer.entities
我们定位到下面三个目标_dataSourceDisplay
、defaultDataSource
、entities
entities: {
get: function () {
return this._dataSourceDisplay.defaultDataSource.entities;
},
},
viewer
中创建对象_dataSourceDisplay
// 创建dataSourceDisplay对象
const dataSourceDisplay = new DataSourceDisplay({
scene: scene,
dataSourceCollection: dataSourceCollection,
});
this._dataSourceDisplay = dataSourceDisplay;
defaultDataSource
const defaultDataSource = new CustomDataSource();
_entityCollection
entities
其实对应的是属性_entityCollection
/**
* Gets the collection of {@link Entity} instances.
* @memberof CustomDataSource.prototype
* @type {EntityCollection}
*/
entities: {
get: function () {
return this._entityCollection;
},
},
_entityCollection
this._entityCollection = new EntityCollection(this);
_entityCollection
对象的add
函数时,其内部调用了fireChangedEvent
函数EntityCollection.prototype.add = function (entity) {
// 创建entity对象
if (!(entity instanceof Entity)) {
entity = new Entity(entity);
}
// 发出信号
fireChangedEvent(this);
return entity;
};
fireChangedEvent
则对外发出了一个信号,其中包含了当前添加的对象、移除的对象以及发生变化的对象function fireChangedEvent(collection) {
// evnet 对象发出信号
collection._collectionChanged.raiseEvent(
collection,
addedArray,
removedArray,
changedArray
);
}
_collectionChanged
是_entityCollection
初始化时创建的一个Event对象this._collectionChanged = new Event();
既然有信号被发出,那就需要找到监听的一方,查看源码可以发现
_dataSourceDisplay
中创建defaultDataSource
之后,调用了函数this._onDataSourceAdded(undefined, defaultDataSource);
defaultDataSource
的_visualizers
进行赋值DataSourceDisplay.prototype._onDataSourceAdded = function (
dataSourceCollection,
dataSource
) {
dataSource._visualizers = this._visualizersCallback(
scene,
entityCluster,
dataSource
);
};
this._visualizersCallback
都返回了什么 this._visualizersCallback = defaultValue(
options.visualizersCallback,
DataSourceDisplay.defaultVisualizersCallback
);
DataSourceDisplay.defaultVisualizersCallback = function (
scene,
entityCluster,
dataSource
) {
const entities = dataSource.entities;
return [
new BillboardVisualizer(entityCluster, entities),
new GeometryVisualizer(
scene,
entities,
dataSource._primitives,
dataSource._groundPrimitives
),
new LabelVisualizer(entityCluster, entities),
new ModelVisualizer(scene, entities),
new Cesium3DTilesetVisualizer(scene, entities),
new PointVisualizer(entityCluster, entities),
new PathVisualizer(scene, entities),
new PolylineVisualizer(
scene,
entities,
dataSource._primitives,
dataSource._groundPrimitives
),
];
};
这段代码比较长,但还是可以看出是返回了一个包含了各类Visualizer
的列表,其中将entities
也就是我们上面的_entityCollection
作为参数传递进去。
4. 以GeometryVisualizer
为例,看看在构造函数阶段都做了什么
function GeometryVisualizer(
scene,
entityCollection,
primitives,
groundPrimitives
) {
this._entityCollection = entityCollection;
entityCollection.collectionChanged.addEventListener(
GeometryVisualizer.prototype._onCollectionChanged,
this
);
}
_onCollectionChanged
函数,可以看见其将添加到entity
添加到了this._addedObjects
属性中/**
* @private
*/
GeometryVisualizer.prototype._onCollectionChanged = function (
entityCollection,
added,
removed
) {
const addedObjects = this._addedObjects;
for (i = added.length - 1; i > -1; i--) {
entity = added[i];
id = entity.id;
if (removedObjects.remove(id)) {
changedObjects.set(id, entity);
} else {
addedObjects.set(id, entity);
}
}
};
于是我们找到了监听collectionChanged
事件的对象,以及如何将被添加的entity
传递到GeometryVisualizer
,从而完成了事件发出到监听的闭环。
在这之后又是如何根据GeometryVisualizer
中的_addedObjects
创建primitive
呢,这我们将在下一篇文章中进行详细的描述。