cesium入坑1 -- vue中渲染多个entity事件优化
目前项目开发中需要使用渲染多个entity实体在地图上,并且通过监听相机高度来进行不同的交互,所有打算将entity封装成一个组件使用:
在这里插入代码片
**modelEntity组件:用js封装的entity组件**
export default {
name: "modelEntity",
// 通过inject注入获取viewer
inject: ["viewerPromise"],
props: {
id: String,
uri: String,
icon: String,
scale: Number,
position: {
type: Object,
default () {
return {}
}
},
orientation: Object,
model: {
type: Object,
default () {
return {}
}
},
billboard: {
type: Object,
default () {
return {}
}
},
label: {
type: Object,
default () {
return {}
}
}
},
created () {
this.viewerPromise.then(viewer => {
this.viewer = viewer;
this.init()
})
},
beforeDestroy () {
if (!this.viewer.isDestroyed()) {
this.viewer.entities.remove(this.graphic)
}
},
methods: {
init () {
const { position, orientation, model, billboard, label } = this;
// 通过这样实例创建可以将每个entity的各个属性进行抽离
const graphic = new Cesium.Entity({
id: this.id || this._uid,
position, // Cartesian3坐标
orientation, // 方向值
model, // 3d模型
billboard, // 广告牌
label // 文字label
})
this.graphic = graphic;
this.viewer.entities.add(graphic)
this.$emit("load")
},
},
render () { }
}
// 组件中具体使用,省去部分引用和数据来源
<K3ModelEntity
v-for="item in list"
:id="`stationline${item.id}`"
:key="`stationline${item.id}`"
:position="item.position"
:orientation="item.orientation"
:billboard="lineBillboard"
@load="handleEntityLoad"
@click="handleModelClick($event, item)"
@mousemove="handleMousemove($event, item)"
@mouseout="handleMouseout"
/>
<K3ModelEntity
v-for="item in list"
:id="`stationmeasure${item.id}`"
:key="`stationmeasure${item.id}`"
:position="item.position"
:orientation="item.orientation"
:model="stationModelStyle"
:billboard="measureBillboard"
@click="handleModelClick($event, item)"
@mousemove="handleMousemove($event, item)"
@mouseout="handleMouseout"
/>
<script type = 'text/javascript'>
export default {
props: {
zoomLevel: {
type: String,
default: MONITOR_LEVEL_MAPS.area
}
},
watch: {
// 此属性是通过外部监听相机高度,根据不同的相机高度显示了不同的层级通过zoomLevel显示,为了区分开
// 不同层级的entity,这里将每个层级的entity完全分开,然后通过id值去寻找同一类的entity进行统一显示隐藏
zoomLevel: {
async handler (val) {
await this.mapLoadedPromise
switch (val) {
// 这里层级涉及项目,统一用第一二三处理
case "第一层级": {
this.entitiesIdVisible("stationline", false)
this.entitiesIdVisible("stationmeasure", false)
break
}
case "第二层级": {
this.entitiesIdVisible("stationline", true)
this.entitiesIdVisible("stationmeasure", false)
break
}
case "第三层级": {
this.entitiesIdVisible("stationline", false)
this.entitiesIdVisible("stationmeasure", true)
break
}
default: {
this.entitiesIdVisible("stationline", false)
this.entitiesIdVisible("stationmeasure", false)
}
}
},
immediate: true
},
},
beforeCreate () {
this.mapLoadedPromise = new Promise((resolve) => {
this.mapLoadedPromiseResolve = resolve
})
this.stationModelStyle = {
uri: "/static/models/station.gltf",
scale: 0.1,
}
this.lineBillboard = {
image: require(`@/assets/images/priority/bus-station-layer.svg`),
width: 44,
height: 103,
horizontalOrigin: Cesium.HorizontalOrigin.MIDDLE,
verticalOrigin: Cesium.VerticalOrigin.BOTTOM
}
this.measureBillboard = {
image: require(`@/assets/images/priority/bus-station-model-layer.svg`),
width: 44,
height: 59,
pixelOffset: new Cesium.Cartesian2(0, -127),
// pixelOffsetScaleByDistance: new Cesium.NearFarScalar(60, 5, 520, 1),
// scaleByDistance: new Cesium.NearFarScalar(60, 1, 520, 1),
horizontalOrigin: Cesium.HorizontalOrigin.MIDDLE,
verticalOrigin: Cesium.VerticalOrigin.BOTTOM
}
},
methods: {
// 这个promise回调函数主要为了确保zoom中实体的显示隐藏是在所有实体加载完成后执行
async handleEntityLoad () {
this.mapLoadedPromiseResolve()
},
entitiesIdVisible (id, visible) {
this.viewer.entities._entities._array.forEach(item => {
if (item.id.indexOf(id) >= 0) {
item.show = visible
}
})
},
}
最后展示一下效果图
相机高度为600时
相机高度为1500时
下面一篇文章会将监听相机事件等的坑都进行展示