jihongshun
3 天以前 b1ec910ae7c0c19f6afabafd3cb75722a6b059dd
src/utils/components/init-map.vue
@@ -4,17 +4,42 @@
    <div ref="cesiumContainer" id="cesiumContainer"></div>
    <!-- 相机视角容器 -->
    <div ref="cesiumCamera" id="cesiumCamera"></div>
    <div class="zoom-ui-container" @wheel="handleWheel">
       <!-- 中间黄色准星框 -->
    <div
      class="reticle"
      :style="{ width: boxWidth + 'px', height: boxHeight + 'px' }"
    ></div>
    <!-- 使用 ElementUI 的 Slider 替代变倍轴 -->
    <div class="zoom-bar-slider">
      <el-slider
        v-model="zoomRatio"
        vertical
        height="200px"
        :min="minZoom"
        :max="maxZoom"
        :step="0.1"
        :format-tooltip="formatTooltip"
        :marks="marks"
        @input="onSliderInput"
      />
    </div>
      <!-- 左下角倍率信息 -->
      <div class="zoom-info">
        <el-tag type="success">倍率: {{ zoomRatio.toFixed(1) }}X</el-tag>
      </div>
    </div>
    <!-- botton -->
    <div class="cesiumBotton">
      <div class="cesiumButtonGroup">
        <el-button id="groundPoi" @click="addGroundPoi()" type="primary">地面点</el-button>
        <!-- <el-button id="groundPoi" @click="addGroundPoi()" type="primary">停留时间</el-button> -->
        <el-input v-model="mergeNumber" placeholder="请输入合并范围" type="number" style="width: 150px;"></el-input>
        <el-button  @click="mergePoint()" type="success">合并</el-button>
        <el-button  @click="renderData()" type="success">数据渲染</el-button>
        <el-button  @click="VisualCone()" type="success">生成视锥体</el-button>
        <el-button  @click="fly()" type="success">飞到指定地点</el-button>
      </div>
      <!-- <div class="key-container">
        <div class="arrow-row">
@@ -96,7 +121,7 @@
let ScopeElement; //光轴、视频
let preVideoScopePrimitiveArrTie = [];
let scratchSetViewMatrix3 = new Cesium.Matrix3();
let chooseId
// let  pois = [0, 0,0] 
let holdingPosition;
let rightKeyMove = false
@@ -134,10 +159,29 @@
        mergeNumber:null,
        activeKey: null,
        timer: null,
        zoomRatio: 1,
        minZoom: 1,
        maxZoom: 56,
        baseBoxSize: 400,
        marks: {
          1: '1X',
          7: '7X',
          14: '14X',
          28: '28X',
          56: '56X'
        }
    }
  },
  mounted(){
     this.initCesium();
  },
  computed: {
    boxWidth() {
      return this.baseBoxSize / this.zoomRatio;
    },
    boxHeight() {
      return (this.baseBoxSize * 0.75) / this.zoomRatio; // 高度保持 4:3 比例
    }
  },
  beforeDestroy() {
    counter = 0
@@ -165,7 +209,6 @@
        control.enableTilt = false;
        control.enableLook = false;
        viewerC.scene.camera.percentageChanged = 0.05 
        this.cammove_measure_point();
      },1000)
    },
@@ -204,13 +247,6 @@
          fullscreenButton: false,
          vrButton: false,
      });
       // 关闭天空盒效果
      // viewer.scene.skyAtmosphere = undefined; // 或者设置为 null
      // // 关闭光照效果
      // viewer.scene.globe.enableLighting = false; // 关闭光照效果
    //    viewer.imageryLayers.add(bdtvectoranoimagery);
      viewer._cesiumWidget._creditContainer.style.display="none";  
      return viewer;
      
