基于cesium实现飞机延航线飞行并可实时增加航线

前言:基于cesium实现飞机延航线飞行并可实时增加航线

效果:基于cesium飞机飞行航线视频_哔哩哔哩_bilibili

思路:

        1.创建cesium (省略.....)

        2.理清需要那些功能,在这里我们用到了cesium得画点,画线,画面,以及cesium时间控件,对时间轴进行设置等

        3.接下来就开始创作了,其中还有一些细节,大家自行体会,

万年不变老开头

话不多说直接上代码

完整代码如下,当然还有一些缺陷或者bug,请大家指正,我会改进

以下是调用代码及参数

有一点功能需要引用turf.js来进行每个间距的距离计算

turf官网: Turf.js中文网

turf引用  在线:    <script src="https://unpkg.com/@turf/turf/turf.min.js"></script>

      //   ----------------------
      let demoPointArr = [
        [105.688371, 25.289973, 10000],
        [109.161164, 25.878748, 15000],
        [109.468776, 27.102328, 30000],
        [104.196792, 26.691527, 25000],
        [105.380841, 28.098639, 20000],
        [111.151287, 30.029206, 15000],
        [106.574412, 30.015039, 15000],
        [103.906272, 32.108362, 30000],
        [110.544005, 32.318148, 10000],
      ];
      let demoGonArr = [
        [105.688371, 25.289973, 10000],
        [109.161164, 25.878748, 15000],
        [109.468776, 27.102328, 150000],
        [111.151287, 30.029206, 15000],
        [110.544005, 32.318148, 10000],
        [103.906272, 32.108362, 90000],
        [104.19679, 26.691527, 40000],
        [105.688371, 25.289973, 10000],
      ];
      mapFunc.flyTo({
        lng: demoPointArr[4][0],
        lat: demoPointArr[4][1],
        elevation: 3000000,
      });
      //   加载模拟飞行
      flyDemo.implement(demoPointArr, demoGonArr);
      // 改变速度
      document.getElementById("speedInput").onchange = (val) => {
        // console.log(val.target.value);
        flyDemo.changeSpeed(Number(val.target.value));
      };
      // 视角改变
      // 俯视
      function btnTopView() {
        flyDemo.topView();
      }
      // 平视
      function btnHorizontals() {
        flyDemo.horizontals();
      }
      // 视角跟随
      function btnPerspectiveFollowing() {
        flyDemo.perspectiveFollowing();
      }
      // 增加飞行轨迹
      function btnAddFlyTrajectory() {
        let demo1 = [
          ...demoPointArr,
          ...[
            [105.989995, 34.250554, 15000],
            [112.616139, 33.883412, 10000],
          ],
        ];
        // .push(
        //   ...[
        //     [105.989995, 34250554, 15000],
        //     [112.616139, 33883412, 10000],
        //   ]
        // );
        console.log("ddd", demo1);
        flyDemo.addFlyTrajectory(demo1);
      }

以下为执行代码 

