cesium入坑1 -- vue中渲染多个entity事件优化

475 阅读2分钟

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时 相机高度为1500时

相机高度为600时

下面一篇文章会将监听相机事件等的坑都进行展示