Cesium案例(二)

一、HTML

<template>
  <div id="cesiumContainer">
    <!-- 地图工具栏 -->
    <ul class="mapTools">
      <li v-for="item in toolsData" :key="item.id" @click="toolsClick(item)">
        <!-- 显示label -->
        <el-tooltip
          v-if="item.id == 1"
          class="item"
          effect="dark"
          :content="item.label"
          placement="left">
          <span class="label">{{ item.text }}</span>
        </el-tooltip>

        <el-tooltip
          v-else
          class="item"
          effect="dark"
          :content="item.label"
          placement="left">
          <!-- 显示icon -->
          <span :class="item.icon" class="icon"></span>
        </el-tooltip>
      </li>
    </ul>

    <!-- 左侧悬浮框 -->
    <div class="leftFlatBox" v-if="isShowInfo">
      <ul class="content">
        <li>
          <span class="subTitle">标识</span>
          <span class="subValue">{{ selModelInfo.id }}</span>
        </li>
        <li>
          <span class="subTitle">名称</span>
          <span class="subValue">{{ selModelInfo.name }}</span>
        </li>
        <li>
          <span class="subTitle">地址</span>
          <span class="subValue">{{ selModelInfo.ip }}</span>
        </li>
        <li>
          <span class="subTitle">端口</span>
          <span class="subValue">{{ selModelInfo.port }}</span>
        </li>
        <li>
          <span class="subTitle">位置</span>
          <span class="subValue">{{
            `${filterNumber(selModelInfo.position.lon, 6)},${filterNumber(
              selModelInfo.position.lat,
              6
            )},${selModelInfo.position.height}`
          }}</span>
        </li>
        <li>
          <span class="subTitle">状态</span>
          <span
            class="subValue"
            :style="
              selModelInfo.status == '连接' ? 'color:#04F44C' : 'color:#F52E2E'
            "
            >{{ selModelInfo.status == "连接" ? "正常" : "异常" }}</span
          >
        </li>
      </ul>
    </div>
  </div>
</template>

二、JavsScript

