这里重点说一下CallbackProperty是一个类,其值由回调函数延迟计算。也就是说它在不断地自我调用,每当其返回的对象有改变时,就会抛出改变后的值。利用这种特性,我们就可以在定义hierarchy(层次结构)时,用CallbackProperty生成动态的对象赋值给hierarchy(层次结构)参数,就可以得到动态绘制多边形的效果。

使用方法:调用 click_draw_polygon() 方法就可以

// 多边形全部点的数组
var polygon_point_arr = [];
// 临时多边形entity
var temporary_polygon_entity = null;
var handler = null;

// 开启绘制的方法
function click_draw_polygon() {
  // 清除可能会用到的监听事件
  if (handler) {
    handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK);
    handler.removeInputAction(Cesium.ScreenSpaceEventType.MOUSE_MOVE);
    handler.removeInputAction(Cesium.ScreenSpaceEventType.RIGHT_CLICK);
  }
  handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);

  //鼠标左键--确定选中点
  handler.setInputAction((event) => {
    // 屏幕坐标转为空间坐标
    let cartesian = viewer.camera.pickEllipsoid(event.position, viewer.scene.globe.ellipsoid);
    // 判断是否定义(是否可以获取到空间坐标)
    if (Cesium.defined(cartesian)) {
      // 将点添加进保存多边形点的数组中,鼠标停止移动的时添加的点和,点击时候添加的点,坐标一样
      polygon_point_arr.push(cartesian);
      // 判断是否开始绘制动态多边形,没有的话则开始绘制
      if (temporary_polygon_entity == null) {
        // 绘制动态多边形
        draw_dynamic_polygon();
      }
    }
  }, Cesium.ScreenSpaceEventType.LEFT_CLICK);

  //鼠标移动--实时绘制多边形
  handler.setInputAction((event) => {
    // 屏幕坐标转为空间坐标
    let cartesian = viewer.camera.pickEllipsoid(event.endPosition, viewer.scene.globe.ellipsoid);
    // 判断是否定义(是否可以获取到空间坐标)
    if (Cesium.defined(cartesian)) {
      // 判断是否已经开始绘制动态多边形,已经开始的话,则可以动态拾取鼠标移动的点,修改点的坐标
      if (temporary_polygon_entity) {
        // 只要元素点大于一,每次就删除一个点,因为实时动态的点是添加上去的
        if (polygon_point_arr.length > 1) {
          // 删除数组最后一个元素(鼠标移动添加进去的点)
          polygon_point_arr.pop();
        }
        // 将新的点添加进动态多边形点的数组中,用于实时变化,注意:这里是先添加了一个点,然后再删除点,再添加,这样重复的
        polygon_point_arr.push(cartesian);
      }
    }
  }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);

  //鼠标右键--结束绘制
  handler.setInputAction((event) => {
    // 取消鼠标移动监听
    handler.removeInputAction(Cesium.ScreenSpaceEventType.MOUSE_MOVE);
    // 清除动态绘制的多边形
    viewer.entities.remove(temporary_polygon_entity);
    // 删除保存的临时多边形的entity
    temporary_polygon_entity = null;
    // 绘制结果多边形
    draw_polygon();
    // 清空多边形点数组,用于下次绘制
    polygon_point_arr = [];
    // 清除所有事件
    if (handler) {
      handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK);
      handler.removeInputAction(Cesium.ScreenSpaceEventType.MOUSE_MOVE);
      handler.removeInputAction(Cesium.ScreenSpaceEventType.RIGHT_CLICK);
    }
  }, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
}

//绘制动态多边形
function draw_dynamic_polygon() {
  temporary_polygon_entity = viewer.entities.add({
    polygon: {
      // 这个方法上面有重点说明
      hierarchy: new Cesium.CallbackProperty(() => {
        // PolygonHierarchy 定义多边形及其孔的线性环的层次结构(空间坐标数组)
        return new Cesium.PolygonHierarchy(polygon_point_arr);
      }, false),
      extrudedHeight: 0,  // 多边体的高度(多边形拉伸高度)
      height: 10,  // 多边形离地高度
      material: Cesium.Color.RED.withAlpha(0.5),
    },
  });
}

//绘制结果多边形
function draw_polygon() {
  // 删除最后一个动态添加的点,如果鼠标没移动,最后一个和倒数第二个是一样的,所以也要删除
  polygon_point_arr.pop();
  // 三个点以上才能绘制成多边形
  if (polygon_point_arr.length >= 3) {
    let polygon_point_entity = viewer.entities.add({
      polygon: {
        hierarchy: polygon_point_arr,
        extrudedHeight: 0,  // 多边体的高度(多边形拉伸高度)
        height: 10,  // 多边形离地高度
        material: Cesium.Color.RED.withAlpha(0.5),
        outlineColor: Cesium.Color.RED,
        outlineWidth: 2
      },
    });
    // 坐标转换--这里可以输出所有点位坐标,不需要就删除了
    // polygon_point_arr.forEach(val => {
    //   let polyObj = {}
    //   let cartographic = viewer.scene.globe.ellipsoid.cartesianToCartographic(val)
    //   polyObj.lon = Cesium.Math.toDegrees(cartographic.longitude)
    //   polyObj.lat = Cesium.Math.toDegrees(cartographic.latitude)
    //   point_arr.push([polyObj.lon, polyObj.lat])
    // })
    // return point_arr;
  } else {
    return
  }
}

在这里插入图片描述

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