@@ -227,7 +263,6 @@
      // 设置视角,使其默认查看某个地理位置
      viewerM.scene.camera.setView({
          destination: Cesium.Cartesian3.fromDegrees(globalon, globalat, 349.0), // 以经纬度设置位置(例如:大庆龙兴路)
          // destination: Cesium.Cartesian3.fromDegrees(0.0005, 0.0017, 207.8), // 以经纬度设置位置(例如:大庆龙兴路)
          orientation: {
              heading: Cesium.Math.toRadians(194.65),  // 方向
              pitch: Cesium.Math.toRadians(-31.43), // 俯角
@@ -259,12 +294,10 @@
    },
    addSyncListener() {
      // 存下回调以便销毁
      // this._preRenderCallback = () => this.syncViewer();
      viewerM.scene.preRender.addEventListener( this.syncViewer());
      window.addEventListener("keydown", this.handleKeydown);
    },
    syncViewer(){
      console.log(viewerM.camera)
      viewerC.camera.flyTo({
          destination: viewerM.camera.position,
          orientation: {
@@ -307,7 +340,6 @@
                let lng = Cesium.Math.toDegrees(cartographic.longitude);
                let lat = Cesium.Math.toDegrees(cartographic.latitude);
                height = cartographic.height;
                console.log(lng+','+lat+','+height)
            }
            //在两个窗口创建标注
@@ -336,34 +368,28 @@
                //根据偏移量求偏移向量
                const scalerNormalize = Cesium.Cartesian3.multiplyByScalar(normalize,distance,new Cesium.Cartesian3());
                const tagert = Cesium.Cartesian3.add(holdingPosition,scalerNormalize,new Cesium.Cartesian3());
                console.log(Cesium.Cartographic.fromCartesian(tagert))
                //创建空中点pin
                _this.creatPin("aerialPoiId"+counter,tagert,`空${counter}`,Cesium.Color.RED,viewerM);
                preVideoScopePrimitiveArrTie = []
                console.log(Cesium.Math.toDegrees(Cesium.Cartographic.fromCartesian(tagert).height))
                //更新键盘事件
                _this.updateCameraMovement();
                if(cameraVideo){
                  viewerM.scene.primitives.remove(cameraVideo)
                }
              //创建视锥体
                //当前选择的id
                chooseId = crypto.randomUUID()
                //创建视锥体
                let data = {
                    "FHorFieldAngle": 32.13,
                    "FVerFieldAngle": 18.39,
                    "altitude":  Cesium.Cartographic.fromCartesian(tagert).height,
                    "id": "111111",
                    "chanNo": 1,
                    "id": chooseId,
                    "latitude": Cesium.Math.toDegrees(Cesium.Cartographic.fromCartesian(tagert).latitude),
                    "longitude":  Cesium.Math.toDegrees(Cesium.Cartographic.fromCartesian(tagert).longitude),
                    "p": 26.8,
                    "t": 351.3,
                    "z": 1,
                }
                //塔的距离和观测点的距离
                const point1 = Cesium.Cartesian3.fromDegrees(0, 0, 50);
                const point2 = Cesium.Cartesian3.fromDegrees(Cesium.Math.toDegrees(Cesium.Cartographic.fromCartesian(tagert).longitude), Cesium.Math.toDegrees(Cesium.Cartographic.fromCartesian(tagert).latitude), Cesium.Cartographic.fromCartesian(tagert).height);
                // 计算距离(单位:米)
                const distance1 = Cesium.Cartesian3.distance(point1, point2)
                console.log(distance1)
                data.distance = distance1
                const distanceCalculate = Cesium.Cartesian3.distance(point1, point2)
                data.distance = distanceCalculate
                //右键结束后把缩放重置为1
                _this.zoomRatio = 1
                _this.createVideoScope(data)
                setTimeout(() => {
                  viewerC.camera.changed.addEventListener(_this.onCameraChange)
@@ -400,8 +426,6 @@
      return result;
    },
    changeCamera(position,heading){
        console.log(position)
        console.log(heading)
        viewerC.camera.flyTo({
            destination: position,
            orientation: {
@@ -503,7 +527,6 @@
        } else {
          groupEntity.position = position;
        }
        console.log(groupEntity)
      }
      const key = event.key;
      const lower = key.toLowerCase();
@@ -670,15 +693,6 @@
      // Fly back to the initial view (home) in 1 second
      viewerC.camera.flyHome(1.0);
    },
    move_measure_point(){
      CesiumSurvey.measureMovePoint(viewerC,'moveResultCon');
    },
    cammove_measure_point(){
      CesiumSurvey.cammeasureMovePoint(viewerC,'cammoveResultCon');
    },
    renderData(){
        this.$emit('renderData',viewerM)
    },
    mergePoint(){
      let allEntities = viewerM.entities.values; // 所有实体对象组成的数组
      const grouped = {};
@@ -715,7 +729,6 @@
          ]
        };
      });
      console.log(result)
      this.$emit('mergePoint',result,this.mergeNumber,viewerM)
    },
    genId() {
@@ -746,31 +759,14 @@
    },
    handleKeydown(e) {
      const key = e.key;
      console.log(key)
      const validKeys = ["a", "s", "d", "w",'q','e','ArrowUp','ArrowDown','ArrowLeft','ArrowRight','q','e'];
      if (validKeys.includes(key)) {
        this.triggerKey(key);
      }
      this.updateCameraMovement()
    },
    VisualCone(){
      let data = {
          "FHorFieldAngle": 32.13,
          "FVerFieldAngle": 18.39,
          "altitude": 55,
          "cameraId": "fdae8144e0fc47cf95152080eb3f7db3",
          "chanNo": 1,
          "latitude": 46.58528798,
          "longitude": 124.9662813,
          "p": 26.8,
          "t": 351.3,
          "z": 1
      }
    },
     // 创建初始化的光轴
    createVideoScope(data) {
      console.log(data)
      console.log(data.distance)
      if (data == undefined) {
        this.$message({
          showClose: true,
@@ -791,7 +787,6 @@
            // Number(data.altitude) + Number(hight[1]) + 1.7
            Number(data.altitude)
        );
        console.log(data)
        let inverseViewMatrix = this.hpr2m({
          position: positionCt3, // 相机坐标
          // heading: Cesium.Math.toRadians(Number(120)),
@@ -802,7 +797,7 @@
          roll: Cesium.Math.toRadians(0),
        });
        let frustum = new Cesium.PerspectiveFrustum({
          fov: Cesium.Math.toRadians(6),
          fov: Cesium.Math.toRadians(56),
          aspectRatio: Number(1.77778), // 宽高比
          near: Number(0.05), // 设备焦距
          far: Number(data.distance), // 拍摄距离
@@ -814,7 +809,7 @@
          showHelperPrimitive: true,
        });
        cameraVideo._primitive.classificationType = 2; // 同时投影地形和3dtiles数据
        cameraVideo.id = "sz" + data.id;
        cameraVideo.id =  data.id;
        let isHole = false;
        cameraVideo._primitive.appearance.material = new Cesium.Material({
          fabric: {
@@ -830,13 +825,15 @@
            );
        // viewer.scene.primitives.add(cameraVideo);
        let pmObj = {};
        console.log(data)
        pmObj.id = "sz" + data.id;
        console.log(pmObj)
        pmObj.id = data.id;
        pmObj.primitive = cameraVideo;
        // pmCollection.push(pmObj);//幕布,视频转换使用
        viewerM.scene.primitives.add(cameraVideo);
        preVideoScopePrimitiveArrTie.push(pmObj);
        preVideoScopePrimitiveArrTie.map((item)=>{
          if(item.id != chooseId){
            item.primitive.show = false
          }
        })
      }
      // }
    },
@@ -893,16 +890,6 @@
      return inverseViewMatrix;
    },
    fly(){
       viewerM.scene.camera.setView({
          destination: Cesium.Cartesian3.fromDegrees(124.9662813, 46.58528798, 349.0), // 以经纬度设置位置(例如:大庆龙兴路)
          orientation: {
              heading: Cesium.Math.toRadians(194.65),  // 方向
              pitch: Cesium.Math.toRadians(-31.43), // 俯角
              roll: 0
          }
      });
    },
    onCameraChange() {
      const camera = viewerC.camera;
      const position = camera.positionCartographic;
@@ -911,14 +898,36 @@
      const roll = Cesium.Math.toDegrees(camera.roll);
      const point1 = Cesium.Cartesian3.fromDegrees(0, 0, 50);
      const point2 = Cesium.Cartesian3.fromDegrees(Cesium.Math.toDegrees(position.longitude),Cesium.Math.toDegrees(position.latitude),position.height)
      var camResult =
        position.longitude.toFixed(4) +
        '\u00B0' +
        ',' +
        position.latitude.toFixed(4) +
        '\u00B0' +
        ',' +
        position.height.toFixed(1) +
        '米,' +
        heading.toFixed(2) +
        '\u00B0' +
        ',' +
        pitch.toFixed(2) +
        '\u00B0' +
        ',' +
        roll.toFixed(1) +
        '\u00B0';
      document.getElementById('cammoveResultCon').innerHTML = camResult;
      // 计算距离(单位:米)
      const distanceBetween = Cesium.Cartesian3.distance(point1, point2)
      console.log(distanceBetween)
      if(preVideoScopePrimitiveArrTie?.length !=0 ){
        let obj = this.updateSZScope(Cesium.Math.toDegrees(position.longitude),Cesium.Math.toDegrees(position.latitude),position.height,heading,pitch,roll,1,distanceBetween)
        preVideoScopePrimitiveArrTie[0].primitive.inverseViewMatrix = obj.M
        preVideoScopePrimitiveArrTie[0].primitive.frustum = obj.F
      }
      console.log(preVideoScopePrimitiveArrTie)
      preVideoScopePrimitiveArrTie.map((item)=>{
        if(item.id == chooseId){
          let obj = this.updateSZScope(Cesium.Math.toDegrees(position.longitude),Cesium.Math.toDegrees(position.latitude),position.height,heading,pitch,roll,this.zoomRatio,distanceBetween)
          item.primitive.inverseViewMatrix = obj.M
          item.primitive.frustum = obj.F
          item.primitive.zoomRatio  = this.zoomRatio
        }
      })
    },
    //更新视椎体位置
    updateSZScope(lon, lat, alt, camHeading, camPitch, camRoll, LightView,distanceBetween) {
@@ -927,24 +936,38 @@
          Number(lat),
          Number(alt)
      );
      console.log(positionCt3)
      console.log(distanceBetween)
      let frustum = new Cesium.PerspectiveFrustum({
        fov: Cesium.Math.toRadians(LightView),
        fov: Cesium.Math.toRadians(56/LightView),
        aspectRatio: Number(1.77778),
        near: Number(0.05),
        far: Number(distanceBetween),
      });
      console.log(frustum)
      let inverseViewMatrixNew = this.hpr2m({
        position: positionCt3,
        heading: Cesium.Math.toRadians(Number(camHeading)),
        pitch: Cesium.Math.toRadians(Number(camPitch)),
        roll: Cesium.Math.toRadians(Number(camRoll)),
      });
      console.log(inverseViewMatrixNew)
      return {M: inverseViewMatrixNew, F: frustum};
    },
    handleWheel(event) {
      const delta = event.deltaY;
      const step = 0.5;
      if (delta > 0) {
        this.zoomRatio = Math.min(this.zoomRatio + step, this.maxZoom);
      } else {
        this.zoomRatio = Math.max(this.zoomRatio - step, this.minZoom);
      }
      this.onCameraChange()
    },
    formatTooltip(val) {
      if(val){
        return `${val.toFixed(1)}X`;
      }
    },
    onSliderInput(val) {
      this.zoomRatio = val;
    }
  }
}
</script>
@@ -957,20 +980,23 @@
#cesiumContainer {
    margin: 0;
    padding: 0;
    width: 60%;
    width: 74%;
    height: calc(100vh - 205px);
}
#cesiumCamera {
    position: absolute;
    z-index: 2;
    background-color: rgba(47, 53, 60, 1);
    padding: 0 5px;
    right: 0px;
    top: 0px;
    /* padding: 0 5px; */
    right: 10px;
    /* top: 0px; */
    bottom: 80px;
    margin: 0;
    width: 33%;
    height:  calc(100vh - 400px);
    border: 1px solid #000;
    width: 400px;
    height: 300px;
    z-index: 6;
    /* height:  calc(100vh - 400px); */
    /* border: 1px solid #000; */
}
.cesiumBotton {
    position: absolute;
@@ -979,14 +1005,16 @@
    /* padding: 0 5px; */
    margin-top: 10px;
    right: 0px;
    width: 410px;
    height: calc(100vh - 210px);
    bottom: 30px;
    margin: 0;
    width: 33%;
    height: calc(30% - 30px);
}
.cesiumButtonGroup{
  margin-top: 10px;
  margin-left: 10px;
  position: absolute;
  bottom: 0;
  /* margin-top: 10px;
  margin-left: 10px; */
}
.moveResult{position:absolute;z-index:2;background-color:rgba(47,53,60,1);padding:0 5px;right:50%;bottom:30px;
    border:1px solid rgba(255,255,255,.1);box-sizing:content-box;width:220px;height:30px;font-size:14px;text-align:center}
@@ -1041,4 +1069,51 @@
.key.active {
  background-color: #00aaff;
}
</style>
<style scoped>
.zoom-ui-container {
  /* width: 100%;
  height: 100%;
  position: relative;
  background: #1e1e1e; /* 你可以替换成图像或视频背景 */
  /* overflow: hidden; */
  width: 400px;
  height: 300px;
  position: absolute;
  right: 10px;
  bottom:80px;
  /* background-color: red; */
  z-index: 9;
}
/* 黄色准星框 */
.reticle {
  position: absolute;
  left: 50%;
  top: 50%;
  border: 2px dashed orange;
  transform: translate(-50%, -50%);
  pointer-events: none;
}
/* ElementUI 滑块样式区域 */
.zoom-bar-slider {
  position: absolute;
  right: 20px;
  top: 50px;
  height: 200px;
}
/* 左下角倍率标签 */
.zoom-info {
  position: absolute;
  bottom: 20px;
  left: 20px;
}
</style>
<style>
.el-slider.is-vertical .el-slider__marks-text{
  width: 30px!important;
}
</style>