Cesium模型封装-模型自动移动

11 篇文章 0 订阅

一、初始化地图

<template>
  <div class="cesium_map">
    <div id="cesiumContainer"></div>
  </div>
</template>

<script setup>
import { reactive, ref, onMounted } from "vue";
import { AutoModel } from "../../utils/Model";

// ---------------------------<<数据>>---------------------------
const me = reactive({
  point: null,
});

// 点位数组
const pointArr = reactive([
  {
    lon: 110.645025,
    lat: 22.03158,
    alt: 5000,
    time: null,
  },
  {
    lon: 110.645025,
    lat: 22.16643590658971,
    alt: 5000,
    time: null,
  },
  {
    lon: 110.7480626299661,
    lat: 22.261761037919744,
    alt: 5000,
    time: null,
  },
  {
    lon: 110.8937798546077,
    lat: 22.261761037919744,
    alt: 5000,
    time: null,
  },
  {
    lon: 110.99674745330135,
    lat: 22.16643590658971,
    alt: 5000,
    time: null,
  },
  {
    lon: 110.99674745330135,
    lat: 22.03158,
    alt: 5000,
    time: null,
  },
  {
    lon: 110.8937798546077,
    lat: 21.936190428417305,
    alt: 5000,
    time: null,
  },
  {
    lon: 110.7483984431316,
    lat: 21.936190428417305,
    alt: 5000,
    time: null,
  },
  {
    lon: 110.645025,
    lat: 22.03158,
    alt: 5000,
    time: null,
  },
]);

// 侧向线计时器
const lineTimer = ref(null);

// 侧向线路径
const aggregate = ref(
  Cesium.Cartesian3.fromDegreesArrayHeights([
    110.82474250408677, 22.095133670052277, 0, 110.645025, 22.03158, 5000,
  ])
);

// ---------------------------<<函数>>---------------------------
// 初始化地图
const initMap = () => {
  // 在线地图token
  Cesium.Ion.defaultAccessToken = "map_token";

  // 在线地图
  let imageryProvider = new Cesium.ArcGisMapServerImageryProvider({
    url: "map_url",
  });

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

  viewer.scene.globe.enableLighting = false;
  viewer.shadows = false;

  viewer.scene.globe.enableLighting = false;
  Cesium.Camera.DEFAULT_VIEW_FACTOR = 0.2; // 摄像机到地图的距离放大倍数
  viewer.camera.flyHome(0);

  // // 调整画面精细度
  viewer.resolutionScale = 1; //默认值为1.0
  viewer.scene.backgroundColor = Cesium.Color.TRANSPARENT;
  viewer.scene.globe.baseColor = Cesium.Color.TRANSPARENT;
  // //是否开启抗锯齿
  viewer.scene.fxaa = false;
  viewer.scene.postProcessStages.fxaa.enabled = false;
  viewer.scene.globe.showGroundAtmosphere = true;

  // 设置相机位置
  viewer.scene.camera.setView({
    destination: Cesium.Cartesian3.fromDegrees(
      110.82474250408677,
      22.095133670052277,
      80000
    ),
    orientation: {
      heading: Cesium.Math.toRadians(0),
      pitch: Cesium.Math.toRadians(-90),
      roll: 0.0,
    },
  });

  //取消双击事件
  viewer.cesiumWidget.screenSpaceEventHandler.removeInputAction(
    Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK
  );
};

// 初始化模型
const initModel = () => {
     // 请查看 “步骤三” 使用示例
};
// 初始化模型类
const initModelClass = () => {
  me.point = new AutoModel(viewer, Cesium);
};

// ---------------------------<<执行>>---------------------------
// 挂载后生命周期
onMounted(() => {
  initMap();
  initModelClass();
  initModel();
});
</script>

<style lang="less" scoped>
.cesium_map {
  width: 100%;
  height: 100%;

  #cesiumContainer {
    width: 100%;
    height: 100%;
  }
}
</style>

二、封装文件

// 自动运动模型
export class AutoModel {
  constructor(viewer, Cesium) {
    this.viewer = viewer
    this.Cesium = Cesium
  }

  // 计算线路
  calcRoute(source, startTime) {
    // 取样位置 相当于一个集合
    let property = new this.Cesium.SampledPositionProperty();
    for (let i = 0; i < source.length; i++) {
      let time = this.Cesium.JulianDate.addSeconds(
        startTime,
        source[i].time,
        new this.Cesium.JulianDate()
      );
      let position = this.Cesium.Cartesian3.fromDegrees(
        source[i].lon,
        source[i].lat,
        source[i].alt
      );
      // 添加位置,和时间对应
      property.addSample(time, position);
    }
    return property;
  }

  // 创建模型
  addModel(option, startTime, stopTime) {

    let {
      id,
      name,
      uri,
      minimumPixelSize,
      maximumScale,
      color,
      flyPath,
    } = option

    let property = this.calcRoute(flyPath, startTime);

    this.viewer.entities.add({
      id, //模型id
      name, // 模型名称,这里用作模型类型,方便场景模型增删改查
      // 和时间轴关联
      availability: new this.Cesium.TimeIntervalCollection([
        new Cesium.TimeInterval({
          start: startTime,
          stop: stopTime,
        }),
      ]),
      position: property, //模型位置,高度
      orientation: new this.Cesium.VelocityOrientationProperty(property),
      model: {
        uri, //模型文件
        minimumPixelSize, //模型最小像素大小
        maximumScale, //模型最大像素大小
        color
      },
    });
  }

