Newer
Older
KaiFengPC / src / views / gisMapPage / drawFeature.vue
@zhangdeliang zhangdeliang on 23 May 16 KB 初始化项目
<template>
  <div class="drawFeature">
    <div class="drawTool">
      <div class="draToolElement" v-for="(toolElement, index) in drawTool" :key="index">
        <div class="tool" :title="toolElement.name" @click="drawEntity(toolElement.type)">
          <el-image style="width: 90%; height: 90%" :src="toolElement.url" />
        </div>
      </div>
    </div>
  </div>
  <div id="lengthAndArea"></div>
</template>
<script>
import { reactive, toRefs, onBeforeMount, onMounted, nextTick, watch } from 'vue';
import markerPoint from '@/assets/images/gisMap/Frame.png';
import drawCircle from '@/assets/images/gisMap/Frame 16.png';
import measureLength from '@/assets/images/gisMap/juli.png';
import measureArea from '@/assets/images/gisMap/cemian.png';
import clearFeature from '@/assets/images/gisMap/clearJm.png';
import marker from '@/assets/images/gisMap/in.png';
import bus from '@/utils/mitt';
export default {
  components: {},
  props: {},
  setup(props) {
    const allData = reactive({
      drawTool: [
        {
          type: 'point',
          name: '标记',
          url: markerPoint,
        },
        {
          type: 'circle',
          name: '画圆',
          url: drawCircle,
        },
        {
          type: 'polygon',
          name: '测面',
          url: measureArea,
        },
        {
          type: 'polyline',
          name: '测距',
          url: measureLength,
        },
        {
          type: 'clear',
          name: '清除',
          url: clearFeature,
        },
      ],
    });
    const drawEntity = (type, config) => {
      let position = [];
      let tempPoints = [];
      let tempEntities = [];
      let point;
      // 开启深度检测
      newfiberMap.getMap().scene.globe.depthTestAgainstTerrain = true;
      let handler = new Cesium.ScreenSpaceEventHandler(newfiberMap.getMap().canvas);
      switch (type) {
        case 'point':
          // 监听鼠标左键
          handler.setInputAction(function (movement) {
            // 从相机位置通过windowPosition 世界坐标中的像素创建一条射线。返回Cartesian3射线的位置和方向。
            let ray = newfiberMap.getMap().camera.getPickRay(movement.position);
            // 查找射线与渲染的地球表面之间的交点。射线必须以世界坐标给出。返回Cartesian3对象
            position = newfiberMap.getMap().scene.globe.pick(ray, newfiberMap.getMap().scene);
            let ellipsoid = newfiberMap.getMap().scene.globe.ellipsoid;
            let cartographic = ellipsoid.cartesianToCartographic(position);
            let lon = Cesium.Math.toDegrees(cartographic.longitude); // 经度
            let lat = Cesium.Math.toDegrees(cartographic.latitude); // 纬度
            point = drawPoint(position, { image: marker });
            tempEntities.push(point);
          }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
          // 左键双击停止绘制
          handler.setInputAction(function () {
            handler.destroy(); //关闭事件句柄
            handler = null;
          }, Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);
          // 右击单击停止绘制
          handler.setInputAction(function () {
            handler.destroy(); //关闭事件句柄
          }, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
          break;
        case 'circle':
          point = null;
          let lonlatArry = [];
          let circleOptions = {};
          let circleFeature = null;
          let radius;
          handler.setInputAction(function (click) {
            //clearDrawEntities('point');
            //调用获取位置信息的接口
            let ray = newfiberMap.getMap().camera.getPickRay(click.position);
            position = newfiberMap.getMap().scene.globe.pick(ray, newfiberMap.getMap().scene);
            tempPoints.push(position);
            let ellipsoid = newfiberMap.getMap().scene.globe.ellipsoid;
            let cartographic = ellipsoid.cartesianToCartographic(position);
            let lon = Cesium.Math.toDegrees(cartographic.longitude); // 经度
            let lat = Cesium.Math.toDegrees(cartographic.latitude); // 纬度
            let lonlat = [lon, lat];
            if (lonlatArry < 1) {
              lonlatArry.push(lonlat);
              // let tempLength = tempPoints.length;
              //调用绘制点的接口
              point = drawPoint(position, { image: null });
            }
            if (lonlatArry.length > 0) {
              handler.setInputAction(function (movement) {
                clearDrawEntities('circle');
                let ellipsoid_end = newfiberMap.getMap().scene.globe.ellipsoid;
                let cartesian = newfiberMap.getMap().camera.pickEllipsoid(movement.endPosition, ellipsoid_end);
                let cartographic_end = ellipsoid_end.cartesianToCartographic(cartesian);
                let lon_end = Cesium.Math.toDegrees(cartographic_end.longitude); // 经度
                let lat_end = Cesium.Math.toDegrees(cartographic_end.latitude); // 纬度
                radius = turf.distance(turf.point(lonlatArry[0]), turf.point([lon_end, lat_end])) * 1000;
                circleOptions = {
                  position: lonlatArry[0],
                  radius: radius,
                };
                circleFeature = drawCircle(circleOptions);
              }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
            }
          }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
          //双击取消绘制操作
          handler.setInputAction(function (click) {
            let areaCircle = (Math.PI * (radius / 1000) * (radius / 1000)).toFixed(3);
            addLabelInfo(lonlatArry[0], { text: `${areaCircle}km²` });
            let circleJson = turf.circle(lonlatArry[0], radius / 1000);
            console.log('circleJson', circleJson);
            handler.destroy(); //关闭事件句柄
            handler = null;
            lonlatArry = [];
          }, Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);
          break;
        case 'polyline':
          tempEntities = [];
          point = null;
          let lonlatarry = [];
          //鼠标移动事件
          handler.setInputAction(function (movement) {}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
          //左键点击操作
          handler.setInputAction(function (click) {
            //调用获取位置信息的接口
            let ray = newfiberMap.getMap().camera.getPickRay(click.position);
            position = newfiberMap.getMap().scene.globe.pick(ray, newfiberMap.getMap().scene);
            tempPoints.push(position);
            let ellipsoid = newfiberMap.getMap().scene.globe.ellipsoid;
            let cartographic = ellipsoid.cartesianToCartographic(position);
            let lon = Cesium.Math.toDegrees(cartographic.longitude); // 经度
            let lat = Cesium.Math.toDegrees(cartographic.latitude); // 纬度
            let lonlat = [lon, lat];
            lonlatarry.push(lonlat);
            let tempLength = tempPoints.length;
            //调用绘制点的接口
            point = drawPoint(tempPoints[tempPoints.length - 1], { image: null });
            if (tempLength > 1) {
              let pointline = drawPolyline([tempPoints[tempPoints.length - 2], tempPoints[tempPoints.length - 1]]);
            } else {
              // tooltip.innerHTML = "请绘制下一个点,右键结束";
            }
          }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
          //双击取消绘制操作
          handler.setInputAction(function (click) {
            let lineJson = {
              type: 'LineString',
              coordinates: lonlatarry, //获取线的geojson
            };
            let lengthLine = turf.length(lineJson, { units: 'kilometers' }).toFixed(3); //计算路线长度
            // let roadline = {
            //   line: Terraformer.WKT.convert(lineJson),
            //   length: lengthLine,
            // };
            // bus.emit('roadObj', roadline);
            let center = turf.center(lineJson).geometry.coordinates; //计算线的中心点
            addLabelInfo(center, { text: `${lengthLine}km` });
            handler.destroy(); //关闭事件句柄
            handler = null;
          }, Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);
          break;
        case 'polygon':
          point = null;
          let lonlatList = [];
          //鼠标移动事件
          handler.setInputAction(function (movement) {}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
          //左键点击操作
          handler.setInputAction(function (click) {
            //调用获取位置信息的接口
            let ray = newfiberMap.getMap().camera.getPickRay(click.position);
            position = newfiberMap.getMap().scene.globe.pick(ray, newfiberMap.getMap().scene);
            tempPoints.push(position);
            let ellipsoid = newfiberMap.getMap().scene.globe.ellipsoid;
            let cartographic = ellipsoid.cartesianToCartographic(position);
            let lon = Cesium.Math.toDegrees(cartographic.longitude); // 经度
            let lat = Cesium.Math.toDegrees(cartographic.latitude); // 纬度
            let lonlat = [lon, lat];
            lonlatList.push(lonlat);
            let tempLength = tempPoints.length;
            //调用绘制点的接口
            point = drawPoint(position, { image: null });
            //tempEntities.push(point);
            if (tempLength > 1) {
              let pointline = drawPolyline([tempPoints[tempPoints.length - 2], tempPoints[tempPoints.length - 1]]);
              //tempEntities.push(pointline);
            } else {
              // tooltip.innerHTML = "请绘制下一个点,右键结束";
            }
          }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
          //双击取消绘制操作
          handler.setInputAction(function (click) {
            let cartesian = newfiberMap.getMap().camera.pickEllipsoid(click.position, newfiberMap.getMap().scene.globe.ellipsoid);
            if (cartesian) {
              let tempLength = tempPoints.length;
              if (tempLength < 3) {
                alert('请选择3个以上的点再执行闭合操作命令');
              } else {
                //闭合最后一条线
                let pointline = drawPolyline([tempPoints[tempPoints.length - 1], tempPoints[0]]);
                //tempEntities.push(pointline);
                drawPolygon(tempPoints);
                tempEntities.push(tempPoints);
                let polygonJson = {
                  type: 'Polygon',
                  coordinates: [lonlatList], //获取面的geojson
                };
                let areaPolygon = (turf.area(polygonJson) / 1000000).toFixed(3); //计算路线长度
                let center = turf.center(polygonJson).geometry.coordinates; //计算线的中心点
                addLabelInfo(center, { text: `${areaPolygon}km²` });
                handler.destroy(); //关闭事件句柄
                handler = null;
              }
            }
          }, Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);
          break;
        case 'clear':
          clearDrawEntities();
          break;
      }
      function drawPoint(position, config) {
        let config_ = config ? config : {};
        return newfiberMap.getMap().entities.add({
          name: '点几何对象',
          position: position,
          point:
            config_ && config_.image
              ? {}
              : {
                  color: new Cesium.Color.fromCssColorString('rgb(186,24,222)'),
                  pixelSize: 4,
                  outlineColor: new Cesium.Color.fromCssColorString('rgb(186,24,222)'),
                  outlineWidth: 2,
                  disableDepthTestDistance: Number.POSITIVE_INFINITY,
                },
          billboard: {
            show: config_ && config_.image ? true : false,
            image: config_ && config_.image ? config_.image : null,
            width: 30,
            height: 30,
            disableDepthTestDistance: Number.POSITIVE_INFINITY,
            heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
          },
        });
      }
      function drawCircle(options, config_) {
        return newfiberMap.getMap().entities.add({
          name: '圆几何对象',
          position: Cesium.Cartesian3.fromDegrees(options.position[0], options.position[1]),
          ellipse: {
            semiMinorAxis: options.radius, // 半短轴
            semiMajorAxis: options.radius, // 半长轴
            outline: true,
            outlineWidth: config_ && config_.width ? config_.width : 5.0,
            outlineColor: new Cesium.Color.fromCssColorString('rgb(255, 130, 255)'),
            material: new Cesium.Color.fromCssColorString('rgba(166,64,202,0.6)'),
          },
        });
      }
      function drawPolyline(positions, config_) {
        if (positions.length < 1) return;
        let config = config_ ? config_ : {};
        return newfiberMap.getMap().entities.add({
          name: '线几何对象',
          polyline: {
            positions: positions,
            width: config.width ? config.width : 5.0,
            material: new Cesium.PolylineGlowMaterialProperty({
              color: config.color
                ? new Cesium.Color.fromCssColorString(config.color)
                : new Cesium.Color.fromCssColorString('rgb(186,24,222)'),
            }),
            depthFailMaterial: new Cesium.PolylineGlowMaterialProperty({
              color: config.color
                ? new Cesium.Color.fromCssColorString(config.color)
                : new Cesium.Color.fromCssColorString('rgb(186,24,222)'),
            }),
            clampToGround: true,
          },
        });
      }
      function drawPolygon(positions, config_) {
        if (positions.length < 2) return;
        let config = config_ ? config_ : {};
        return newfiberMap.getMap().entities.add({
          name: '面几何对象',
          polygon: {
            hierarchy: positions,
            material: config.color
              ? new Cesium.Color.fromCssColorString(config.color).withAlpha(0.2)
              : new Cesium.Color.fromCssColorString('rgba(166,64,202,0.6)'),
          },
        });
      }
      function addLabelInfo(position, config) {
        let config_ = config ? config : {};
        return newfiberMap.getMap().entities.add({
          name: '几何标注',
          position: Cesium.Cartesian3.fromDegrees(position[0], position[1], 0),
          label: {
            text: config_.text,
            font: '15px sans-serif',
            pixelOffset: new Cartesian2(10, 10),
            disableDepthTestDistance: Number.POSITIVE_INFINITY,
          },
        });
      }
    };
    /**清除绘制
     *
     */
    const clearDrawEntities = type => {
      // 清除之前的实体
      const entitys = newfiberMap.getMap().entities._entities._array;
      let length = entitys.length;
      if (type && type == 'circle') {
        for (let f = length - 1; f >= 0; f--) {
          if (entitys[f]._name && entitys[f]._name === '圆几何对象') {
            newfiberMap.getMap().entities.remove(entitys[f]);
          }
        }
      } else if (type == 'point') {
        for (let f = length - 1; f >= 0; f--) {
          if (entitys[f]._name && entitys[f]._name === '点几何对象') {
            newfiberMap.getMap().entities.remove(entitys[f]);
          }
        }
      } else {
        // 倒叙遍历防止实体减少之后entitys[f]不存在
        for (let f = length - 1; f >= 0; f--) {
          if (
            entitys[f]._name &&
            (entitys[f]._name === '点几何对象' ||
              entitys[f]._name === '线几何对象' ||
              entitys[f]._name === '面几何对象' ||
              entitys[f]._name === '圆几何对象' ||
              entitys[f]._name === '几何标注')
          ) {
            newfiberMap.getMap().entities.remove(entitys[f]);
          }
        }
      }
    };
    //地图移动,更新标注位置
    onBeforeUnmount(() => {
      bus.off('roadObj');
    });
    return {
      ...toRefs(allData),
      drawEntity,
      clearDrawEntities,
    };
  },
};
</script>
<style lang="scss">
.drawFeature {
  display: flex;
  position: absolute;
  right: 470px;
  top: 20px;
  z-index: 20;
  background: transparent;
  .draToolElement {
    width: 35px;
    height: 35px;
    margin: 10px;
    cursor: pointer;
  }
}
#lengthAndArea {
  position: absolute;
  .featureChild {
    position: absolute;
    z-index: 110;
  }
}
</style>