let flyEntity = null;
let cylinderDemo = null;
let startTime = Cesium.JulianDate.fromDate(new Date());
let endTime = null;
let allTime = null;
let nodeTimeArr = [0];
let timeInterval = 30;
const flyDemo = {
  implement: (demoPointArr = [], demoGonArr = []) => {
    // console.log(9999999, demoPointArr);
    // 线数据
    let lineDataArr = [];
    // 画点
    demoPointArr.forEach((a, n) => {
      flyDemo.drawPonit(a, n);
      lineDataArr.push(...a);
    });
    // 画线
    flyDemo.drawPolyline(lineDataArr);
    // 画面
    // flyDemo.drawPlaygon(demoGonArr);
    // 加载模拟飞行
    flyDemo.loadSimulationFly(demoPointArr);
  },
  // 画点
  drawPonit: (lonAndLat, num) => {
    // return
    const entityPoint = viewer.entities.add({
      position: Cesium.Cartesian3.fromDegrees(...lonAndLat),
      name: "point_name",
      point: {
        color: Cesium.Color.fromCssColorString("#fc3d4a"),
        outlineColor: Cesium.Color.fromCssColorString("#fc3d4a"),
        pixelSize: 11,
      },
      label: {
        show: true,
        text: String(num),
        font: "normal 22px MicroSoft YaHei",
        fillColor: Cesium.Color.WHITE,
        style: Cesium.LabelStyle.FILL_AND_OUTLINE,
        outlineWidth: 1,
        verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
        pixelOffset: new Cesium.Cartesian2(0, -20),
        showBackground: !0,
        backgroundColor: new Cesium.Color(0, 0, 0, 0),
      },
    });
    return entityPoint;
  },
  // 画线
  drawPolyline: (lineArr) => {
    const entityLine = viewer.entities.add({
      name: "polyline_name",
      polyline: {
        positions: Cesium.Cartesian3.fromDegreesArrayHeights(lineArr),
        width: 5,
        material: Cesium.Color.fromCssColorString("#fcc31f"),
      },
    });
    return entityLine;
  },
  // 画面
  drawPlaygon: (gonArr) => {
    let lonLats = (data) => {
      let arr = [];
      for (let d in data) {
        //判断经纬度范围
        if (
          data[d][0] >= -180 &&
          data[d][0] <= 180 &&
          data[d][1] >= -90 &&
          data[d][1] <= 90
        ) {
          arr.push(data[d][0], data[d][1]);
        } else {
          console.log("经纬度数值不对:", data[d][0], data[d][1]);
        }
      }
      return arr;
    };
    const entityPolygon = viewer.entities.add({
      name: "polyGon_name",
      polygon: {
        clampToGround: true, //开启贴地
        hierarchy: new Cesium.PolygonHierarchy(
          Cesium.Cartesian3.fromDegreesArray(lonLats(gonArr))
        ),
        material: Cesium.Color.BLUE.withAlpha(0.5),
        // distanceDisplayCondition: new Cesium.DistanceDisplayCondition(0, 300000)
      },
    });
    return entityPolygon;
  },
  // 画锥体
  drawCylinder: (lonAndLat) => {
    const cylinderEntity = viewer.entities.add({
      name: "cylinder_name",
      position: Cesium.Cartesian3.fromDegrees(
        lonAndLat[0],
        lonAndLat[1],
        lonAndLat[2]
      ),
      cylinder: {
        length: 1,
        topRadius: 0.0,
        bottomRadius: 40000.0,
        // outline: true,
        // outlineColor: Cesium.Color.WHITE,
        // outlineWidth: 4,
        // material: Cesium.Color.fromRandom({ alpha: 1.0 }),#dddddd
        material: new Cesium.Color.fromCssColorString("#dddddd"),
      },
    });
    return cylinderEntity;
  },
  // 画模型
  drawModel: (lonAndLat, startTime, endTime, propertyFly) => {
    const flyEntityDemo = viewer.entities.add({
      // 与时间进行关联
      availability: new Cesium.TimeIntervalCollection([
        new Cesium.TimeInterval({
          start: startTime,
          stop: endTime,
        }),
      ]),
      id: "demo",
      position: Cesium.Cartesian3.fromDegrees(
        lonAndLat[0],
        lonAndLat[1],
        lonAndLat[2] * 10
      ),
      orientation: new Cesium.VelocityOrientationProperty(propertyFly),
      model: {
        uri: "./Cesium_Air.glb",
        minimumPixelSize: 128,
      },
      // 飞行路径
      path: {
        resolution: 1,
        material: new Cesium.PolylineGlowMaterialProperty({
          glowPower: 0.1,
          color: Cesium.Color.YELLOW,
        }),
        // leadTime、trailTime 不设置 path全显示
        // leadTime:0,// 设置为0时 模型通过后显示path
        // trailTime: 0,// 设置为0时 模型通过后隐藏path
        width: 10,
      },
    });
    return flyEntityDemo;
  },

  // 加载模拟飞行

  loadSimulationFly: (demoPointArr = []) => {
    // 获取总时间和节点时间
    flyDemo.getAllTime(demoPointArr);
    // 配置飞行轨迹时间线
    flyDemo.setTimeLine();

    // 根据模拟数据创建对应时间与坐标的SampledPositionProperty并生成entity实体
    // 创建SampledPositionProperty
    // 设置到每一个点位的时间和坐标进行关联
    // 飞机
    const propertyFlyData = flyDemo.mapPropertyData(demoPointArr, "fly");
    // 锥体
    const propertyCylinderData = flyDemo.mapPropertyData(
      demoPointArr,
      "cylinder"
    );

    // ----------
    // 画锥体
    cylinderDemo = flyDemo.drawCylinder(demoPointArr[0]);

    // --------
    // ----------
    // 画模型
    flyEntity = flyDemo.drawModel(
      demoPointArr[0],
      startTime,
      endTime,
      propertyFlyData
    );

    // --------
    cylinderDemo.position = propertyCylinderData;
    flyEntity.position = propertyFlyData;
  },
  // 改变速度
  changeSpeed: (val = Number) => {
    // console.log("speed 改变速度");
    viewer.clock.multiplier = val;
  },
  // 视角改变
  // 俯视
  topView: () => {
    viewer.trackedEntity = undefined;
    viewer.zoomTo(
      flyEntity,
      new Cesium.HeadingPitchRange(0, Cesium.Math.toRadians(-90), 2000000)
    );
  },
  // 平视
  horizontals: () => {
    viewer.trackedEntity = undefined;
    viewer.zoomTo(
      flyEntity,
      new Cesium.HeadingPitchRange(
        Cesium.Math.toRadians(-90),
        Cesium.Math.toRadians(-15),
        2000000
      )
    );
  },
  // 视角跟随
  perspectiveFollowing: () => {
    flyEntity.viewFrom = new Cesium.Cartesian3(0.0, -1000.0, 1500.0);
    viewer.trackedEntity = flyEntity;
  },
  // 增加飞行轨迹
  addFlyTrajectory: (val) => {
    // console.log(val);
    flyDemo.getAllTime(val);
    // 设置到每一个点位的时间和坐标进行关联
    // 飞机
    const propertyFlyData = flyDemo.mapPropertyData(val, "fly");
    // 锥体
    const propertyCylinderData = flyDemo.mapPropertyData(val, "cylinder");
    // 设置阴影
    cylinderDemo.position = propertyCylinderData;
    // console.log("ddd flyEntity", flyEntity);
    // 设置飞机
    // 设置结束时间
    endTime = Cesium.JulianDate.addSeconds(
      startTime,
      allTime,
      new Cesium.JulianDate()
    );
    flyEntity.position = propertyFlyData;
    flyEntity.availability = new Cesium.TimeIntervalCollection([
      new Cesium.TimeInterval({
        start: startTime,
        stop: endTime,
      }),
    ]);
    flyEntity.orientation = new Cesium.VelocityOrientationProperty(
      propertyFlyData
    );
    // 设置时间轴
    // 设置结束时间
    viewer.clock.stopTime = endTime.clone();
    // 设置时间轴
    viewer.timeline.zoomTo(startTime, endTime);
  },
  // 设置时间轴
  setTimeLine: () => {
    // 配置飞行轨迹时间线
    // 1.设置两点之间飞行所用时间间隔
    timeInterval = 30;
    // 2.计算飞完一整个航线所需要的时间
    // console.log(allTime);
    // 3.设置起始时间即获取当前时间
    // console.log(startTime);
    // 4.获取结束时间
    endTime = Cesium.JulianDate.addSeconds(
      startTime,
      allTime,
      new Cesium.JulianDate()
    );
    // 5.设置时钟
    // 开始时间
    viewer.clock.startTime = startTime.clone();
    // 设置当前时间
    viewer.clock.currentTime = startTime.clone();
    // 设置结束时间
    viewer.clock.stopTime = endTime.clone();
    // 设置飞行速率 (飞行速度)
    viewer.clock.multiplier = 20;
    // 循环飞行
    viewer.clock.clockRange = Cesium.ClockRange.LOOP_STOP;
    // 设置时间轴
    viewer.timeline.zoomTo(startTime, endTime);
  },
  // 获取总用时
  getAllTime: (data) => {
    allTime = 0;
    nodeTimeArr = [0];
    for (let i = 0; i < data.length; i++) {
      // console.log("ddd i ", i);
      if (i < data.length - 1) {
        let from = turf.point([data[i][0], data[i][1]]);
        let to = turf.point([data[i + 1][0], data[i + 1][1]]);
        let options = { units: "kilometers" };
        let distance = turf.distance(from, to, options);
        // console.log("ddd distance", Math.round(distance / timeInterval));
        allTime = allTime + Math.round(distance / timeInterval);
        nodeTimeArr.push(allTime);
      }
      // console.log("ddd 2", allTime);
    }
  },
  // 数据处理
  mapPropertyData: (data, isFlyOrCylinder) => {
    // 根据模拟数据创建对应时间与坐标的SampledPositionProperty并生成entity实体
    // 创建SampledPositionProperty
    let property = new Cesium.SampledPositionProperty();
    for (let i = 0; i < data.length; i++) {
      // console.log("ddd nodeTimeArr[i]", nodeTimeArr[i]);

      // 获取到点的时间
      let time = Cesium.JulianDate.addSeconds(
        startTime,
        nodeTimeArr[i], //+2是给一个基础默认时间
        new Cesium.JulianDate()
      );

      // console.log("ddd time", time);
      // 获取点位
      let position = Cesium.Cartesian3.fromDegrees(
        data[i][0],
        data[i][1],
        isFlyOrCylinder == "fly" ? data[i][2] * 10 : data[i][2]
      );
      // 将时间和位置进行关联
      // console.log('ddd property',property);
      property.addSample(time, position);
    }

    return property;
  },
  // 屏幕坐标转化成经纬度
  Cartesian3_to_WGS84: (point) => {
    let cartesian3 = new Cesium.Cartesian3(point.x, point.y, point.z);
    let cartographic = Cesium.Cartographic.fromCartesian(cartesian3);
    let lat = Cesium.Math.toDegrees(cartographic.latitude);
    let lng = Cesium.Math.toDegrees(cartographic.longitude);
    let alt = cartographic.height;
    return {
      lat: lat,
      lng: lng,
      alt: alt,
    };
  },
};

最后谢谢大家观看,第一次创作,感谢大家!

如有不好的地方,欢迎指正.

也作为在工作当中的积累,展示在这里.

同时也欢迎技术交流,本人cesium小白,热爱学习,希望学到更多!

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值