<script>
import * as turf from "@turf/turf";
export default {
  name: "Cesium",
  components: {},
  props: {},
  data() {
    return {
      // ----------------------<<地图>>----------------------
      // cesium相机初始位置
      ps: {
        lon: 110,
        lat: 30,
        height: 1000,
      },
      // 地图工具栏列表
      toolsData: [
        {
          id: 1,
          text: "2D",
          label: "2D/3D切换",
          icon: "",
        },
      ],
      // 模型颜色集合
      modeColorObj: {},
      // 路径集合
      aggregate: {},
      // 圆锥集合
      primitiveObj: {},
      // 选中模型id
      selModelId: "",
      // 选中模型数据
      selModelInfo: null,
      // 是否显示模型信息框
      isShowInfo: false,
      // 圆锥实体key
      coneKey: "",
    };
  },
  mounted() {
    // 初始化地图
    this.initMap();
    this.createGroundPlat();
    this.addPolar();
  },
  methods: {
    // -------------------------<<地图>>------------------------
    // 初始化地图
    initMap() {
      // 配置在线地图token
      Cesium.Ion.defaultAccessToken ="<Map_Token>";

      let imageryProvider;

      //在线地图
      imageryProvider = new Cesium.ArcGisMapServerImageryProvider({
        url: "https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer",
      });

      window.viewer = new Cesium.Viewer("cesiumContainer", {
        geocoder: false, //右上角搜索
        homeButton: false, //右上角home
        sceneModePicker: false, //右上角2D/3D切换
        baseLayerPicker: false, //右上角地形
        navigationHelpButton: false, //右上角帮助
        animation: true, //左下角圆盘动画控件
        timeline: true, //底部时间轴
        fullscreenButton: false, //右下角全屏控件
        vrButton: false, //如果设置为true,将创建VRButton小部件。
        scene3DOnly: false, // 每个几何实例仅以3D渲染以节省GPU内存
        infoBox: false, //隐藏点击要素后的提示信息
        imageryProvider: imageryProvider, //地图地址
        selectionIndicator: false,
      });

      // 隐藏左下角商标信息
      viewer._cesiumWidget._creditContainer.style.display = "none";
      // 隐藏底部时间轴
      viewer.timeline.container.style.display = "none";
      viewer.scene.globe.depthTestAgainstTerrain = false; //开启深度检测

      // 设置最小缩放级别,以米为单位
      viewer.scene.screenSpaceCameraController.minimumZoomDistance = 500.0;

      // 设置最大缩放级别,以米为单位
      viewer.scene.screenSpaceCameraController.maximumZoomDistance = 20000000.0;

      // 隐藏动画控件
      const animationContainer = document.querySelector(
        ".cesium-viewer-animationContainer"
      );
      animationContainer.style.display = "none";

      // 自动播放动画
      viewer.clock.shouldAnimate = true;

      // 启用光照
      viewer.scene.globe.enableLighting = true;

      // 设置相机初始位置
      viewer.camera.setView({
        destination: Cesium.Cartesian3.fromDegrees(
          this.$store.state.platModelInfo.desc.position.lon,
          this.$store.state.platModelInfo.desc.position.lat - 0.0075,
          800
        ),
        // 设置相机方向,俯视和仰视的视角
        orientation: {
          heading: Cesium.Math.toRadians(0), //坐标系旋转0度
          pitch: Cesium.Math.toRadians(-45), //设置俯仰角度为-45度
        },
      });

      // --------<<鼠标事件>>--------
      // 移除左键双击默认事件
      // viewer.screenSpaceEventHandler.removeInputAction(
      //   Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK
      // );
      // 注册左键单击事件
      this.leftClick();
    },

    // -----------------------<<模型操作>>-----------------------
    // 绘制其他模型
    addModel(info) {
      if (viewer.entities.getById(info.desc.id)) {
        return;
      }

      // 转换笛卡尔空间直角坐标
      const position = new Cesium.Cartesian3.fromDegrees(
        info.desc.position.lon,
        info.desc.position.lat,
        info.desc.position.height
      );

      //模型朝向
      const heading = Cesium.Math.toRadians(90); // 方位
      const pitch = 0; // 俯仰
      const roll = 0; // 偏移角度
      const hpr = new Cesium.HeadingPitchRoll(heading, pitch, roll);
      const orientation = Cesium.Transforms.headingPitchRollQuaternion(
        position,
        hpr
      );

      // ++++++++++<<创建模型>>++++++++++
      const entity = viewer.entities.add({
        id: info.desc.id, //模型id
        name: info.type, // 模型名称,这里用作模型类型,方便场景模型增删改查
        position: position, //模型位置,高度
        orientation: orientation,
        model: {
          uri: info.desc.path, //模型文件
          minimumPixelSize: 30, //模型最小像素大小
          maximumScale: 60, //模型最大像素大小
          color: Cesium.Color.CYAN,
          silhouetteColor: Cesium.Color.MAGENTA,
          silhouetteSize: 1,
        },
        description: info.desc,
      });
    },

    // 绘制飞机
    addPlane(info) {
      if (viewer.entities.getById(info.desc.id)) {
        return;
      }

      // 转换笛卡尔空间直角坐标
      const position = new Cesium.Cartesian3.fromDegrees(
        info.desc.position.lon,
        info.desc.position.lat,
        info.desc.position.height
      );

      //模型朝向
      const heading = Cesium.Math.toRadians(90); // 方位
      const pitch = 0; // 俯仰
      const roll = 0; // 偏移角度
      const hpr = new Cesium.HeadingPitchRoll(heading, pitch, roll);
      const orientation = Cesium.Transforms.headingPitchRollQuaternion(
        position,
        hpr
      );

      // ++++++++++<<创建模型>>++++++++++
      viewer.entities.add({
        id: info.desc.id, //模型id
        name: info.type, // 模型名称,这里用作模型类型,方便场景模型增删改查
        position: position, //模型位置,高度
        orientation: orientation,
        model: {
          uri: info.desc.path, //模型文件
          minimumPixelSize: 100, //模型最小像素大小
          maximumScale: 150, //模型最大像素大小
          color: Cesium.Color.fromCssColorString(
            JSON.parse(JSON.stringify(this.$store.state.modelColor.color))
          ),
          silhouetteColor: Cesium.Color.MAGENTA,
          silhouetteSize: 1,
        },
        description: info.desc,
      });
    },
    // 更新飞机
    updatePlane(item) {
      let entities = viewer.entities.getById(item.id);

      // 记录航迹信息
      this.aggregate[item.id].push(
        Cesium.Cartesian3.fromDegrees(
          item.position.lon,
          item.position.lat,
          item.position.height
        )
      );

      // 更新无人机信息
      entities._description._value = item;

      // 绘制航迹信息
      this.addFlightPath(item.id, {
        lon: item.position.lon,
        lat: item.position.lat,
        alt: item.position.height,
      });

      // 更新无人机位置
      entities.position = Cesium.Cartesian3.fromDegrees(
        item.position.lon,
        item.position.lat,
        item.position.height
      );
    },
    // 绘制飞行线路
    addFlightPath(id, ps) {
      let entities = viewer.entities.getById(`line${id}`);

      // 如果航迹不存在,创建航迹
      if (!entities) {
        var that = this;
        viewer.entities.add({
          id: `line${id}`,
          name: "line",
          polyline: {
            positions: Cesium.Cartesian3.fromDegreesArray([], false), // 初始化一个空的线条
            positions: new Cesium.CallbackProperty(function () {
              return that.aggregate[id];
            }, false),
            width: 3,
            // material: Cesium.Color.YELLOW,
            material: new Cesium.StripeMaterialProperty({
              // 用条纹材质设置外边颜色
              evenColor: Cesium.Color.YELLOW, // 偶数条纹颜色
              oddColor: Cesium.Color.RED, // 奇数条纹颜色
              repeat: 3.0, // 条纹的重复数量
            }),
          },
        });
      }
    },

    // 绘制极坐标
    addPolar() {
      // 绘制圆形
      this.addCircle();

      for (let i = 0; i < 360; i++) {
        if (i % 10 == 0) {
          this.addPolarLabel([110, 30], 0.315, i, i); // 绘制label(刻度值)
        }
        if (i % 30 == 0) {
          this.addArrow(i); // 绘制箭头
        }
        if (i % 90 == 0) {
          // 绘制距离标识
          this.addPolarLabel([110, 30], 0.25, i, "300m");
          this.addPolarLabel([110, 30], 0.15, i, "200m");
          this.addPolarLabel([110, 30], 0.05, i, "100m");
        }
      }
    },
    // 绘制圆形-极坐标
    addCircle() {
      // 圆柱体
      let position = Cesium.Cartesian3.fromDegrees(103.650219, 31.035943);
      viewer.entities.add({
        name: "coordinates",
        position: position,
        ellipse: {
          semiMinorAxis: 300.0,
          semiMajorAxis: 300.0,
          material: this.getColorRamp(
            [
              [0.0, "rgba(255,255,255,0)"],
              [0.15, "rgba(255,255,255,0)"],
              [0.8, "rgba(1,255,0,.2)"],
              [0.9, "rgba(0,255,0,.4)"],
              [1.0, "rgba(0,255,0,.6)"],
            ],
            false
          ),
        },
      });
      viewer.entities.add({
        name: "coordinates",
        position: position,
        ellipse: {
          semiMinorAxis: 200.0,
          semiMajorAxis: 200.0,
          material: this.getColorRamp(
            [
              [0.0, "rgba(255,255,255,0)"],
              [0.15, "rgba(255,255,255,0)"],
              [0.8, "rgba(0,255,0,.2)"],
              [0.9, "rgba(0,255,0,.4)"],
              [1.0, "rgba(0,255,0,.6)"],
            ],
            false
          ),
        },
      });
      viewer.entities.add({
        name: "coordinates",
        position: position,
        ellipse: {
          semiMinorAxis: 100.0,
          semiMajorAxis: 100.0,
          material: this.getColorRamp(
            [
              [0.0, "rgba(255,255,255,0)"],
              [0.15, "rgba(255,255,255,0)"],
              [0.8, "rgba(0,255,0,.2)"],
              [0.9, "rgba(0,255,0,.4)"],
              [1.0, "rgba(0,255,0,.6)"],
            ],
            false
          ),
        },
      });
    },
    // 圆形渐变材质-极坐标
    getColorRamp(elevationRamp, isVertical = true) {
      var ramp = document.createElement("canvas");
      ramp.width = 300;
      ramp.height = 300;
      var ctx = ramp.getContext("2d");
      var grd = ctx.createRadialGradient(150, 150, 50, 150, 150, 150);
      elevationRamp.forEach((item) => {
        grd.addColorStop(item[0], item[1]); //black
      });
      ctx.fillStyle = grd;
      ctx.fillRect(0, 0, 300, 300);
      return ramp;
    },
    // 绘制箭头-极坐标
    addArrow(angel) {
      var endPs, entity;

      // 计算箭头结束点
      endPs = this.calcEndPosition(
        [
          this.$store.state.platModelInfo.desc.position.lon,
          this.$store.state.platModelInfo.desc.position.lat,
        ],
        0.3,
        angel
      );

      entity = viewer.entities.add({
        name: "coordinates",
        polyline: {
          positions: [
            Cesium.Cartesian3.fromDegrees(
              this.$store.state.platModelInfo.desc.position.lon,
              this.$store.state.platModelInfo.desc.position.lat,
              0.005
            ),
            Cesium.Cartesian3.fromDegrees(endPs.lon, endPs.lat),
          ],
          width: 6,
          material: new Cesium.PolylineArrowMaterialProperty(
            Cesium.Color.fromCssColorString("#00FF33")
          ),
        },
      });
    },
    // 绘制标签-极坐标
    addPolarLabel(ps, distance, angel, content) {
      var labelEntity, endPs;

      // 计算label经纬坐标
      endPs = this.calcEndPosition(ps, distance, angel);

      // 创建标签实体
      labelEntity = viewer.entities.add({
        name: "coordinates",
        position: Cesium.Cartesian3.fromDegrees(endPs.lon, endPs.lat, 5), // 点位坐标
        label: {
          text: `${content}`, // 文本内容
          font: "15px monospace", // 字体样式
          style: Cesium.LabelStyle.FILL, // label样式
          outlineWidth: 1, // 外边框宽度
          outlineColor: Cesium.Color.fromCssColorString("#00FF00"),
          fillColor: Cesium.Color.fromCssColorString("#00FF00"),
          backgroundColor: Cesium.Color.BLACK.withAlpha(0.0), //背景颜色
          showBackground: true, //是否显示背景颜色
          verticalOrigin: Cesium.VerticalOrigin.CENTER, // 文字对齐方式BOTTOM,TOP,CENTER
        },
      });
    },

    // 绘制圆锥
    addCone(item, angel, pitch) {
      if (!angel && angel != 0) {
        console.error("请传入圆锥方位");
        return;
      }
      if (!pitch && pitch != 0) {
        console.error("请传入圆锥俯仰");
        return;
      }

      // 计算角度
      let info = {
        lon: 103.650219, // 经度
        lat: 31.035943, // 纬度
        alt: 0, // 高度
        length: 300, // 圆锥高度
        startAz: angel - 1.5, //起始方位角
        endAz: angel + 1.5, //终止方位角
        startEl: pitch - 1.5, //起始俯仰角
        endEl: pitch + 1.5, //终止俯仰角
      };

      var result = this.calcBeamScaleMatrix4(info);

      //绘制圆锥几何体
      var cone = new Cesium.Primitive({
        show: true,
        releaseGeometryInstances: false, // 默认为true,自动清空geometryInstances配置
        geometryInstances: new Cesium.GeometryInstance({
          id: {
            id: item.id,
            name: "cone",
            description: item,
          },
          geometry: new Cesium.CylinderGeometry({
            length: 200,
            topRadius: 0.0,
            bottomRadius: result.bottomRadius,
          }),
          // attributes: {
          //     show: new Cesium.ShowGeometryInstanceAttribute(typeof show == 'undefined' ? true : show)
          // }
        }),
        modelMatrix: result.mm, //提供位置与姿态参数
        appearance: new Cesium.EllipsoidSurfaceAppearance({
          material: this.getRingM({
            color: JSON.parse(
              JSON.stringify(this.$store.state.modelColor.color)
            ),
          }), // 交替
          faceForward: true,
          closed: true,
        }),
      });

      this.coneKey = "cone" + item.id;

      this.primitiveObj[this.coneKey] = cone;

      viewer.scene.primitives.add(cone);
    },
    // 更新圆锥位置
    updateCone(data, item) {
      let { model, angel, pitch } = data;
      var result = this.calcBeamScaleMatrix4({
        lon: 103.650219, // 经度
        lat: 31.035943, // 纬度
        alt: 0, // 高度
        length: 300, // 圆锥高度
        startAz: angel - 2.5, //起始方位角
        endAz: angel + 2.5, //终止方位角
        startEl: pitch - 2.5, //起始俯仰角
        endEl: pitch + 2.5, //终止俯仰角
      });

      model.geometryInstances.id.description = item;
      model.modelMatrix = result.mm;
    },
    // 圆锥计算
    adjustAngle({ startAngle, endAngle }) {
      if (endAngle < startAngle) {
        if (endAngle > 180 && startAngle < 180) {
          var Az = startAngle; //先大小-前后交换顺序
          startAngle = endAngle;
          endAngle = Az;
        }
      }
      if (Math.abs(endAngle - startAngle) > 180) {
        if (endAngle > 180) {
          Az = startAngle;
          startAngle = endAngle - 360;
          endAngle = startAngle;
        }
      }
      return {
        startAngle,
        endAngle,
      };
    },
    calcBeamMatrix4({ lon, lat, alt, pitch, heading, length }) {
      //北天东与cesium坐标系的差距
      heading += 90;
      pitch = 270 - pitch;
      var center = Cesium.Cartesian3.fromDegrees(lon, lat, alt);
      heading = Cesium.Math.toRadians(heading);
      pitch = Cesium.Math.toRadians(pitch);

      var deadingPitchRoll = new Cesium.HeadingPitchRoll(heading, pitch, 0);
      var hprRotation = Cesium.Matrix3.fromHeadingPitchRoll(deadingPitchRoll);

      var subtract = new Cesium.Cartesian3(0, 0, -length / 2);
      var rotated = Cesium.Matrix3.multiplyByVector(
        hprRotation,
        subtract,
        new Cesium.Cartesian3()
      );

      var hpr = Cesium.Matrix4.fromRotationTranslation(hprRotation, rotated);

      var modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(center);
      Cesium.Matrix4.multiply(modelMatrix, hpr, modelMatrix);
      return modelMatrix;
    },
    calcBeamScaleMatrix4({
      lon,
      lat,
      alt,
      length,
      startAz, //波束起始方位角
      endAz, //波束终止方位角
      startEl, //俯仰
      endEl, //俯仰
    }) {
      //俯仰在正负180之间
      if (startEl > 180) startEl -= 360;
      if (startEl < -180) startEl += 360;
      if (endEl > 180) endEl -= 360;
      if (endEl < -180) endEl += 360;

      var newParam = this.adjustAngle({
        startAngle: startAz,
        endAngle: endAz,
      });
      startAz = newParam.startAngle;
      endAz = newParam.endAngle;

      var newParam1 = this.adjustAngle({
        startAngle: startEl,
        endAngle: endEl,
      });
      startEl = newParam1.startAngle;
      endEl = newParam1.endAngle;

      var heading = (endAz + startAz) / 2; //圆锥的方位指向
      var pitch = ((startEl + endEl) / 2) % 180; //圆锥的俯仰指向俯仰在-180到180之间

      var angle0 = (endAz - startAz) / 2; //方位
      var angle1 = (endEl - startEl) / 2; //俯仰

      if (endAz < 0 && startAz < 0) {
        //计算缩放比列,取最小角度和取绝对值
        angle0 = Math.abs(((endAz % 360) - (startAz % 360)) / 2); //方位圆锥底面
        angle1 = Math.abs(((endEl % 360) - (startEl % 360)) / 2); //俯仰圆锥底面
      }
      var angle = 0;
      var scaleX = 1,
        scaleY = 1;
      if (angle0 < angle1) {
        angle = angle1;
        scaleX = angle0 / angle1; //计算x,y,z的缩放比例(以便形成椭圆面)
      } else {
        angle = angle0;
        scaleY = angle1 / angle0; //计算x,y,z的缩放比例(以便形成椭圆面)
      }

      var bottomRadius = length * Math.tan(Cesium.Math.toRadians(angle)); //计算底边半径(以最小的方位或俯仰角为准)
      var modelMatrix = this.calcBeamMatrix4({
        lon,
        lat,
        alt,
        heading,
        pitch,
        length,
      });

      var s = Cesium.Matrix3.fromScale(
        new Cesium.Cartesian3(scaleY, scaleX, 1.0)
      );
      var scaleMatrix = Cesium.Matrix4.fromRotationTranslation(s);

      let mm = modelMatrix.clone();
      Cesium.Matrix4.multiply(mm, scaleMatrix, mm);
      return { mm, bottomRadius };
    },
    // 圆锥材质
    getRingM(params) {
      var { color, thickness, repeat } = params || {};
      var material = new Cesium.Material({
        fabric: {
          type: "VtxfShader",
          uniforms: {
            color: Cesium.Color.fromCssColorString(
              color || "rgba(255,0,0,0.3)"
            ),
            repeat: repeat || 40.0, //40.0,/重复次数
            offset: 10, // 1.0,
            thickness: thickness || 0.5, //环宽度比列(0, 1]
          },
          source: `
                      uniform vec4 color;
                      uniform float repeat;
                      uniform float offset;
                      uniform float thickness;
                      czm_material czm_getMaterial(czm_materialInput materialInput)
                      {
                          czm_material material = czm_getDefaultMaterial(materialInput);
                          float sp = 1.0/repeat;
                          vec2 st = materialInput.st;
                          float dis = distance(st, vec2(0.5));
                          float m = mod(dis + offset, sp);
                          float a = step(sp*(1.0-thickness), m);
                          material.diffuse = color.rgb;
                          material.alpha = a * color.a;
                          return material;
                      }
                  `,
        },
        // translucent: false,
      });
      return material;
    },

    // 计算结束点(根据坐标,方位,距离计算)
    calcEndPosition(ps, range, angel) {
      var pt = turf.point(ps, { "marker-color": "F00" }); // 起始点
      var distance = range; // 距离
      var bearing = angel; // 角度
      var options = { units: "kilometers" }; // 公里
      var destination = turf.rhumbDestination(pt, distance, bearing, options);

      return {
        lon: destination.geometry.coordinates[0],
        lat: destination.geometry.coordinates[1],
      };
    },

    // 生成随机颜色--浅色
    getColorUndertint() {
      const letters = "ABCDEF";
      let color = "#";
      for (let i = 0; i < 6; i++) {
        color += letters[Math.floor(Math.random() * letters.length)];
      }
      return color;

      // 深色+浅色
      // const letters = "0123456789ABCDEF";
      // let color = "#";
      // for (let i = 0; i < 6; i++) {
      //   color += letters[Math.floor(Math.random() * 16)];
      // }
      // return color;
    },

    delAllModel() {
      // 删除除极坐标内容外的所有模型
      const entitiesArr = viewer.entities.values;

      // 删除entities模型
      for (let i = 0; i < entitiesArr.length; i++) {
        if (
          entitiesArr[i]._name != "coordinates" &&
          entitiesArr[i]._name != "plat"
        ) {
          viewer.entities.removeById(entitiesArr[i]._id);

          i--;
        }
      }

      // 删除primitives模型
      for (let key in this.primitiveObj) {
        viewer.scene.primitives.remove(this.primitiveObj[key]);
      }

      this.primitiveObj = {};

      // 清空飞行数据
      for (let key in this.aggregate) {
        this.aggregate[key] = [];
      }
    },

    // 选中模型
    clickModel(id) {
      // 获取点击模型的实体
      let entities = viewer.entities.getById(id);

      if (entities) {
        // 取消选中模型
        this.deselectModel();

        // 选中模型id
        this.selModelId = id;

        // 显示模型详细信息
        this.isShowInfo = true;

        // 点击模型添加选中颜色
        entities.model.color = Cesium.Color.MAGENTA;
      }
    },

    // 取消选中模型
    deselectModel() {
      // 获取所有模型的实体集合
      const entitiesArr = viewer.entities.values;

      if (entitiesArr.length !== 0) {
        // 恢复模型颜色
        for (let i = 0; i < entitiesArr.length; i++) {
          if (
            entitiesArr[i]._name == "model" ||
            entitiesArr[i]._name == "plat"
          ) {
            for (let key in this.modeColorObj) {
              if (key == entitiesArr[i]._id) {
                entitiesArr[i].model.color = Cesium.Color.fromCssColorString(
                  this.modeColorObj[key]
                );
              }
            }
          }
        }
      }

      this.selModelId = null;
      this.isShowInfo = false;
    },

    // 更新地图
    updateMap() {
      let entities = null;

      if (this.$store.state.selDeviceData.length !== 0) {
        this.$store.state.selDeviceData.forEach((item) => {
          // 耿勋左侧弹框数据
          if (this.selModelId == item.id) {
            this.selModelInfo = JSON.parse(JSON.stringify(item));
          }

          // 更新圆锥模型
          if (
            item.position.hasOwnProperty("azimuthAngle") &&
            item.position.hasOwnProperty("pitchAngle")
          ) {
            if (this.primitiveObj.hasOwnProperty(`cone${item.id}`)) {
              // 更新圆锥方位俯仰
              this.updateCone(
                {
                  model: this.primitiveObj[`cone${item.id}`],
                  angel: item.position.azimuthAngle,
                  pitch: item.position.pitchAngle,
                },
                JSON.parse(JSON.stringify(item))
              );
            } else {
              // 生成模型颜色(随机颜色)
              this.$store.state.modelColor = {
                id: `cone${item.id}`,
                color: this.getColorUndertint(),
              };

              // 创建圆锥
              this.addCone(
                item,
                item.position.azimuthAngle,
                item.position.pitchAngle
              );
            }
          }

          // 更新飞机模型
          entities = viewer.entities.getById(item.id);
          if (entities) {
            this.updatePlane(JSON.parse(JSON.stringify(item)));
          } else {
            if (
              (item.status == "连接" && item.position.lon !== 0) ||
              item.position.lat !== 0
            ) {
              // 添加航迹数据(绘制航迹)
              this.aggregate[item.id] = [];

              this.aggregate[item.id].push(
                Cesium.Cartesian3.fromDegrees(
                  item.position.lon,
                  item.position.lat,
                  item.position.height
                )
              );

              // 模型参数
              this.modelInfo = {
                desc: JSON.parse(JSON.stringify(item)),
                type: "model",
              };

              // 创建模型
              this.addPlane(JSON.parse(JSON.stringify(this.modelInfo)));

              // 保存模型颜色信息
              this.modeColorObj[item.id] = JSON.parse(
                JSON.stringify(this.$store.state.modelColor.color)
              );
            }
          }
        });
      }
    },

    // -----------------------<<鼠标事件>>-----------------------
    // 左键单击
    leftClick() {
      // 添加用户输入监听范围(element)
      let handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);

      // 处理用户输入事件
      handler.setInputAction((event) => {
        let pick = viewer.scene.pick(event.position);

        if (Cesium.defined(pick)) {
          if (
            (pick.id._name && pick.id._name == "model") ||
            pick.id._name == "plat"
          ) {
            // 获取模型信息
            this.selModelInfo = JSON.parse(
              JSON.stringify(pick.id._description._value)
            );

            // 选中模型样式
            this.clickModel(pick.id._id);
          } else if (pick.id.name && pick.id.name == "cone") {
            // 选中模型样式
            this.clickModel(pick.id.id);

            // 获取模型信息
            this.selModelInfo = JSON.parse(JSON.stringify(pick.id.description));
            // 显示详细信息弹框
            this.isShowInfo = true;
          } else {
            return;
          }
        } else {
          this.deselectModel();
        }
      }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
    },

    // -----------------------<<其他操作>>-----------------------
    // 工具栏点击事件
    toolsClick(item) {
      switch (item.id) {
        case 1: // 2D/3D切换
          if (item.text == "3D") {
            item.text = "2D";

            // 切换为3D
            viewer.scene.morphTo3D(0);
          } else {
            item.text = "3D";

            // 切换为2D
            viewer.scene.morphTo2D(0);
          }
          break;
      }

      this.deselectModel();
    },

    // 过滤数据
    filterNumber(val, digit) {
      return val.toFixed(digit);
    },
  },
};
</script>

