Cesium实现自定义标签功能

Cesium实现自定义标签功能

实现的底层逻辑和方法跟实现Popup弹窗功能类似,只需要修改对应的创建的html内容和css样式,即可定义出更好看的标签。

实现效果

在这里插入图片描述

源码

LabelPlot 标签类


const defaultNameField = "label";
const defaultIdField = "id";
const billboardPointDatasourceName = "LABELPLOT_BILLBOARD_POINT"

/**
 * 标签类
 */
class LabelPlot {
  constructor(info) {
    let _this = this;
    _this.viewer = info.viewer; //弹窗创建的viewer
    _this.geometry = info.position; //弹窗挂载的位置
    _this.properties = info.properties; // 属性信息
    if (!info || !info.viewer || !info.position) {
      throw new Error("缺少构造参数!");
    }

    let labelPlotId = _this._getKeyVal(info.properties,defaultIdField);
    if (!labelPlotId) {
      labelPlotId = "LabelPlot_" + (new Date().getTime() + Math.random() + '').replace('.', '');
    }
    _this.id = labelPlotId;

    _this.ctn = $("<div class='LabelPlot-container' id =  '" + _this.id + "'>");
    $(_this.viewer.container).append(_this.ctn);
    _this.ctn.append(_this._createHtml(info.properties));
    //生成底座小圆点
    if (!!info.showBillboardPoint) {
      _this.entity = _this._createBillboardPoint(info.position);
    }
    try {
      _this._render(_this.geometry);
      _this.eventListener = _this.viewer.clock.onTick.addEventListener(function (clock) {
        _this._render(_this.geometry);
      })
    } catch (e) {

    }
  }

  //关闭当前标签
  close() {
    let _this = this;
    _this.ctn.remove();
    _this.viewer.clock.onTick.removeEventListener(_this.eventListener);
    if (_this.entity) {
      let myEntityCollection = _this._getBillboardPointEntityCollection();
      myEntityCollection.entities.remove(_this.entity);
    }
  }

  //清除所有的小圆点
  static clearBillboardPointEntityCollection(){
    let dats = Viewer.dataSources.getByName(billboardPointDatasourceName);
    if (!!dats && !!dats.length) {
      dats.forEach(item => {
        Viewer.dataSources.remove(item);
      })
    }
  }

  _render(geometry) {
    let _this = this;
    let position = Cesium.SceneTransforms.wgs84ToWindowCoordinates(_this.viewer.scene, geometry);
    if (position) {
      _this.ctn.css("left", position.x);
      _this.ctn.css("top", position.y - _this.ctn.get(0).offsetHeight - 85);
      //摄像头高度超过一定值,标签隐藏
      /*let cameraHeight = _this.viewer.camera.positionCartographic.height;
      if (cameraHeight > 50000) {
        _this.ctn.hide();
      } else {
        _this.ctn.show();
      }*/
    }
  }

  //生成标签
  _createHtml(properties) {
    let _this = this;
    let labelName = _this._getKeyVal(properties,defaultNameField);
    labelName = !!labelName ? labelName : "";
    let html = '<div class="LabelPlot-content">' +
      '<div class="info-item">'+ labelName +'</div></div>';
    return html;
  }

  //生成底下的小圆点
  _createBillboardPoint(position) {
    let _this = this;
    let myEntityCollection = _this._getBillboardPointEntityCollection();
    let entityOption = {
      name: "LABELPLOT_BILLBOARD_POINT_ENTITY",
      position: position,
      point: { //点
        color: Cesium.Color.DARKBLUE.withAlpha(.4),
        pixelSize: 6,
        outlineColor: Cesium.Color.YELLOW.withAlpha(.4),
        outlineWidth: 2,
        // scaleByDistance: new Cesium.NearFarScalar(300, 1, 1200, .4),
        // disableDepthTestDistance: 500
      }
    }
    let entity = new Cesium.Entity(entityOption);
    if (entity && myEntityCollection) {
      myEntityCollection.entities.add(entity);
    }
    return entity;
  }

  _getKeyVal(data,keyName) {
    let keyVal = null;
    if (!!data && !!keyName && !!Object.keys(data).length) {
      let keys = Object.keys(data);
      for (let index = 0 ; index < keys.length;index++) {
        if (keys[index].toLowerCase() === keyName) {
          keyVal = data[keys[index]];
          break;
        }
      }
    }
    return keyVal;
  }
  _getBillboardPointEntityCollection() {
    let _this = this;
    let myEntityCollection = null;
    let dats = _this.viewer.dataSources.getByName(billboardPointDatasourceName);
    if (!dats || !dats.length) {
      myEntityCollection = new Cesium.CustomDataSource(billboardPointDatasourceName);
      _this.viewer.dataSources.add(myEntityCollection);
    } else {
      myEntityCollection = dats[0];
    }
    return myEntityCollection;
  }
}

export default LabelPlot;

css样式


.LabelPlot-container {
  background: rgba(227,238,229,.62);
  position: absolute;
  z-index: 999;
}

.LabelPlot-content {
  left: 0;
  bottom: 0;
  cursor: default;
  padding: 5px;
  border: 1px solid rgba(156,153,68,.91);
}

.LabelPlot-container:before {
  position: absolute;
  content: "";
  left: 0%;
  bottom: -80px;
  height: 80px;
  border-left: 2px dashed rgba(197,226,39,.44);
}

调用示例

let labelPlotList = [];
 let handler3D = new Cesium.ScreenSpaceEventHandler(Viewer.scene.canvas);
      handler3D.setInputAction(function (click) {
        let pick = new Cesium.Cartesian2(click.position.x, click.position.y);
        if (pick) {
          // 获取点击位置坐标
          let cartesian = Viewer.scene.globe.pick(Viewer.camera.getPickRay(pick), Viewer.scene);
          if (cartesian) {
            //生成标签
            let labelPlot = new LabelPlot({
              viewer: Viewer,
              position: cartesian,
              properties: {
                id: 'ilabel-'+new Date().getTime()+Math.random(),   
                label: 'ilabel-'+new Date().getTime()+Math.random(), 
              },
              showBillboardPoint: true
            })
            labelPlotList.push(labelPlot);
          }
        }
      }, Cesium.ScreenSpaceEventType.LEFT_CLICK)

//清除标签
if (!!labelPlotList && labelPlotList.length) {
 labelPlotList.forEach(ee=>{
    ee.close();
  })
}
labelPlotList = [];
  • 2
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
回答: 要在Vue3中使用Cesium实现自定义框,你可以按照以下步骤进行操作。首先,在vite.config.js中配置vite-plugin-cesium插件,引入Cesium和vite-plugin-cesium,并将其添加到plugins中。\[1\]然后,安装Cesium和vite-plugin-cesium插件,可以使用npm命令进行安装。\[2\]接下来,创建一个子组件,使用template标签定义组件的模板,其中包含自定义框的HTML结构和样式。\[3\]在script setup标签中,使用defineProps定义props属性,用于接收父组件传递的数据。最后,在style标签中定义组件的样式。这样就可以实现自定义框了。 #### 引用[.reference_title] - *1* *2* [使用vue3+vite+cesium,在地图上显示图标,并且点击实体弹出消息框](https://blog.csdn.net/weixin_46212682/article/details/127348864)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [Vue3+cesium添加自定义弹窗并设置随地图移动位置移动](https://blog.csdn.net/qq_43474235/article/details/129230006)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值