# 思路

  • 绘制多边形:
    当点击 "绘制多边形" 时,在屏幕上依次点击多个点来定义多边形的顶点。
    每次点击创建一个序号,点击两个点以上时,会在绘制点之间生成生成线并且计算出距离,用户最少需要选择三个点才能绘制多边形。
    双击右键绘制完成,生成矩形区域,并在矩形的中心添加一个标签,显示 "标签内容"。
    所有绘制的点、线、实体、都会被保存在 entities 数组中,方便销毁
  • 绘制圆形:
    当点击 "绘制圆形" 时,用户可以在屏幕上选择一个点作为圆形的中心,第二个点为圆形区域半径,右键点击后生成圆形区域

# 效果

  • 矩形效果

  • 圆形效果

# 示例

pt
<template>
  <div>
    <span @click="drawClick">绘制多边形</span>
    <span @click="drawCircleClick">绘制圆形</span>
  </div>
</template>
<script>
// 绘制的空域
let polygonEntity = null;
let viewer;
let entities = [];
let positions = [];
let centerPositionEntity = null;
export default {
  name: "AirspaceMgEdit",
  data() {
    return {
      // 空域类型
      airSpaceTypeList: [],
      leftClickHandler: null,
    };
  },
  mounted() {
    viewer = window.viewer;
  },
  methods: {
    // 双击右键绘制矩形
    handleRightDoubleClick() {
      if (positions.length < 3) {
        return this.$message.warning("请最少选择三个点");
      }
      // 取消事件监听
      this.removeInputAction();
      // 添加连线,形成闭合区域,
      if (positions.length > 2) {
        polygonEntity = viewer.entities.add({
          polygon: {
            hierarchy: positions,
            material: Cesium.Color.fromCssColorString("#ff0000"),
          },
        });
        const centerPosition =
          Cesium.BoundingSphere.fromPoints(positions).center;
        centerPositionEntity = viewer.entities.add({
          position: centerPosition,
          label: {
            text: "区域名称",
            scaleByDistance: new Cesium.NearFarScalar(800, 2.0, 900, 0.6),
            scale: 0.8,
            verticalOrigin: Cesium.VerticalOrigin.CENTER, // 垂直方向居中对齐
            pixelOffset: new Cesium.Cartesian2(), // 文本偏移量
          },
        });
        this.createAfterPolyline();
        entities.push(polygonEntity);
        entities.push(centerPositionEntity);
      }
      // 创建矩形最后一条边
      this.createAfterPolyline();
    },
    drawCircleClick() {
      this.removeInputAction();
      this.clearMarker();
      this.$message.success("请点击选择第一个点");
      const _this = this;
      this.leftClickHandler = viewer.screenSpaceEventHandler.setInputAction(
        function (event) {
          // 获取鼠标点击的位置信息
          const position = viewer.scene.pickPosition(event.position);
          if (position) {
            // 创建序号点
            _this.creatPoint(position);
          }
          _this.$message.success("请选择第二个点");
          if (positions.length == 2) {
            // 生成原点 - 边的半径线
            _this.createPolyline(position);
            // 生成圆形区域
            _this.createCircle();
            // 清除之前的点击位置和圆形实体
            viewer.screenSpaceEventHandler.removeInputAction(
              Cesium.ScreenSpaceEventType.LEFT_CLICK,
              _this.leftClickHandler
            );
          }
        },
        Cesium.ScreenSpaceEventType.LEFT_CLICK
      );
    },
    // 生成圆形区域
    createCircle() {
      const radius = Cesium.Cartesian3.distance(positions[0], positions[1]);
      const center = positions[0];
      try {
        polygonEntity = viewer.entities.add({
          position: center,
          label: {
            text: "圆形区域",
            scaleByDistance: new Cesium.NearFarScalar(800, 2.0, 900, 0.6),
            scale: 0.8,
            verticalOrigin: Cesium.VerticalOrigin.CENTER, // 垂直方向居中对齐
            pixelOffset: new Cesium.Cartesian2(20, 20), // 文本偏移量
          },
          ellipse: {
            semiMinorAxis: radius,
            semiMajorAxis: radius,
            material: Cesium.Color.fromCssColorString("#1b6ef3"),
            outline: true,
            outlineColor: Cesium.Color.WHITE,
          },
        });
        entities.push(polygonEntity);
      } catch (error) {
        console.log(error);
      }
    },
    // 创建矩形 
    drawClick() {
      const _this = this;
      // 点击事件处理函数
      this.leftClickHandler = viewer.screenSpaceEventHandler.setInputAction(
        function (e) {
          // 获取点击位置的地理坐标
          const position = viewer.scene.pickPosition(e.position);
          if (position) {
            _this.creatPoint(position);
            _this.createPolyline(position);
          }
        },
        Cesium.ScreenSpaceEventType.LEFT_CLICK
      );
      var rightClickTimer; // 计时器用于判断双击事件
      var isRightDoubleClick = false; // 标记是否为右键双击事件
      this.rightClickHandler = viewer.screenSpaceEventHandler.setInputAction(
        function (click) {
          // 判断是否为右击事件
          if (click.button === Cesium.ScreenSpaceEventType.RIGHT_BUTTON) {
            if (rightClickTimer) {
              // 如果计时器已经存在,则表示已经进行了一次右击
              // 此次右击为双击事件
              clearTimeout(rightClickTimer);
              isRightDoubleClick = true;
              _this.handleRightDoubleClick();
            } else {
              // 否则,启动计时器等待一段时间判断是否为双击事件
              rightClickTimer = setTimeout(function () {
                if (!isRightDoubleClick) {
                  // 如果计时器结束后仍然没有触发双击事件,则为右击事件
                }
                // 重置计时器和标记
                rightClickTimer = undefined;
                isRightDoubleClick = false;
              }, 300); // 调整延时时间以适应您的需求
            }
          }
        },
        Cesium.ScreenSpaceEventType.RIGHT_CLICK
      );
    },
    // 取消事件监听
    removeInputAction() {
      viewer.screenSpaceEventHandler.removeInputAction(
        Cesium.ScreenSpaceEventType.LEFT_CLICK,
        this.leftClickHandler
      );
      viewer.screenSpaceEventHandler.removeInputAction(
        Cesium.ScreenSpaceEventType.RIGHT_CLICK,
        this.rightClickHandler
      );
    },
    createAfterPolyline() {
      if (positions.length > 1) {
        const lineEntity = viewer.entities.add({
          polyline: {
            positions: [positions[0], positions[positions.length - 1]],
            width: 2,
            material: Cesium.Color.RED,
          },
        });
        entities.push(lineEntity);
        // 计算两个点之间的距离
        const distance = Cesium.Cartesian3.distance(
          positions[0],
          positions[positions.length - 1]
        );
        // 创建最后一条边 - 距离
        const center = Cesium.Cartesian3.add(
          positions[positions.length - 1],
          positions[0],
          new Cesium.Cartesian3()
        );
        // 创建最后一条边 - 距离计算线的中心位置
        const newcenter = Cesium.Cartesian3.divideByScalar(center, 2, center);
        // 创建 Label 标签来显示距离
        var labelEntity = viewer.entities.add({
          position: newcenter,
          label: {
            text: distance.toFixed(2) + "m",
            font: "18px sans-serif",
            fillColor: Cesium.Color.WHITE,
            outlineColor: Cesium.Color.BLACK,
            outlineWidth: 2,
            style: Cesium.LabelStyle.FILL_AND_OUTLINE,
            pixelOffset: new Cesium.Cartesian2(0, -20),
          },
        });
        entities.push(labelEntity);
      }
    },
    // 生成序号
    creatPoint(position) {
      // 创建 点
      const pointEntity = viewer.entities.add({
        position: position,
        point: {
          pixelSize: 20,
          color: Cesium.Color.RED,
          outlineColor: Cesium.Color.WHITE,
          outlineWidth: 2,
        },
        label: {
          text: (positions.length + 1).toString(),
          scale: 0.5,
          font: "bold 24px Microsoft YaHei",
          fillColor: Cesium.Color.WHITE,
          horizontalOrigin: Cesium.VerticalOrigin.CENTER,
          verticalOrigin: Cesium.VerticalOrigin.CENTER,
          disableDepthTestDistance: Number.POSITIVE_INFINITY,
          showBackground: false,
          outlineWidth: 0,
        },
      });
      entities.push(pointEntity);
      positions.push(position);
    },
    // 创建线
    createPolyline(position) {
      // 添加线
      if (positions.length > 1) {
        var lineEntity = viewer.entities.add({
          polyline: {
            positions: [positions[positions.length - 2], position],
            width: 2,
            material: Cesium.Color.RED,
          },
        });
        entities.push(lineEntity);
        // 计算两个点之间的距离
        const distance = Cesium.Cartesian3.distance(
          position,
          positions[positions.length - 2]
        );
        // 计算线的中心位置
        const center = Cesium.Cartesian3.add(
          positions[positions.length - 2],
          position,
          new Cesium.Cartesian3()
        );
        const newcenter = Cesium.Cartesian3.divideByScalar(center, 2, center);
        // 创建 Label 标签来显示距离
        var labelEntity = viewer.entities.add({
          position: newcenter,
          label: {
            text: distance.toFixed(2) + "m",
            font: "18px sans-serif",
            fillColor: Cesium.Color.WHITE,
            outlineColor: Cesium.Color.BLACK,
            outlineWidth: 2,
            style: Cesium.LabelStyle.FILL_AND_OUTLINE,
            pixelOffset: new Cesium.Cartesian2(0, -20),
          },
        });
        entities.push(labelEntity);
      }
    },
        // 清除区域数据
        clearMarker() {
      if (entities) {
        for (let i = 0; i < entities.length; i++) {
          const element = entities[i];
          viewer.entities.remove(element);
        }
        entities = [];
        positions = [];
        // 绘制的空域
        polygonEntity = null;
      }
    },
  },
};
</script>

更新于 阅读次数

请我喝[茶]~( ̄▽ ̄)~*

温凯 微信支付

微信支付

温凯 支付宝

支付宝