vue + cesium 实现 Entity实例生命周期和vue组件生命周期融合

本文介绍如何将Cesium中的Entity实例生命周期与Vue组件生命周期相结合,通过封装Vue组件实现弹窗展示及交互功能,提高代码可读性和维护性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

🚀 个人简介:某大型测绘遥感企业资深Webgis开发工程师,软件设计师(中级)、优快云优质创作者
💟 作 者:柳晓黑胡椒❣️
📝 专 栏:cesium实践(原生)
🌈 若有帮助,还请关注点赞收藏,不行的话我再努努力💪💪💪

场景

ceisum中Entity实例的生成和销毁,大部分逻辑和vue代码分离,导致不好阅读和维护

解决方案

ceisum 中实例 Entity 的生命周期,和vue的生命周期’相似’,把两个生命周期结合(把entity封装为vue组件)

实现方案

  1. vue中 template 中内容可以放置 弹框的内容,通过ceisum 获取屏幕坐标,进行渲染
  2. 通过代码逻辑使 vue组件的 mountedbeforeDestroy 来和 entity 实例的生成 add,和销毁destroy 相关联
  3. 通过 Cesium.ScreenSpaceEventHandler 关联vue组件的方法实现交互

方案解决效果

在这里插入图片描述

index.vue

采用原生cesium 实现entity的弹窗,并封装为vue组件

<!--/**
 * @author: liuk
 * @date: 2023/8/10
 * @describe: 小区视角
 * @email:1229223630@qq.com
*/-->
<template>
  <div>
    <div class="heat-info" v-if="showPopup" :style="{top:popupPos.top,left:popupPos.left}">
      <div class="name">小区</div>
      {{showPopup}}
      <div class="bottom_div">
        <div>
          <div class="num">20.3&nbsp;<span></span></div>
          <div style="margin-top: 6px;">均温</div>
        </div>
        <div>
          <div class="num">92.9&nbsp;<span>%</span></div>
          <div style="margin-top: 6px;">室温</div>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import communityList from "../data/community.json"

let heatDatasource, preSelEntity,handler
export default {
  data(){
    return {
      showPopup: false,
      popupPos: {
        left: 0,
        top: 0
      },
    }
  },
  methods:{
    addEntity() {
      let features = communityList.features || [];
      features.forEach(el => {
        let pos = Cesium.Cartesian3.fromDegreesArray(el.geometry.coordinates[0].map(el1 => {
          return el1.join(',')
        }).join(',').split(',').map(Number));
        let boundingSphere = new Cesium.BoundingSphere.fromPoints(pos);
        let center = boundingSphere.center;
        heatDatasource.entities.add({
          position: center,
          customType: "communityEntity",
          label: {
            text: el.properties.name,
            disableDepthTestDistance: Number.POSITIVE_INFINITY,
            horizontalOrigin: Cesium.HorizontalOrigin.Top,
            scaleByDistance: new Cesium.NearFarScalar(2000, 1, 500000, 0.1)
          },
          show: true,
          polygon: {
            hierarchy: new Cesium.PolygonHierarchy(pos),
            heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
            material: Cesium.Color.fromCssColorString("white").withAlpha(0),
          },
          polyline: {
            show: true,
            positions: pos,
            width:1.5,
            material: Cesium.Color.fromCssColorString("#C0C0C0").withAlpha(0.5),
            heightReference: Cesium.HeightReference.CLAMP_TO_GROUND
          }
        });
      })
    },
    onMouseClick(movement){
      var preSelEntity = window.dasViewer.scene.pick(movement.position);
      if (!Cesium.defined(preSelEntity) || !Cesium.defined(preSelEntity.id)) return;
      var entity = preSelEntity.id;
      if (!(entity instanceof Cesium.Entity) || entity.customType !== "communityEntity") return;
      window.dasViewer.camera.flyTo({
        destination: Cesium.Rectangle.fromCartesianArray(entity.polygon.hierarchy.getValue().positions),
        complete: () => {
          this.$emit('hideCommunityEntity')
        }
      });
    },
    onMouseMove(movement){
      var pickedObject = window.dasViewer.scene.pick(movement.endPosition);
      if (!Cesium.defined(pickedObject) || !Cesium.defined(pickedObject.id)) {
        this.resetSelectedEntity();
        return;
      }
      var entity = pickedObject.id;
      if (!(entity instanceof Cesium.Entity) || entity.customType !== "communityEntity") {
        this.resetSelectedEntity();
        return;
      }
      if (entity !== preSelEntity) {
        this.resetSelectedEntity();
        entity.polygon.material = Cesium.Color.fromCssColorString("white").withAlpha(0.1);
        entity.polyline.material = Cesium.Color.fromCssColorString("white").withAlpha(1);
      }
      preSelEntity = entity;
      this.showPopupBox(movement.endPosition);
    },
    onMouseLeave(){
      this.showPopup = false
    },
    resetSelectedEntity(){
      if (preSelEntity) {
        this.showPopup = false
        preSelEntity.polygon.material = Cesium.Color.fromCssColorString("white").withAlpha(0);
        preSelEntity.polyline.material = Cesium.Color.fromCssColorString("#C0C0C0").withAlpha(0.5);
        preSelEntity = null;
      }
    },
    showPopupBox(movement){
      this.showPopup = true
      this.popupPos.left = `${movement.x + 10}px`;
      this.popupPos.top = `${movement.y + 10}px`;
    }
  },
  mounted(){
    const self = this
    heatDatasource = new Cesium.CustomDataSource("community");
    window.dasViewer.dataSources.add(heatDatasource);
    this.addEntity()
    handler = new Cesium.ScreenSpaceEventHandler(window.dasViewer.scene.canvas);
    handler.setInputAction(self.onMouseClick, Cesium.ScreenSpaceEventType.LEFT_CLICK);
    handler.setInputAction(self.onMouseMove, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
    handler.setInputAction(self.onMouseLeave, Cesium.ScreenSpaceEventType.MOUSE_LEAVE);
  },
  beforeDestroy() {
    handler.destroy()
    window.dasViewer.dataSources.remove(heatDatasource);
  }
}
</script>


<style lang="less" scoped>
.heat-info {
  position: absolute;
  width: 196px;
  min-height: 124px;
  padding: 12px;
  border: 1px solid rgba(85, 85, 85, 1);
  box-shadow: 0px 2px 4px 0px rgba(0, 0, 0, 0.5);
  border-radius: 4px;
  background-color: rgba(0, 0, 0, 0.8);
  color: #fff;
  z-index: 9999;
  pointer-events: none;

  .name {
    font-family: PingFangSC-Medium;
    font-size: 16px;
    color: #FFFFFF;
    letter-spacing: 0;
    font-weight: 500;
    margin-top: 5px;
  }

  .bottom_div {
    display: flex;
    position: relative;
    justify-content: space-between;
    font-size: 12px;
    color: #A2A3A3;
    letter-spacing: 0;
    font-weight: 400;
    font-family: PingFangSC-Regular;
    margin-top: 21px;

    .num {
      font-size: 20px;
      color: #FFFFFF;
      letter-spacing: 0;
      line-height: 16px;
      font-weight: 400;

      span {
        font-size: 12px;
        color: #FFFFFF;
        letter-spacing: 0;
        font-weight: 200;
        color: #A2A3A3;
      }
    }

  }
}
</style>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

柳晓黑胡椒

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值