cesium-添加点线面可以动可编辑

使用

const drawEntities = new CesiumEntityDraw(viewer!, {});
 drawEntities.startDraw('需要绘制的类型');

CesiumEntityDraw.ts文件

import Cesium from 'cesium';
import CesiumEntityEdit from './entityMove';
class CesiumEntityDraw {
  private viewer: any;
  private config: any;
  private infoDetail: any;
  private handler: any;
  private entityEdit: any;
  constructor(
    viewer: Cesium.Viewer,
    config: { borderColor?: Cesium.Color; borderWidth?: number; material?: Cesium.Color }
  ) {
    /**cesium实例对象 */
    this.viewer = viewer;
    this.entityEdit = new CesiumEntityEdit(viewer, {});
    /**绘制要素的相关配置
       * 默认配置
       * {
          borderColor: Cesium.Color.BLUE,  边框颜色
          borderWidth: 2, 边框宽度
          material: Cesium.Color.GREEN.withAlpha(0.5),填充材质
      }
      */
    this.config = config || {
      borderColor: Cesium.Color.BLUE,
      borderWidth: 2
      // material: Cesium.Color.GREEN.withAlpha(0.5),
    };
    /**存贮绘制的数据 坐标 */
    this.infoDetail = {
      point: [],
      line: [],
      rectangle: [],
      circle: [],
      planeSelf: []
    };
    this.handler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas);
  }
  startDraw(type: string) {
    switch (type) {
      case 'point':
        this.drawPoint();
        break;
      case 'rectangle':
        this.drawRectangle();
        break;
      case 'circle':
        this.drawCircle();
        break;
      case 'polygon':
        this.drawPolygon();
        break;
      case 'line':
        this.drawLine();
        break;
      default:
        this.drawPoint();
        break;
    }
    this.entityEdit.start();
  }
  /*******
   * @function: function
   * @return {*}
   * @description: 绘制点数据
   */
  drawPoint() {
    this.stopDraw();
    // 设置鼠标样式为crosshair
    document.body.style.cursor = 'crosshair';
    this.handler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas);
    this.handler.setInputAction((click: { position: any }) => {
      /**点击位置笛卡尔坐标 */
      const cartesian = this.viewer.camera.pickEllipsoid(
        click.position,
        this.viewer.scene.globe.ellipsoid
      );
      /**笛卡尔转弧度坐标 */
      const cartographic = Cesium.Cartographic.fromCartesian(
        cartesian,
        this.viewer.scene.globe.ellipsoid,
        new Cesium.Cartographic()
      );
      /**点击位置经度 */
      const lng = Cesium.Math.toDegrees(cartographic.longitude);
      /**点击位置维度 */
      const lat = Cesium.Math.toDegrees(cartographic.latitude);
      /**实体的唯一标注 */
      const id = new Date().getTime();
      this.viewer.entities.add({
        position: Cesium.Cartesian3.fromDegrees(lng, lat, 0),
        name: 'point',
        id: id,
        point: {
          color: Cesium.Color.BLUE,
          pixelSize: 13,
          outlineColor: Cesium.Color.WHITE,
          outlineWidth: 1
        }
      });
      this.infoDetail.point.push({ id: id, position: [lng, lat] });
    }, Cesium.ScreenSpaceEventType.LEFT_CLICK);

    this.handler.setInputAction((click: any) => {
      this.stopDraw();
      // 添加操作完成后恢复鼠标样式为默认箭头
      document.body.style.cursor = 'default';
    }, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
  }
  /*******
   * @function: function
   * @description: 绘制矩形区域
   */
  drawRectangle() {
    this.stopDraw();
    // 设置鼠标样式为crosshair
    document.body.style.cursor = 'crosshair';
    const positions: any = [];
    let rectangle = null;
    const canvas = this.viewer.scene.canvas;
    this.handler = new Cesium.ScreenSpaceEventHandler(canvas);
    this.handler.setInputAction((click: { position: any }) => {
      if (positions.length) return;
      const cartesian = this.getCatesian3FromPX(click.position);
      positions.push(cartesian, cartesian);
      rectangle = this.viewer.entities.add({
        name: 'rectangle',
        rectangle: {
          coordinates: new Cesium.CallbackProperty(() => {
            const obj = Cesium.Rectangle.fromCartesianArray(positions);
            return obj;
          }, false),
          height: 0.1,
          material: this.config.material,
          zIndex: 100
        }
      });
      this.handler.setInputAction((move: { endPosition: any }) => {
        const cartesian = this.getCatesian3FromPX(move.endPosition);
        if (rectangle) {
          positions[positions.length - 1] = cartesian;
        }
      }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
    }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
    this.handler.setInputAction((click: any) => {
      this.stopDraw();
      // 添加操作完成后恢复鼠标样式为默认箭头
      document.body.style.cursor = 'default';
    }, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
  }
  /*******
   * @function: function
   * @description: 绘制矩形区域
   */
  drawRectangleByPolygon() {
    this.stopDraw();
    // 设置鼠标样式为crosshair
    document.body.style.cursor = 'crosshair';
    /**
     * 矩形四点坐标
     */
    let westSouthEastNorth: number[] = [];
    /**实体的唯一标注 */
    let id: any = null;
    /**地图点击对象 */
    this.handler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas);
    this.handler.setInputAction((click: { position: any }) => {
      this.viewer.scene.screenSpaceCameraController.enableRotate = false; //锁定相机
      /**点击位置笛卡尔坐标 */
      const cartesian = this.viewer.camera.pickEllipsoid(
        click.position,
        this.viewer.scene.globe.ellipsoid
      );
      /**笛卡尔转弧度坐标 */
      const cartographic = Cesium.Cartographic.fromCartesian(
        cartesian,
        this.viewer.scene.globe.ellipsoid,
        new Cesium.Cartographic()
      );
      /**点击位置经度 */
      const lng1 = Cesium.Math.toDegrees(cartographic.longitude);
      /**点击位置维度 */
      const lat1 = Cesium.Math.toDegrees(cartographic.latitude);
      /**边框坐标 */
      westSouthEastNorth = [lng1, lat1];
      id = new Date().getTime();
      if (westSouthEastNorth) {
        this.handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK);
      }
      /**面实例对象 */
      this.viewer.entities.add({
        name: 'rectangle',
        id: id,
        polygon: {
          hierarchy: new Cesium.CallbackProperty(function () {
            return {
              positions: Cesium.Cartesian3.fromDegreesArray(westSouthEastNorth)
            };
          }, false),
          height: 0,
          // 填充的颜色,withAlpha透明度
          material: this.config.material,
          // 是否被提供的材质填充
          fill: true,
          // 是否显示
          show: true
        }
        // polyline: {
        //   positions: new Cesium.CallbackProperty(function() {
        //     return Cesium.Cartesian3.fromDegreesArray(westSouthEastNorth);
        //   }),
        //   material: this.config.borderColor,
        //   width: this.config.borderWidth,
        //   zIndex: 1
        // }
      });
      this.handler.setInputAction((move: { endPosition: any }) => {
        const cartesian = this.viewer.camera.pickEllipsoid(
          move.endPosition,
          this.viewer.scene.globe.ellipsoid
        );
        const cartographic = Cesium.Cartographic.fromCartesian(
          cartesian,
          this.viewer.scene.globe.ellipsoid,
          new Cesium.Cartographic()
        );
        const lng = Cesium.Math.toDegrees(cartographic.longitude);
        const lat = Cesium.Math.toDegrees(cartographic.latitude);

        westSouthEastNorth = [lng1, lat1, lng1, lat, lng, lat, lng, lat1, lng1, lat1];
      }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
    }, Cesium.ScreenSpaceEventType.LEFT_CLICK);

    this.handler.setInputAction(() => {
      this.stopDraw();
      // 添加操作完成后恢复鼠标样式为默认箭头
      document.body.style.cursor = 'default';
      this.infoDetail.rectangle.push({ id: id, position: westSouthEastNorth });
    }, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
  }
  /*******
   * @function: function
   * @description: 绘制圆形区域
   * @return {*}
   */
  drawCircle() {
    this.stopDraw();
    // 设置鼠标样式为crosshair
    document.body.style.cursor = 'crosshair';
    /**实体的唯一标注 */
    let id: any = null;

    /**圆半径 */
    let radius: number = 0;
    /**圆心 */
    let lngLat: any = [];
    /**鼠标事件 */
    this.handler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas);
    this.handler.setInputAction((click: { position: any }) => {
      id = new Date().getTime();
      const cartesian = this.viewer.camera.pickEllipsoid(
        click.position,
        this.viewer.scene.globe.ellipsoid
      );
      const cartographic = Cesium.Cartographic.fromCartesian(
        cartesian,
        this.viewer.scene.globe.ellipsoid,
        new Cesium.Cartographic()
      );
      const lng = Cesium.Math.toDegrees(cartographic.longitude);
      const lat = Cesium.Math.toDegrees(cartographic.latitude);
      lngLat = [lng, lat];
      const entity = this.viewer.entities.add({
        position: new Cesium.CallbackProperty(function () {
          return Cesium.Cartesian3.fromDegrees(lng, lat);
        }, false),
        name: 'circle',
        id: id,
        ellipse: {
          height: 0,
          outline: true,
          material: this.config.material,
          outlineColor: this.config.borderColor,
          outlineWidth: this.config.borderWidth
        }
      });
      entity.ellipse.semiMajorAxis = new Cesium.CallbackProperty(function () {
        return radius;
      }, false);
      entity.ellipse.semiMinorAxis = new Cesium.CallbackProperty(function () {
        return radius;
      }, false);

      if (lngLat) {
        this.handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK);
      }
      this.handler.setInputAction((move: { endPosition: any }) => {
        const cartesian2 = this.viewer.camera.pickEllipsoid(
          move.endPosition,
          this.viewer.scene.globe.ellipsoid
        );
        radius = Cesium.Cartesian3.distance(cartesian, cartesian2);
      }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
    }, Cesium.ScreenSpaceEventType.LEFT_CLICK);

    this.handler.setInputAction(() => {
      this.infoDetail.circle.push({ id: id, center: lngLat, radius: radius });
      this.stopDraw();
      // 添加操作完成后恢复鼠标样式为默认箭头
      document.body.style.cursor = 'default';
    }, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
  }
  /*******
   * @function: function
   * @description: 自定义区域绘制
   */
  drawPolygon() {
    this.stopDraw();
    // 设置鼠标样式为crosshair
    document.body.style.cursor = 'crosshair';
    /**实体的唯一标注 */
    const id = new Date().getTime();
    /**记录拐点坐标 */
    const positions: any = [];
    /**记录返回结果 */
    const codeInfo: any = [];
    /**面的hierarchy属性 */
    const polygon = new Cesium.PolygonHierarchy();
    const _polygonEntity: any = new Cesium.Entity();
    /**面对象配置 */
    let polyObj = null;
    this.handler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas);
    // left
    this.handler.setInputAction((movement: { position: any }) => {
      const cartesian = this.viewer.camera.pickEllipsoid(
        movement.position,
        this.viewer.scene.globe.ellipsoid
      );
      const cartographic = Cesium.Cartographic.fromCartesian(
        cartesian,
        this.viewer.scene.globe.ellipsoid,
        new Cesium.Cartographic()
      );
      const lng = Cesium.Math.toDegrees(cartographic.longitude);
      const lat = Cesium.Math.toDegrees(cartographic.latitude);

      if (cartesian && cartesian.x) {
        if (positions.length == 0) {
          positions.push(cartesian.clone());
        }
        codeInfo.push([lng, lat]);
        positions.push(cartesian.clone());
        polygon.positions.push(cartesian.clone());
        if (!polyObj) {
          // _polygonEntity.polyline = {
          //   width: this.config.borderWidth,
          //   material: this.config.borderColor,
          //   clampToGround: false
          // };
          // _polygonEntity.polyline.positions = new Cesium.CallbackProperty(
          //   function() {
          //     return positions;
          //   },
          //   false
          // );

          _polygonEntity.polygon = {
            hierarchy: new Cesium.CallbackProperty(function () {
              return polygon;
            }, false),
            zIndex: 100,
            height: 0.1,
            material: Cesium.Color.BLUE.withAlpha(0.8),
            clampToGround: false
          };
          _polygonEntity.name = 'polygon';

          _polygonEntity._id = id;
          polyObj = this.viewer.entities.add(_polygonEntity);
        }
      }
    }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
    // mouse
    this.handler.setInputAction((movement: { endPosition: any }) => {
      const cartesian = this.viewer.camera.pickEllipsoid(
        movement.endPosition,
        this.viewer.scene.globe.ellipsoid
      );
      const cartographic = Cesium.Cartographic.fromCartesian(
        cartesian,
        this.viewer.scene.globe.ellipsoid,
        new Cesium.Cartographic()
      );
      const lng = Cesium.Math.toDegrees(cartographic.longitude);
      const lat = Cesium.Math.toDegrees(cartographic.latitude);

      if (positions.length >= 0) {
        if (cartesian && cartesian.x) {
          positions.pop();
          positions.push(cartesian);
          polygon.positions.pop();
          polygon.positions.push(cartesian);
          codeInfo.pop();
          codeInfo.push([lng, lat]);
        }
      }
    }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);

    // right
    this.handler.setInputAction((movement: any) => {
      this.stopDraw();
      // 添加操作完成后恢复鼠标样式为默认箭头
      document.body.style.cursor = 'default';
      this.infoDetail.planeSelf.push({ id: id, positions: codeInfo });
      positions.push(positions[0]);
    }, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
  }

  /*******
   * @function: function
   * @return {*}
   * @description: 绘制线段
   */
  drawLine() {
    this.stopDraw();
    // 设置鼠标样式为crosshair
    document.body.style.cursor = 'crosshair';
    /**实体的唯一标注 */
    const id = new Date().getTime();
    /**记录拐点坐标 */
    const positions: any = [],
      /**记录返回结果 */
      codeInfo: any = [],
      /**面的hierarchy属性 */
      polygon = new Cesium.PolygonHierarchy(),
      _polygonEntity: any = new Cesium.Entity();
    /**面对象配置 */
    let polyObj = null;
    this.handler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas);
    // left
    this.handler.setInputAction((movement: { position: any }) => {
      const cartesian = this.viewer.camera.pickEllipsoid(
        movement.position,
        this.viewer.scene.globe.ellipsoid
      );
      const cartographic = Cesium.Cartographic.fromCartesian(
        cartesian,
        this.viewer.scene.globe.ellipsoid,
        new Cesium.Cartographic()
      );
      const lng = Cesium.Math.toDegrees(cartographic.longitude);
      const lat = Cesium.Math.toDegrees(cartographic.latitude);

      if (cartesian && cartesian.x) {
        if (positions.length == 0) {
          positions.push(cartesian.clone());
        }
        codeInfo.push([lng, lat]);
        positions.push(cartesian.clone());
        polygon.positions.push(cartesian.clone());
        if (!polyObj) {
          _polygonEntity.polyline = {
            width: 4,
            material: Cesium.Color.BLUE.withAlpha(0.8),
            clampToGround: true
          };
          _polygonEntity.polyline.positions = new Cesium.CallbackProperty(function () {
            return positions;
          }, false);
          _polygonEntity.name = 'line';
          _polygonEntity._id = id;

          polyObj = this.viewer.entities.add(_polygonEntity);
          // this.entityEdit = new CesiumEntityEdit(this.viewer, polyObj);
        }
      }
    }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
    // mouse
    this.handler.setInputAction((movement: { endPosition: any }) => {
      const cartesian = this.viewer.camera.pickEllipsoid(
        movement.endPosition,
        this.viewer.scene.globe.ellipsoid
      );
      const cartographic = Cesium.Cartographic.fromCartesian(
        cartesian,
        this.viewer.scene.globe.ellipsoid,
        new Cesium.Cartographic()
      );
      const lng = Cesium.Math.toDegrees(cartographic.longitude);
      const lat = Cesium.Math.toDegrees(cartographic.latitude);

      if (positions.length >= 0) {
        if (cartesian && cartesian.x) {
          positions.pop();
          positions.push(cartesian);
          codeInfo.pop();
          codeInfo.push([lng, lat]);
        }
      }
    }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);

    // right
    this.handler.setInputAction((movement: any) => {
      this.infoDetail.line.push({ id: id, positions: codeInfo });
      this.stopDraw();
      // 添加操作完成后恢复鼠标样式为默认箭头
      document.body.style.cursor = 'default';
    }, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
  }
  /*******
   * @function: function
   * @description: 移除实体对象
   * @return {*}
   */
  removeEntity() {
    this.handler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas);
    this.handler.setInputAction((move: { endPosition: any }) => {
      /**实体对象信息  {id:entities,primitive:。。} */
      const pick = this.viewer.scene.pick(move.endPosition);
      this.entityEdit.removeStretchPoint();

      if (pick && pick.id && pick.id.id) {
        document.body.style.cursor = 'pointer';
        this.handler.setInputAction((click: any) => {
          let newPoint: any;
          switch (pick.id.name) {
            case 'point':
              /**删除某一条数据 */
              newPoint = this.infoDetail.point.filter(
                (item: { id: any }) => item.id != pick.id._id
              );
              this.infoDetail.point = newPoint;
              break;
            case 'line':
              /**删除某一条数据 */
              newPoint = this.infoDetail.line.filter((item: { id: any }) => item.id != pick.id._id);
              this.infoDetail.line = newPoint;
              break;
            case 'rectangle':
              /**删除某一条数据 */
              newPoint = this.infoDetail.rectangle.filter(
                (item: { id: any }) => item.id != pick.id._id
              );
              this.infoDetail.rectangle = newPoint;
              break;

            case 'planeSelf':
              /**删除某一条数据 */
              newPoint = this.infoDetail.planeSelf.filter(
                (item: { id: any }) => item.id != pick.id._id
              );
              this.infoDetail.planeSelf = newPoint;
              break;
            case 'circle':
              /**删除某一条数据 */
              newPoint = this.infoDetail.circle.filter(
                (item: { id: any }) => item.id != pick.id._id
              );
              this.infoDetail.circle = newPoint;
              break;
            default:
              break;
          }
          this.viewer.entities.remove(pick.id);
        }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
      } else {
        document.body.style.cursor = 'default';
      }
    }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
  }
  /**
   *
   */
  removeAllEntity() {
    this.entityEdit.removeStretchPoint();
    Object.keys(this.infoDetail).map((name) => {
      this.infoDetail[name].map((item: { id: any }) => {
        this.viewer.entities.removeById(item.id);
      });
    });
  }
  /*******
   * @function: function
   * @return {*}
   * @description: 返回绘制数据
   */
  backInfoDetail() {
    return this.infoDetail;
  }
  stopDraw() {
    this.handler.removeInputAction(Cesium.ScreenSpaceEventType.RIGHT_CLICK);
    this.handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK);
    // this.handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_DOWN);
    // this.handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_UP);
    this.handler.removeInputAction(Cesium.ScreenSpaceEventType.MOUSE_MOVE);
    // this.handler && this.handler.destroy();
    // this.entityEdit.stop();
  }
  stopEdit() {
    this.entityEdit.stop();
  }
  getMousePostion(position: any) {
    if (!position) return;
    /**点击位置笛卡尔坐标 */
    const cartesian = this.viewer.camera.pickEllipsoid(position, this.viewer.scene.globe.ellipsoid);
    /**笛卡尔转弧度坐标 */
    const cartographic = Cesium.Cartographic.fromCartesian(
      cartesian,
      this.viewer.scene.globe.ellipsoid,
      new Cesium.Cartographic()
    );
    /**点击位置经度 */
    const lng1 = Cesium.Math.toDegrees(cartographic.longitude);
    /**点击位置维度 */
    const lat1 = Cesium.Math.toDegrees(cartographic.latitude);
    return [lng1, lat1];
  }
  getCatesian3FromPX(px: any) {
    const ray = this.viewer.camera.getPickRay(px);
    if (!ray) return null;
    const cartesian = this.viewer.scene.globe.pick(ray, this.viewer.scene);
    return cartesian;
  }
}
export default CesiumEntityDraw;

CesiumEntityEdit .ts文件

/**
 * cesium 实体编辑:拖拽、旋转、修改
 */
import * as turf from '@turf/turf';
import Cesium from 'cesium';
class CesiumEntityEdit {
  private viewer: any;
  private options: any;
  private selectedEntity: any; // 被选择的实体对象
  private handler: any; // 事件捕获
  private mouseStatus: any; // 当前鼠标状态 LEFT_DOWN:左键按下;LEFT_UP: 左键抬起;MOVE: 鼠标移动
  private coordinates: any; // 当前被选中的实体组成的点集合
  private entityType: any; // 当前被选中实体的类型
  private entityCenter: any; // 多边形中心点
  private strecthPointIds: any; // 拉伸点Id集合
  private strecthObj: any; // 被选中的拉伸点
  private isStrecth: any; // 当前是否点击拉伸点
  private strecthObjId_index: any;
  constructor(viewer: any, options: {} | null) {
    this.viewer = viewer;
    this.options = options || {};
    this.selectedEntity = null; // 被选择的实体对象
    this.handler = null; // 事件捕获
    this.mouseStatus = null; // 当前鼠标状态 LEFT_DOWN:左键按下;LEFT_UP: 左键抬起;MOVE: 鼠标移动
    this.coordinates = []; // 当前被选中的实体组成的点集合
    this.entityType = 'polygon'; // 当前被选中实体的类型
    this.entityCenter = []; // 多边形中心点
    this.strecthPointIds = []; // 拉伸点Id集合
    this.strecthObj = null; // 被选中的拉伸点
    this.isStrecth = false; // 当前是否点击拉伸点
  }
  start() {
    this.handler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas);
    // 监听鼠标左键按下事件
    this.handler.setInputAction(
      (e: any) => this.handleLeftDown(e),
      Cesium.ScreenSpaceEventType.LEFT_DOWN
    );
    // 监听鼠标左键抬起事件
    this.handler.setInputAction(
      (e: any) => this.handleLeftUp(e),
      Cesium.ScreenSpaceEventType.LEFT_UP
    );
    // 监听鼠标移动事件
    this.handler.setInputAction(
      (e: any) => this.handleMouseMove(e),
      Cesium.ScreenSpaceEventType.MOUSE_MOVE
    );
  }
  handleLeftDown(e: { position: any }) {
    // 更新鼠标状态
    this.mouseStatus = 'LEFT_DOWN';
    // 获取当前点击位置的实体对象
    const obj = this.viewer.scene.pick(e.position);
    if (!obj) {
      this.strecthObj = null;
      this.selectedEntity = null;
      this.viewer.scene.screenSpaceCameraController.enableRotate = true;
      this.removeStretchPoint();
      return;
    }
    if (obj && obj.id.name === 'stretch_point') {
      const index = this.strecthPointIds.findIndex((p: any) => p === obj.id.id);
      this.strecthObjId_index = index;
      this.strecthObj = obj;
      this.isStrecth = true;
    } else {
      this.removeStretchPoint();
      this.strecthObj = null;
      this.selectedEntity = obj;
    }

    //锁定相机
    this.viewer.scene.screenSpaceCameraController.enableRotate = false;
    if (obj.id.polygon) {
      this.entityType = 'polygon';
      this.coordinates = this.selectedEntity.id.polygon.hierarchy.getValue().positions;
      this.entityCenter = this.getEntityCenter();
      this.addStrecthPoint(this.selectedEntity.id.polygon);
    }
    if (obj.id.rectangle) {
      this.entityType = 'rectangle';
      this.coordinates = this.selectedEntity.id.rectangle.coordinates.getValue();
      this.addStrecthPoint(this.selectedEntity.id.rectangle);
    }
    if (obj.id.point) {
      this.entityType = 'point';
    }
    if (obj.id.polyline) {
      this.entityType = 'polyline';

      this.coordinates = this.selectedEntity.id.polyline.positions.getValue();
      // this.entityCenter = this.getEntityCenter()
      this.addStrecthPoint(this.selectedEntity.id.polyline);
    }
  }
  handleLeftUp(e: any) {
    // 更新鼠标状态
    this.mouseStatus = 'LEFT_UP';
  }
  handleMouseMove(e: any) {
    if (this.mouseStatus === 'LEFT_DOWN' && this.selectedEntity) {
      // 拖拽实体
      if (this.strecthObj) {
        this.handleDrag(e, this.strecthObj);
        this.handleStretch(this.selectedEntity);
        return;
      }
      this.removeStretchPoint();
      this.handleDrag(e, this.selectedEntity);
    }
  }
  /**
   * 拖拽移动实体
   * @param {*} e
   */
  handleDrag(
    e: { startPosition: any; endPosition: any },
    selectedEntity: {
      id: {
        position: Cesium.CallbackProperty;
        polygon: { hierarchy: Cesium.CallbackProperty };
        rectangle: { coordinates: Cesium.CallbackProperty };
        polyline: { positions: Cesium.CallbackProperty };
      };
    }
  ) {
    if (!selectedEntity) return;
    const coordinates = this.coordinates;
    // 获取开始位置坐标
    const startPosition = this.viewer.scene.camera.pickEllipsoid(
      e.startPosition,
      this.viewer.scene.globe.ellipsoid
    );
    // 获取结束位置坐标
    const endPosition = this.viewer.scene.camera.pickEllipsoid(
      e.endPosition,
      this.viewer.scene.globe.ellipsoid
    );
    selectedEntity.id.position = new Cesium.CallbackProperty(function () {
      return endPosition;
    }, false);
    const changed_x = endPosition.x - startPosition.x;
    const changed_y = endPosition.y - startPosition.y;
    const changed_z = endPosition.z - startPosition.z;
    if (this.entityType === 'point') {
      const ray = this.viewer.camera.getPickRay(e.endPosition);
      const cartesian = this.viewer.scene.globe.pick(ray, this.viewer.scene);
      selectedEntity.id.position = new Cesium.CallbackProperty(() => {
        return cartesian;
      }, false);
    }
    if (this.entityType === 'polygon' || this.entityType === 'polyline') {
      const currentsPoint: any = [];
      for (let i = 0; i < coordinates.length; i++) {
        coordinates[i].x = coordinates[i].x + changed_x;
        coordinates[i].y = coordinates[i].y + changed_y;
        coordinates[i].z = coordinates[i].z + changed_z;
        currentsPoint.push(coordinates[i]);
      }
      if (this.entityType === 'polygon') {
        selectedEntity.id.polygon.hierarchy = new Cesium.CallbackProperty(() => {
          return { positions: currentsPoint };
        }, false); // 防止闪烁
      } else {
        selectedEntity.id.polyline.positions = new Cesium.CallbackProperty(() => {
          return currentsPoint;
        }, false); // 防止闪烁
      }
    }
    if (this.entityType === 'rectangle') {
      const position_start = startPosition;
      const cartographic_start = Cesium.Cartographic.fromCartesian(position_start);
      const longitude_start = Cesium.Math.toDegrees(cartographic_start.longitude);
      const latitude_start = Cesium.Math.toDegrees(cartographic_start.latitude);

      const position_end = endPosition;
      const cartographic_end = Cesium.Cartographic.fromCartesian(position_end);
      const longitude_end = Cesium.Math.toDegrees(cartographic_end.longitude);
      const latitude_end = Cesium.Math.toDegrees(cartographic_end.latitude);

      const changer_lng = longitude_end - longitude_start;
      const changer_lat = latitude_end - latitude_start;
      coordinates.west = Cesium.Math.toRadians(
        Cesium.Math.toDegrees(coordinates.west) + changer_lng
      );
      coordinates.east = Cesium.Math.toRadians(
        Cesium.Math.toDegrees(coordinates.east) + changer_lng
      );
      coordinates.south = Cesium.Math.toRadians(
        Cesium.Math.toDegrees(coordinates.south) + changer_lat
      );
      coordinates.north = Cesium.Math.toRadians(
        Cesium.Math.toDegrees(coordinates.north) + changer_lat
      );
      selectedEntity.id.rectangle.coordinates = new Cesium.CallbackProperty(() => {
        return coordinates;
      }, false);
    }
  }
  /**
   * 旋转实体
   * @param {*} angle
   */
  handleRotation(angle: number) {
    if (!this.selectedEntity) return;
    // 旋转时清除辅助拉伸的点
    if (this.strecthPointIds.length) {
      this.removeStretchPoint();
    }
    if (this.entityType === 'rectangle') {
      // 旋转图形
      this.selectedEntity.id.rectangle.rotation = new Cesium.CallbackProperty(function () {
        return angle;
      }, false);
      // 旋转图形材质
      this.selectedEntity.id.rectangle.stRotation = new Cesium.CallbackProperty(function () {
        return angle;
      }, false);
    }
    if (this.entityType === 'polygon') {
      // let previousCoordinates = this.selectedEntity.id.polygon.hierarchy.getValue().positions
      // let coors = this.getWGS84FromDKR(previousCoordinates)
      // console.log(coors)
      // let poly = turf.polygon([coors])
      // let centroid = turf.centroid(poly)
      // let rotatedPoly = turf.transformRotate(poly, angle, { pivot: centroid.geometry.coordinates})
      // let newCoors = rotatedPoly.geometry.coordinates[0]
      // let positions = []
      // newCoors.forEach(item => {
      //  positions.push(item[0], item[1])
      // })
      this.selectedEntity.id.polygon.stRotation = new Cesium.CallbackProperty(function () {
        return Cesium.Math.toRadians(angle);
      }, false);
      // this.selectedEntity.id.polygon.hierarchy = new Cesium.CallbackProperty(function () {
      //  return { positions: Cesium.Cartesian3.fromDegreesArray(positions) }
      // }, false)
    }
  }
  /**
   * 拉伸实体
   */
  handleStretch(selectedEntity: {
    id: {
      polygon: { hierarchy: Cesium.CallbackProperty };
      rectangle: { coordinates: Cesium.CallbackProperty };
      polyline: { positions: Cesium.CallbackProperty };
    };
  }) {
    const positions: any = [];
    // 更新polygon的位置数组
    if (selectedEntity.id.polygon) {
      for (let i = 0; i < this.strecthPointIds.length; i++) {
        const id = this.strecthPointIds[i];
        positions.push(this.viewer.entities.getById(id).position.getValue());
      }
      selectedEntity.id.polygon.hierarchy = new Cesium.CallbackProperty(() => {
        return { positions: positions };
      }, false);
    }
    // 更新polyline的位置数组
    if (selectedEntity.id.polyline) {
      for (let i = 0; i < this.strecthPointIds.length; i++) {
        const id = this.strecthPointIds[i];
        positions.push(this.viewer.entities.getById(id).position.getValue());
      }
      selectedEntity.id.polyline.positions = new Cesium.CallbackProperty(() => {
        return positions;
      }, false);
    }
    // 更新rectangle的位置数组
    if (selectedEntity.id.rectangle) {
      const index = this.strecthPointIds.findIndex((item: any) => item === this.strecthObj.id.id);
      for (let i = 0; i < this.strecthPointIds.length; i++) {
        const id = this.strecthPointIds[i];
        // 矩形由两个对角的点组成的区域,因此先判断用户点击的是哪一个点,即奇偶判断
        if (index % 2 === 0) {
          if (i % 2 === 0) {
            positions.push(this.viewer.entities.getById(id).position.getValue());
          } else {
            // 将另外一半点隐藏
            this.viewer.entities.getById(id).show = false;
          }
        } else {
          if (i % 2 != 0) {
            positions.push(this.viewer.entities.getById(id).position.getValue());
          } else {
            this.viewer.entities.getById(id).show = false;
          }
        }
      }
      selectedEntity.id.rectangle.coordinates = new Cesium.CallbackProperty(() => {
        const obj = Cesium.Rectangle.fromCartesianArray(positions);
        return obj;
      }, false);
    }
  }
  /**
   * 添加拉伸点
   * @param {*} entity
   */
  addStrecthPoint(entity: {
    hierarchy: { getValue: () => { (): any; new (): any; positions: never[] } };
    coordinates: { getValue: () => any };
    positions: { getValue: () => any };
  }) {
    let points = [];
    if (this.entityType === 'polygon') {
      points = entity.hierarchy.getValue().positions;
    } else if (this.entityType === 'rectangle') {
      const rectangle = entity.coordinates.getValue();
      Cesium.Rectangle.subsample(rectangle, Cesium.Ellipsoid.WGS84, rectangle.height, points);
    } else if (this.entityType === 'polyline') {
      points = entity.positions.getValue();
    }
    // const id = new Date().getTime();
    for (const position of points) {
      const point = this.viewer.entities.add({
        name: 'stretch_point',
        position: position,
        // id:new Date().getTime()
        point: {
          color: Cesium.Color.WHITE,
          pixelSize: 10,
          outlineColor: Cesium.Color.BLACK,
          outlineWidth: 1
        }
      });
      this.strecthPointIds.push(point.id);
    }
  }
  /**
   * 清除拉伸点
   */
  removeStretchPoint() {
    for (const id of this.strecthPointIds) {
      this.viewer.entities.removeById(id);
    }
    this.strecthPointIds = [];
    this.strecthObj = null;
    this.isStrecth = false;
  }
  /**
   * 获取多边形图形中心点
   */
  getEntityCenter() {
    const previousCoordinates = this.selectedEntity.id.polygon.hierarchy.getValue().positions;
    const coors = this.getWGS84FromDKR(previousCoordinates);
    coors.push(coors[0]);
    const poly = turf.polygon([coors]);
    const centroid = turf.centroid(poly);

    return centroid.geometry.coordinates;
  }
  /**
   * 将笛卡尔坐标转换成国际坐标
   * @param {*} coors
   * @returns
   */
  getWGS84FromDKR(coors: string | any[]) {
    const newCoors: any = [];
    for (let i = 0; i < coors.length; i++) {
      const coor = coors[i];
      const cartographic = Cesium.Cartographic.fromCartesian(coor);
      const x = Cesium.Math.toDegrees(cartographic.longitude);
      const y = Cesium.Math.toDegrees(cartographic.latitude);
      newCoors.push([x, y]);
    }

    return newCoors;
  }
  stop() {
    this.handler && this.handler.destroy();
    this.removeStretchPoint();
    this.viewer.scene.screenSpaceCameraController.enableRotate = true;
  }
}

export default CesiumEntityEdit;

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值