三、Css

<style lang="less" scoped>
#cesiumContainer {
  width: 100%;
  height: 100%;
  position: relative;

  .mapTools {
    position: absolute;
    top: 10px;
    right: 10px;
    border-radius: 5px;
    // background: rgba(255, 255, 255, 0.9);
    background-color: rgba(#001c22, 0.8);
    z-index: 999;
    color: #f73a0a;

    li {
      width: 35px;
      height: 35px;
      color: #fff;
      display: flex;
      align-items: center;
      justify-content: center;
      border-radius: 5px;
      cursor: pointer;

      .icon {
        font-size: 20px;
      }

      &:hover {
        background: #087b7a;
        color: #fff;
      }
    }
  }

  .leftFlatBox {
    position: absolute;
    left: 10px;
    top: 10px;
    z-index: 999;
    width: 280px;
    border: 1.5px solid #18d1d4;
    box-sizing: border-box;
    background-color: rgba(#087b7a, 0.3);
    color: #fff;
    font-size: 12px;

    ul {
      padding: 0px 5px;
      box-sizing: border-box;
      li {
        margin: 5px 0px;

        .subTitle {
          width: 60px;
          display: inline-block;
          background-color: #013946;
          border: 1px solid #18d1d4;
          margin-right: 5px;
          padding: 5px 5px;
          box-sizing: border-box;
        }
        .subValue {
          width: calc(100% - 65px);
          display: inline-block;
          border: 1px solid #18d1d4;
          background-color: #013946;
          padding: 5px 5px;
          box-sizing: border-box;
        }
      }
    }
  }
}
</style>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/609829.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

ARM(2)ARMv8基础知识

目录 一、异常 1.1异常等级的定义 1.2异常的种类 1.2.1同步异常和异步异常 1.3改变异常等级 1.4异常后的处理 1.4.1异常处理相关寄存器 1.4.2系统调用 1.4.3对EL2/EL3的系统调用 1.4.4异常返回 1.4.5异常处理流程 二、安全状态 三、执行状态 本文介绍以下内容&…

KUKA机器人X11投入运行模式

KUKA机器人出厂时有个X11外部安全插头&#xff0c;外部急停和安全门就是从其中引出双回路接线。正常使用时需要将插头内部短接&#xff0c;不短接则会出现外部安全停止等报警信息&#xff0c;导致机器人无法上使能&#xff0c;不能转动。 通过设置【投入运行模式】可以暂时屏蔽…

Linux 操作系统TCP、UDP

1、TCP服务器编写流程 头文件&#xff1a; #include <sys/socket.h> 1.1 创建套接字 函数原型&#xff1a; int socket(int domain, int type, int protocol); 参数&#xff1a; domain: 网域 AF_INET &#xff1a; IPv4 AF_INET6 &a…

大数据面试题 —— 数据库

目录 关系型数据库与非关系型数据库的区别数据库三范式MySQL中 drop、delete、truncate的区别MySQL中 char和 varchar 的区别MySQL中inner join、left join、right join以及full join的区别MySQL中 having 和 where 的区别count(*)、count(1)、count(列名)的区别MySQL中视图和表…

【C++】-类模板-002

1创建类模板 &#xff08;1&#xff09;新建工程 &#xff08;2&#xff09; &#xff08;3&#xff09; &#xff08;4&#xff09; &#xff08;5&#xff09;模板运行结果 2【UI】设计器 &#xff08;1&#xff09;跳转到【UI】设计器 &#xff08;2&#xff09;添加…

神经网络中的归一化

我们今天介绍一下神经网络中的归一化方法~ 之前学到的机器学习中的归一化是将数据缩放到特定范围内&#xff0c;以消除不同特征之间的量纲和取值范围差异。通过将原始数据缩放到一个特定的范围内&#xff0c;比如[0,1]或者[-1,1]&#xff0c;来消除不同特征之间的量纲和取值范围…

Ti雷达CFG阅读技巧

Ti雷达CFG阅读技巧 使用TI雷达测量数据前&#xff0c;需要考虑不同的设计参数之间的区别&#xff0c;虽然Ti雷达的说明文档非常清晰&#xff0c;直接查询mmwave_sdk_user_guide文档就可以了&#xff0c;但是用的多了&#xff0c;参数都知道可能是什么含义&#xff0c;来回查询…

Springboot集成Mybatispuls操作mysql数据库-04

MyBatis-Plus&#xff08;简称MP&#xff09;是一个MyBatis的增强工具&#xff0c;在MyBatis的基础上只做增强而不做改变。它支持所有MyBatis原生的特性&#xff0c;因此引入MyBatis-Plus不会对现有的MyBatis构架产生任何影响。MyBatis-Plus旨在简化开发、提高效率&#xff0c;…

商务分析方法与工具(七):Python的趣味快捷-异常处理结构

Tips&#xff1a;"分享是快乐的源泉&#x1f4a7;&#xff0c;在我的博客里&#xff0c;不仅有知识的海洋&#x1f30a;&#xff0c;还有满满的正能量加持&#x1f4aa;&#xff0c;快来和我一起分享这份快乐吧&#x1f60a;&#xff01; 喜欢我的博客的话&#xff0c;记得…

布局全球内容生态,酷开科技Coolita AIOS以硬核品质亮相

当前&#xff0c;全球产业链供应链格局持续重构&#xff0c;成为影响中国对外经济发展的重要因素。2024年4月15至5月5日&#xff0c;历史久、规模大、层次高&#xff0c;作为中国外贸风向标的第135届中国进出口商品交易会&#xff08;即广交会&#xff09;在美丽的广州隆重举行…

matlab打开文件对话框

在使用matlab GUI制作时&#xff0c;为了便于用户交互使用&#xff0c;经常设置文件打开对话框&#xff0c;让用户根据实际需要选择打开的文件。下面以打开一张图片为例&#xff0c;matlab代码如下&#xff1a; [temp_filepath,temp_filename]uigetfile(*.jpg,请选择要打开的图…

探秘Tailwind CSS:前端开发的加速器(TailwindCSS让CSS编写更简洁)

文章目录 📖 介绍 📖🏡 演示环境 🏡📒 Tailwind CSS 📒📝 快速体验📝 深入学习⚓️ 相关链接 ⚓️📖 介绍 📖 在这个快速迭代的互联网时代,前端开发效率和设计质量的双重要求,使得开发者们不断寻求更高效的工具和方法。今天,我们要介绍的是一个能够极大…

如何在Python中调用系统命令或执行外部程序?详细教程来了!

基本原理 在Python中执行程序或调用系统命令是一项非常实用的技能&#xff0c;这允许Python脚本与操作系统进行交互&#xff0c;执行各种外部程序。Python提供了多种方法来实现这一功能&#xff0c;包括os.system(), subprocess模块等。 示例代码 示例1&#xff1a;使用os.s…

LLM生态下爬虫程序的现状与未来

最近出现一批与LLM有关的新的爬虫框架&#xff0c;一类是为LLM提供内容抓取解析的&#xff0c;比如 Jina Reader 和 FireCrawl &#xff0c;可以将抓取的网页解析为markdown这样的对LLM友好的内容&#xff0c;例如markdown&#xff0c;这类本质上还是传统的爬虫解决方案。还有一…

[C++] const 成员函数

标题&#xff1a;[C] this指针 & const 成员函数 水墨不写bug 正文开始&#xff1a; 目录 &#xff08;一&#xff09;Cpp的面向对象编程 &#xff08;二&#xff09;this指针 &#xff08;三&#xff09;const修饰的成员函数 在正式讲解const修饰成员函数之前&#x…

在做题中学习(55):一维前缀和模板

【模板】前缀和_牛客题霸_牛客网 (nowcoder.com) 题目解释&#xff1a; 注意&#xff1a;下标从1开始的。 l 和 r就是对这n个整数去取一个区间&#xff0c;例如示例一&#xff1a; (1,2) 区间 就是算出1 2 4 中 1&#xff0c;2下标对应值的和&#xff0c;12 3 同理,(2,3) …

vscode正则匹配技巧

写正则表达式 下面是匹配加粗的单词或空格 \*\*[a-zA-Z\s]*\*\*vscode提取加粗的内容 altenter&#xff0c;再ctrlC复制选中的内容出来

前端 | iframe框架标签应用(三)| 点击指定部分,进行外部页面搜索,内置iframe返回搜索结果

文章目录 &#x1f4da;实现效果&#x1f4da;模块实现解析 &#x1f4da;实现效果 点击单词列表内的任意单词↓ 弹出对应单词的搜狗翻译搜索结果&#xff0c;点击关闭按钮关闭界面。 &#x1f4da;模块实现解析 在列表框搜索功能的基础上加一个click触发效果就好了&#xf…

网络安全在数字时代的重要性:以近期网络安全事件为镜

在当今这个信息化爆炸的时代&#xff0c;互联网如同一张无形的网&#xff0c;将我们的生活、工作、学习紧密相连。然而&#xff0c;这张网在带来便捷的同时&#xff0c;也暗藏着无数的安全隐患。近年来&#xff0c;网络安全事件频发&#xff0c;从个人隐私泄露到企业数据被盗&a…

网站未部署证书有何影响,如何解决?

如果您的网站没有ssl证书会有以下风险 1 浏览器标记为不安全 未安装证书的网站在访问时会有不安全的提示弹窗或者在网址栏直接显示不安全 2 影响企业信誉 当用户访问网站时看到不安全提示&#xff0c;会对网站的真实性和安全性产生怀疑&#xff0c;不敢轻易与该企业合作&…