  // 移动模型
  moveModel(option) {
    let {
      flyPath,
      multiplier,
      clockRange
    } = option

    let flyTime = 0

    for (let i = 0; i < flyPath.length; i++) {
      flyPath[i].time = flyTime;

      flyTime += 2;
    }

    // 起始时间
    var startTime = this.Cesium.JulianDate.fromDate(new Date());
    // 结束时间
    var stopTime = this.Cesium.JulianDate.addSeconds(
      startTime,
      flyPath[flyPath.length - 1].time,
      new this.Cesium.JulianDate()
    );

    // 设置始时钟始时间
    this.viewer.clock.startTime = startTime.clone();
    // 设置时钟当前时间
    this.viewer.clock.currentTime = stopTime.clone();
    // 设置始终停止时间
    this.viewer.clock.stopTime = stopTime.clone();
    // 时间速率,数字越大时间过的越快
    this.viewer.clock.multiplier = multiplier;
    // 时间轴
    // viewer.timeline.zoomTo(start.value, stop.value);
    // 循环执行,即为2,到达终止时间,重新从起点时间开始LOOP_STOP
    // viewer.clock.clockRange = Cesium.ClockRange.CLAMPED;
    this.viewer.clock.clockRange = clockRange;

    // 创建模型
    this.addModel(option, startTime, stopTime);
  }
}

三、使用示例

1、代码
const initModel = () => {
  let temp = ref([]);

  for (let i = 0; i < pointArr.length; i++) {
    // 绘制飞行线路坐标点
    me.point.entitiesPoint({
      id: "entitiesPoint" + i, // 点id
      position: Cesium.Cartesian3.fromDegrees(
        pointArr[i].lon,
        pointArr[i].lat,
        pointArr[i].alt
      ), // {lon,lat,alt}
    });

    temp.value.push(pointArr[i].lon, pointArr[i].lat, pointArr[i].alt);
  }

  // 绘制飞行线路
  me.line.entitiesLine({
    id: "solidLine", // 线条id***
    name: "solidLine", // 线条name***
    // 参数依次为[经度1, 纬度1, 高度1, 经度2, 纬度2, 高度2]
    positions: Cesium.Cartesian3.fromDegreesArrayHeights(temp.value), // 线条坐标***
    width: 2,
    material: Cesium.Color.fromCssColorString("tomato"), // 线条材质:通过材质控制线条类型***
    clampToGround: false, // 是否贴地
    zIndex: 1, // clampToGround = true才生效
    ddc: {
      start: 0,
      end: 150000000,
    }, //显示在距相机的距离处的属性,多少区间内是可以显示的
    show: true, // 是否显示线条
  });

  // 绘制测向线
  me.line.entitiesLine({
    id: "sideLine", // 线条id***
    name: "sideLine", // 线条name
    positions: new Cesium.CallbackProperty(() => {
      return aggregate.value;
    }, false), //  线条坐标***
    material: new Cesium.StripeMaterialProperty({
      evenColor: Cesium.Color.WHITE,
      oddColor: Cesium.Color.TOMATO,
      repeat: 3,
    }),
    width: 5, // 线条宽度
    clampToGround: false, // 是否贴地
    zIndex: 999, // 线条层级,clampToGround = true才生效
    ddc: {
      start: 0,
      end: 150000000,
    },
    show: true,
  });

  // 绘制移动模型***
  me.autoModel.moveModel({
    id: "autoModel", // 模型id
    name: "autoModel", // 模型name
    uri: "./model/test1.GLTF", // 模型文件
    minimumPixelSize: 100, // 模型最小
    maximumScale: 200, // 模型最大
    color: Cesium.Color.WHITE.withAlpha(1), // 模型颜色
    flyPath: pointArr, // 飞行线路
    multiplier: 0.2, // 飞行速度
    clockRange: Cesium.ClockRange.LOOP_STOP, // 飞行效果:循环
  });
};

// 更新测向线
const getCurrentPosition = () => {
  if (!lineTimer.value) {
    // 定时获取实体位置
    lineTimer.value = setInterval(() => {
      // 获取飞机模型
      let plane = viewer.entities.getById("autoModel");

      var planePosition = Cesium.Property.getValueOrDefault(
        plane._position,
        viewer.clock.currentTime,
        new Cesium.Cartesian3()
      );
      var cartographic = Cesium.Cartographic.fromCartesian(planePosition);
      var lon = Cesium.Math.toDegrees(cartographic.longitude);
      var lat = Cesium.Math.toDegrees(cartographic.latitude);

      aggregate.value = Cesium.Cartesian3.fromDegreesArrayHeights([
        110.82474250408677,
        22.095133670052277,
        0,
        lon,
        lat,
        cartographic.height,
      ]);
    }, 10);
  }
};
2、效果

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值