jihongshun
2025-09-22 4c73249b84759081f625b6196eb59973f06fb9c0
视频融合
已添加1个文件
已修改1个文件
309 ■■■■■ 文件已修改
public/images/videoMark.jpg 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/flightRouteSimulation/index.vue 309 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
public/images/videoMark.jpg
src/views/system/flightRouteSimulation/index.vue
@@ -1,5 +1,7 @@
<template>
   <div class="app-container">
    <el-button @click="putVideo">播放视频</el-button>
    <el-button @click="videoMerge">视频融合</el-button>
    <!-- <a @click="showGZ">显示视锥体</a> -->
    <input @change="handleKMZUpload" type="file" id="kmzFile" accept=".kmz" class="block w-full text-sm text-gray-500
    file:mr-4 file:py-2 file:px-4
@@ -18,6 +20,7 @@
    ></div>
      <!-- 左下角倍率信息 -->
    </div>
    <div id="videoSource"></div>
   </div>
</template>
@@ -25,6 +28,31 @@
import xml2js from 'xml2js'
import CesiumMap from "../../../utils/components/cesium-map.vue";
import { getScopeTower} from "@/api/system/template"
let scratchSetViewMatrix3 = new Cesium.Matrix3();
let cmCollection = [];
let pmCollection = [];
let camera_marks = [];
let cameraData = [];
let playersArr = [];
let fixedHandler;
let camMovehandler;
let mouseMovehandler;
let lastEntity;
let lockfunction;
let isCamLock = false; //超范围回弹标记,回弹坐标参数
let camLockId;
let pointLock;
let headingLock;
let pitchLock;
let preVideoScopeElement = null;
let preVideoScopePrimitiveArr = [];
let preVideoScopePrimitiveArrTie = [];
export default {
  name: "flightRouteSimulation",
  components: {
@@ -608,37 +636,270 @@
        this.camera.frustum.fov = newFov
      }
    },
     // 创建幕布
    createVideoElementOld(videoSrc, id) {
      var videoElement = document.createElement("div");
      videoElement.id = "video" + id;
      videoElement.style.position = "absolute";
      videoElement.style.zIndex = "-100";
      videoElement.style.background = "red";
      document.getElementById("videoSource").appendChild(videoElement);
      return videoElement;
    },
    createVideoElementwithMouse(videoSrc,id) {
        let videoElement = document.createElement('video');
        videoElement.id = 'video'+id;
        videoElement.src = videoSrc+'?t='+new Date().getTime();
        videoElement.style.position = 'absolute';
        videoElement.style.zIndex = '-100';
        videoElement.style.visibility = 'hidden';
        videoElement.crossOrigin = 'anonymous';
        videoElement.autoplay = true;
        videoElement.loop = true;
        videoElement.muted = true;
        document.getElementById("videoSource").appendChild(videoElement);
        return videoElement;
    },
    hpr2m(obj, result) {
      // const inverseViewMatrix = Cesium.Transforms.headingPitchRollToFixedFrame(position, headingPitchRoll, undefined, undefined, result);
      const inverseViewMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(
        obj.position,
        undefined,
        result
      );
      // const hpr = new Cesium.HeadingPitchRoll(heading - Cesium.Math.PI_OVER_TWO, pitch, roll);
      // var rotQuat = Cesium.Quaternion.fromHeadingPitchRoll(hpr, scratchSetViewQuaternion);
      // var rotMat = Cesium.Matrix3.fromQuaternion(rotQuat, scratchSetViewMatrix3);
      let rotMat = Cesium.Matrix3.fromRotationX(
        Cesium.Math.PI_OVER_TWO,
        scratchSetViewMatrix3
      );
      Cesium.Matrix4.multiplyByMatrix3(
        inverseViewMatrix,
        rotMat,
        inverseViewMatrix
      );
      rotMat = Cesium.Matrix3.fromRotationY(
        -obj.heading,
        scratchSetViewMatrix3
      );
      Cesium.Matrix4.multiplyByMatrix3(
        inverseViewMatrix,
        rotMat,
        inverseViewMatrix
      );
      rotMat = Cesium.Matrix3.fromRotationX(obj.pitch, scratchSetViewMatrix3);
      Cesium.Matrix4.multiplyByMatrix3(
        inverseViewMatrix,
        rotMat,
        inverseViewMatrix
      );
      rotMat = Cesium.Matrix3.fromRotationZ(-obj.roll, scratchSetViewMatrix3);
      Cesium.Matrix4.multiplyByMatrix3(
        inverseViewMatrix,
        rotMat,
        inverseViewMatrix
      );
      return inverseViewMatrix;
    },
    showGZ(){
      let viewer = window['cesiumContainer'].viewer;
      this.camera = new Cesium.Camera(viewer.scene)
      // 视锥体参数
      this.camera.frustum = new Cesium.PerspectiveFrustum({
        // fov: Cesium.Math.PI_OVER_THREE,
        fov:Cesium.Math.toRadians(60),
        aspectRatio: 1920 / 1080,
      // this.camera = new Cesium.Camera(viewer.scene)
      // // 视锥体参数
      // this.camera.frustum = new Cesium.PerspectiveFrustum({
      //   // fov: Cesium.Math.PI_OVER_THREE,
      //   fov:Cesium.Math.toRadians(60),
      //   aspectRatio: 1920 / 1080,
      // });
      // this.camera.setView({
      //   up: Cesium.Cartesian3.UNIT_Z,
      //   destination: this.c3Position,
      //   orientation: {
      //     heading: Cesium.Math.toRadians(this.heading),
      //     pitch: Cesium.Math.toRadians(this.pitch),
      //     roll: Cesium.Math.toRadians(this.roll),
      //   },
      // })
      // this.frustumOutline = new Cesium.DebugCameraPrimitive({
      //   id: 111111,
      //   camera: this.camera,
      //   frustumSplits: [0.01, 10000],
      //   color: Cesium.Color.fromCssColorString('#00ff00'),
      //   // updateOnChange: false,
      //   updateOnChange: true,
      // })
      // viewer.scene.primitives.add(this.frustumOutline);
      // this.listenChange()
      // let videoElement = this.createVideoElementwithMouse("",'11111111');
      preVideoScopeElement = this.createVideoElementOld(
        "http://192.168.5.122:9998/live?port=1234&app=live&stream=mystream",
        '1111111',
        1.7778
      );
      let positionCt3 = this.c3Position
      // 2.2.2.2 准备inverseViewMatrix
        // 准备inverseViewMatrix是为了定义视频拍摄的相机的姿态(位置和方向)
        // 此处设定为当前相机的欧拉角(heading\pitch\roll)和位置信息
      let inverseViewMatrix = this.hpr2m({
            position: positionCt3,
            heading: Cesium.Math.toRadians(Number(this.heading)),
            pitch: Cesium.Math.toRadians(Number(this.pitch)),
            roll: Cesium.Math.toRadians(Number(this.roll)),
      });
      this.camera.setView({
        up: Cesium.Cartesian3.UNIT_Z,
        destination: this.c3Position,
        orientation: {
          heading: Cesium.Math.toRadians(this.heading),
          pitch: Cesium.Math.toRadians(this.pitch),
          roll: Cesium.Math.toRadians(this.roll),
      // 2.2.2.3 准备frustum,
        // frustum是为了定义投影体的形状
        // frustum选填,可以直接置为undefined
        let frustum = new Cesium.PerspectiveFrustum({
            fov: Cesium.Math.toRadians(60),
            aspectRatio: Number(1.77778), // 宽高比
            near: Number(0.05), // 设备焦距
            far : 1000.0
        });
        // 2.2.2.4 根据以上信息创建cameraVideo
        let cameraVideo = new Cesium.XbsjCameraVideo({
            inverseViewMatrix: inverseViewMatrix,
            frustum: frustum,
            videoElement: preVideoScopeElement,
            showHelperPrimitive: true
        });
        cameraVideo._primitive.classificationType = 2; // 同时投影地形和3dtiles数据
        cameraVideo.id='sz'+11111111
        let isHole = false;
        cameraVideo._primitive.appearance.material = new Cesium.Material({
            fabric : {
                type : 'Color',
                uniforms : {
                    color : new Cesium.Color(1.0, 0, 0, 0.2)
                }
            }
        });
        viewer.scene.primitives.add(cameraVideo);
        let pmObj = {};
      pmObj.id = 'video'+11111111;
      pmObj.primitive = cameraVideo;
      cmCollection.push(pmObj);
        },
      })
      this.frustumOutline = new Cesium.DebugCameraPrimitive({
        id: 111111,
        camera: this.camera,
        frustumSplits: [0.01, 10000],
        color: Cesium.Color.fromCssColorString('#00ff00'),
        // updateOnChange: false,
        updateOnChange: true,
      })
      viewer.scene.primitives.add(this.frustumOutline);
    putVideo(){
      this.createVideoElement('/trailer.mp4','111111',2)
      
      this.listenChange()
    },
    videoMerge(){
      let node = null
        this.createCameraVideo(node,document.getElementById("video" + 111111))
    },
    // 创建幕布flv技术
    createVideoElement(videoSrc, id, as) {
      let viewer = window['cesiumContainer'].viewer
      let videoElement = document.createElement("video");
      videoElement.id = "video" + id;
      videoElement.style.position = "absolute";
      videoElement.style.zIndex = "100";
      // videoElement.style.top = "0";
      videoElement.style.visibility = 'hidden';
      console.log(viewer.canvas)
      console.log(viewer.canvas.clientHeight)
      let veHeight = viewer.canvas.clientHeight / 2;
      videoElement.style.height = veHeight + "px";
      let veWidth = Number(veHeight) * Number(as);
      videoElement.style.width = veWidth / 2 + "px";
      videoElement.style.bottom = 0;
      videoElement.style.left =
        (Number(viewer.canvas.clientWidth) - veWidth) / 2 + "px";
      // videoElement.crossOrigin = "anonymous";
      videoElement.autoplay = 'autoplay';
      videoElement.loop = 'loop';
      videoElement.controls = 'controls';
      videoElement.muted = "muted";
      // 设置视频源
      // videoElement.src = 'https://media.w3.org/2010/05/sintel/trailer.mp4';
      videoElement.src =videoSrc ;
      // videoElement.type = "video/mp4"
      document.getElementById("videoSource").appendChild(videoElement);
      let playerObj = {};
      playerObj.id = "video" + id;
      playersArr.push(playerObj);
      return videoElement;
    },
     // 清除幕布的div元素
    destroyVideoElement(videoElement) {
      document.getElementById("videoSource").removeChild(videoElement);
    },
    // 创建相机姿势
    createCameraVideo(node, videoElement) {
      console.log(document.getElementById("video" + 111111))
      let viewer = window['cesiumContainer'].viewer;
      let positionCt3 = Cesium.Cartesian3.fromDegrees(125.04159166971326, 46.63755601510411,33.13806141449017)
      // 2.2.2.2 准备inverseViewMatrix
      // 准备inverseViewMatrix是为了定义视频拍摄的相机的姿态(位置和方向)
      // 此处设定为当前相机的欧拉角(heading\pitch\roll)和位置信息
      let inverseViewMatrix = this.hpr2m({
        position: positionCt3,
        heading: Cesium.Math.toRadians(Number(this.heading)),
        pitch: Cesium.Math.toRadians(Number(this.pitch)),
        roll: Cesium.Math.toRadians(Number(this.roll)),
      });
      // 2.2.2.3 准备frustum,
      // frustum是为了定义投影体的形状
      // frustum选填,可以直接置为undefined
      let frustum = new Cesium.PerspectiveFrustum({
        fov: Cesium.Math.toRadians(60),
        aspectRatio: Number(1.77778), // 宽高比
        near: Number(0.05), // 设备焦距
        far : 1000.0
      });
      // 2.2.2.4 根据以上信息创建cameraVideo
      let cameraVideo = new Cesium.XbsjCameraVideo({
        inverseViewMatrix: inverseViewMatrix,
        frustum: frustum,
        videoElement: videoElement,
        showHelperPrimitive: false,
      });
      cameraVideo._primitive.classificationType = 2;
      let isHole = false;
      let alphamaterial = new Cesium.Material({
        fabric: {
          type: 'XbsjCameraVideo',
          uniforms: {
            image: '', // Cesium有bug,此处不能直接赋值video
            alphaImage: '/images/videoMark.jpg',
          },
          components: {
            diffuse: 'texture2D(image, fract(materialInput.st)).rgb',
            // alpha : 'texture2D(alphaImage, fract(repeat * materialInput.st)).a * color.a'
            alpha: 'texture2D(alphaImage, fract(materialInput.st)).r',
    }
        }
      });
      alphamaterial.uniforms.image = videoElement;
      cameraVideo._primitive.appearance.material = alphamaterial;
      // 2.2.2.5 加入到场景中去
      viewer.scene.primitives.add(cameraVideo);
      let pmObj = {};
      pmObj.id = 'video' + '111111';
      pmObj.isHole = isHole;
      pmObj.primitive = cameraVideo;
      pmCollection.push(pmObj);
    },
    //清除视频投影渲染基元
    destroyCameraVideo(vid) {
      if(pmCollection){
        for (let i = 0; i < pmCollection.length; i++) {
          if (vid === pmCollection[i].id) {
            viewer.scene.primitives.remove(pmCollection[i].primitive);
            pmCollection.splice(i, 1);
          }
        }
      }
    },
  }
}
</script>