cesium粒子效果——飞机喷口火焰效果

效果:


实现思路(最后有完整代码):

1.用clock组件创建时间线

2.时间轴和飞机的位置信息绑定

3.添加模型让模型按照绑定的位置飞行

4.创建粒子系统就是飞机的两个喷口

粒子所需图片地址链接:https://pan.baidu.com/s/12fUyDn6M_uyna5bGHTOvSQ 
提取码:1234

5.让粒子实时跟随模型移动


1.用clock组件创建时间线 代码:

 // 创建时间线
  var start = Cesium.JulianDate.fromDate(new Date()); // 设置时间轴当前时间为开始时间
  var start = Cesium.JulianDate.addHours(start, 8, new Cesium.JulianDate()); // 开始时间加8小时改为北京时间
  var stop = Cesium.JulianDate.addSeconds(start, 400, new Cesium.JulianDate()); // 设置结束时间为开始时间加400秒
  // 设置时钟开始时间
  viewer.clock.startTime = start.clone();
  // 设置时钟当前时间
  viewer.clock.currentTime = start.clone();
  // 设置时钟结束时间
  viewer.clock.stopTime = stop.clone();
  // 时间速率,数字越大时间过的越快,设置1好像是和实际时间一样
  viewer.clock.multiplier = 0.8;
  // 时间轴绑定到viewer上去
  //   viewer.timeline.zoomTo(start, stop);
  // 循环执行,到达终止时间,重新从起点时间开始
  viewer.clock.clockRange = Cesium.ClockRange.LOOP_STOP;

2.时间轴和飞机的位置信息绑定 代码:

//设置飞行轨迹  
var data = [
    {
      long: 111.110693,
      lat: 36.0994841,
      height: 10000,
      time: 0,
    },
    {
      long: 111.112693,
      lat: 35.0994841,
      height: 10000,
      time: 180,
    },
    {
      longe: 112.310693,
      lat: 34.0994841,
      height: 50000,
      time: 400,
    },
  ];

  let property = computeFlight(data); // 这是通过一个方法把时间轴和飞机的位置信息绑定了
  //   时间轴和飞机的位置信息绑定
  function computeFlight(source) {
    let property = new Cesium.SampledPositionProperty();
    for (let i = 0; i < source.length; i++) {
      let time = Cesium.JulianDate.addSeconds(
        start,
        source[i].time,
        new Cesium.JulianDate()
      );
      let position = Cesium.Cartesian3.fromDegrees(
        source[i].long,
        source[i].lat,
        source[i].height
      );
      // 添加位置,和时间对应
      property.addSample(time, position);
    }
    return property;
  }

3.添加模型让模型按照绑定的位置飞行 代码:

 //   添加并移动飞机
  var entity2 = viewer.entities.add({
    availability: new Cesium.TimeIntervalCollection([
      new Cesium.TimeInterval({
        start: start,
        stop: stop,
      }),
    ]),
    position: property,
    // 基于位置计算方向角
    orientation: new Cesium.VelocityOrientationProperty(property),
    model: {
      uri: "./model/j11.gltf",
      scale: 100.05, //放大倍数
    },
    // 画出飞行路径
    path: {
      resolution: 1, 
      material: new Cesium.PolylineGlowMaterialProperty({
        glowPower: 0.1, // 颜色透明度
        color: Cesium.Color.fromCssColorString("rgba(0, 253, 239, 0.5)"), // 路线颜色
      }),
      width: 2, // 路线的显示宽度
    },
  });
  // 视角跟随模型
  viewer.trackedEntity = entity2;

4.创建粒子系统就是飞机的两个喷口火焰效果

因为后面要更新粒子的位置 所以先搞个变量接一下 代码:

可以通过emitter给粒子设置不同样式

这里需要给粒子设置基于模型的位置偏移 不然粒子会在模型中心置  computeEmitterModelMatrix函数中设置

       // emitter: new Cesium.CircleEmitter(0.5), //粒子发射器样式 圆形
        emitter: new Cesium.ConeEmitter(Cesium.Math.toRadians(45.0)), //锥形
        // emitter: new Cesium.BoxEmitter(new Cesium.Cartesian3(1.0, 1.0, 1.0)), //方形
        // emitter: new Cesium.SphereEmitter(0.5), //球形
// 会有两个粒子 一个左喷口一个右喷口
  let particleSystemaArr = [];
  particleSystemaArr[0] = particleSystema(-932.5, -103.5, 201.0);
  particleSystemaArr[1] = particleSystema(-932.5, 103.5, 201.0);
  //   创建粒子系统 这个是最重要部分
  function particleSystema(z, x, y) {
    var particle;
    particle = viewer.scene.primitives.add(
      new Cesium.ParticleSystem({
        image: "./imgs/fire3.png",
        startScale: 70, //粒子图像的初始比例
        endScale: 80, //粒子图像的结束比例
        // lifetime: 1.0, //粒子系统发射粒子的时间(以秒为单位)。
        emissionRate: 55, //每秒要发射的粒子数
        //主模型参数(位置)
        // 发射器参数
        // emitter: new Cesium.CircleEmitter(0.5), //粒子发射器样式 圆形
        emitter: new Cesium.ConeEmitter(Cesium.Math.toRadians(45.0)), //锥形
        // emitter: new Cesium.BoxEmitter(new Cesium.Cartesian3(1.0, 1.0, 1.0)), //方形
        // emitter: new Cesium.SphereEmitter(0.5), //球形
        speed: 1,
        minimumParticleLife: 0.1, //粒子生命的可能持续时间的最小范围
        maximumParticleLife: 0.4, //粒子生命的可能持续时间的最大范围
        //颜色
        startColor: Cesium.Color.RED.withAlpha(0.7), //粒子在其生命初期的颜色
        endColor: Cesium.Color.YELLOW.withAlpha(0.5), //粒子在其生命结束的颜色
        modelMatrix: computeModelMatrix(entity2, Cesium.JulianDate.now()), //从模型转换为世界坐标的4x4转换矩阵
        emitterModelMatrix: computeEmitterModelMatrix(z, x, y), // 粒子发射器模型矩阵,粒子发射器位置
      })
    );
    return particle;
  }
  // 计算当前时间点飞机模型的位置矩阵
  function computeModelMatrix(entity, time) {
    //获取位置
    var position = Cesium.Property.getValueOrUndefined(
      entity2.position,
      time,
      new Cesium.Cartesian3()
    );
    if (!Cesium.defined(position)) {
      return undefined;
    }
    //获取方向
    var modelMatrix;
    var orientation = Cesium.Property.getValueOrUndefined(
      entity.orientation,
      time,
      new Cesium.Quaternion()
    );
    if (!Cesium.defined(orientation)) {
      modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(
        position,
        undefined,
        new Cesium.Matrix4()
      );
    } else {
      modelMatrix = Cesium.Matrix4.fromRotationTranslation(
        Cesium.Matrix3.fromQuaternion(orientation, new Cesium.Matrix3()),
        position,
        new Cesium.Matrix4()
      );
    }
    return modelMatrix;
  }

  // 粒子发射器位置
  function computeEmitterModelMatrix(x, y, z) {
    //方向
    var hpr = Cesium.HeadingPitchRoll.fromDegrees(
      0.0,
      0.0,
      0.0,
      new Cesium.HeadingPitchRoll()
    );
    var trs = new Cesium.TranslationRotationScale();

    //以modelMatrix(飞机模型)中心为原点的坐标系的xyz轴位置偏移
    trs.translation = Cesium.Cartesian3.fromElements(
      x,
      y,
      z,
      new Cesium.Cartesian3()
    );
    trs.rotation = Cesium.Quaternion.fromHeadingPitchRoll(
      hpr,
      new Cesium.Quaternion()
    );
    return Cesium.Matrix4.fromTranslationRotationScale(
      trs,
      new Cesium.Matrix4()
    );
  }

5.让粒子实时跟随模型移动 代码:

  // 粒子跟随模型
  viewer.scene.preRender.addEventListener(function (scene, time) {
    //重新计算位置
    particleSystemaArr[0].modelMatrix = computeModelMatrix(entity2, time);
    particleSystemaArr[1].modelMatrix = computeModelMatrix(entity2, time);
  });

全部完整代码:

<!--
 * @Author: pengxingjie 980133894@qq.com
 * @Date: 2024-01-09 10:57:30
 * @LastEditors: pengxingjie 980133894@qq.com
 * @LastEditTime: 2024-01-12 14:08:58
 * @FilePath: \pxjcesium-demo\src\components\API\DemoCase\PloneParticle.vue
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
-->
<template>
  <div class="btn"></div>
  <div>
    <Map />
  </div>
</template>

<script setup>
import Map from "@/components/map/Map.vue";
import { nextTick, onUnmounted, reactive } from "vue";
const person = reactive({});
nextTick(() => {
  // 创建时间线
  var start = Cesium.JulianDate.fromDate(new Date()); // 设置时间轴当前时间为开始时间
  var start = Cesium.JulianDate.addHours(start, 8, new Cesium.JulianDate()); // 开始时间加8小时改为北京时间
  var stop = Cesium.JulianDate.addSeconds(start, 400, new Cesium.JulianDate()); // 设置结束时间为开始时间加400秒
  // 设置时钟开始时间
  viewer.clock.startTime = start.clone();
  // 设置时钟当前时间
  viewer.clock.currentTime = start.clone();
  // 设置时钟结束时间
  viewer.clock.stopTime = stop.clone();
  // 时间速率,数字越大时间过的越快,设置1好像是和实际时间一样
  viewer.clock.multiplier = 0.8;
  // 时间轴绑定到viewer上去
  //   viewer.timeline.zoomTo(start, stop);
  // 循环执行,到达终止时间,重新从起点时间开始
  viewer.clock.clockRange = Cesium.ClockRange.LOOP_STOP;
  //   =================================================
  //设置飞行轨迹
  var data = [
    {
      longitude: 111.110693,
      dimension: 36.0994841,
      height: 10000,
      time: 0,
    },
    {
      longitude: 111.112693,
      dimension: 35.0994841,
      height: 10000,
      time: 180,
    },
    {
      longitude: 112.310693,
      dimension: 34.0994841,
      height: 50000,
      time: 400,
    },
  ];

  let property = computeFlight(data); // 这是通过一个方法把时间轴和飞机的位置信息绑定了
  //   时间轴和飞机的位置信息绑定
  function computeFlight(source) {
    let property = new Cesium.SampledPositionProperty();
    for (let i = 0; i < source.length; i++) {
      let time = Cesium.JulianDate.addSeconds(
        start,
        source[i].time,
        new Cesium.JulianDate()
      );
      let position = Cesium.Cartesian3.fromDegrees(
        source[i].longitude,
        source[i].dimension,
        source[i].height
      );
      // 添加位置,和时间对应
      property.addSample(time, position);
    }
    return property;
  }
  //   添加并移动飞机
  var entity2 = viewer.entities.add({
    availability: new Cesium.TimeIntervalCollection([
      new Cesium.TimeInterval({
        start: start,
        stop: stop,
      }),
    ]),
    position: property,
    // 基于位置计算方向角
    orientation: new Cesium.VelocityOrientationProperty(property),
    model: {
      uri: "./model/j11.gltf",
      scale: 100.05, //放大倍数
    },
    // 模拟的飞行路径
    path: {
      resolution: 1, //  这个不知道是啥
      material: new Cesium.PolylineGlowMaterialProperty({
        glowPower: 0.1, // 颜色透明度
        color: Cesium.Color.fromCssColorString("rgba(0, 253, 239, 0.5)"), // 路线颜色
      }),
      width: 2, // 路线的显示宽度
    },
  });
  // 视角跟随模型
  viewer.trackedEntity = entity2;
  // 计算当前时间点飞机模型的位置矩阵
  function computeModelMatrix(entity, time) {
    //获取位置
    var position = Cesium.Property.getValueOrUndefined(
      entity2.position,
      time,
      new Cesium.Cartesian3()
    );
    if (!Cesium.defined(position)) {
      return undefined;
    }
    //获取方向
    var modelMatrix;
    var orientation = Cesium.Property.getValueOrUndefined(
      entity.orientation,
      time,
      new Cesium.Quaternion()
    );
    if (!Cesium.defined(orientation)) {
      modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(
        position,
        undefined,
        new Cesium.Matrix4()
      );
    } else {
      modelMatrix = Cesium.Matrix4.fromRotationTranslation(
        Cesium.Matrix3.fromQuaternion(orientation, new Cesium.Matrix3()),
        position,
        new Cesium.Matrix4()
      );
    }
    return modelMatrix;
  }

  // 粒子发射器位置
  function computeEmitterModelMatrix(x, y, z) {
    //方向
    var hpr = Cesium.HeadingPitchRoll.fromDegrees(
      0.0,
      0.0,
      0.0,
      new Cesium.HeadingPitchRoll()
    );
    var trs = new Cesium.TranslationRotationScale();

    //以modelMatrix(飞机模型)中心为原点的坐标系的xyz轴位置偏移
    trs.translation = Cesium.Cartesian3.fromElements(
      x,
      y,
      z,
      new Cesium.Cartesian3()
    );
    trs.rotation = Cesium.Quaternion.fromHeadingPitchRoll(
      hpr,
      new Cesium.Quaternion()
    );
    return Cesium.Matrix4.fromTranslationRotationScale(
      trs,
      new Cesium.Matrix4()
    );
  }
  // 会有两个粒子 一个左喷口一个右喷口
  let particleSystemaArr = [];
  particleSystemaArr[0] = particleSystema(-932.5, -103.5, 201.0);
  particleSystemaArr[1] = particleSystema(-932.5, 103.5, 201.0);
  //   创建粒子系统
  function particleSystema(z, x, y) {
    var particle;
    particle = viewer.scene.primitives.add(
      new Cesium.ParticleSystem({
        image: "./imgs/fire3.png",
        startScale: 70, //粒子图像的初始比例
        endScale: 80, //粒子图像的结束比例
        // lifetime: 1.0, //粒子系统发射粒子的时间(以秒为单位)。
        emissionRate: 55, //每秒要发射的粒子数
        //主模型参数(位置)
        // 发射器参数
        // emitter: new Cesium.CircleEmitter(0.5), //粒子发射器样式 圆形
        emitter: new Cesium.ConeEmitter(Cesium.Math.toRadians(45.0)), //锥形
        // emitter: new Cesium.BoxEmitter(new Cesium.Cartesian3(1.0, 1.0, 1.0)), //方形
        // emitter: new Cesium.SphereEmitter(0.5), //球形
        speed: 1,
        minimumParticleLife: 0.1, //粒子生命的可能持续时间的最小范围
        maximumParticleLife: 0.4, //粒子生命的可能持续时间的最大范围
        //颜色
        startColor: Cesium.Color.RED.withAlpha(0.7), //粒子在其生命初期的颜色
        endColor: Cesium.Color.YELLOW.withAlpha(0.5), //粒子在其生命结束的颜色
        modelMatrix: computeModelMatrix(entity2, Cesium.JulianDate.now()), //从模型转换为世界坐标的4x4转换矩阵
        emitterModelMatrix: computeEmitterModelMatrix(z, x, y), // 粒子发射器模型矩阵,粒子发射器位置
      })
    );
    return particle;
  }

  // 粒子跟随模型
  viewer.scene.preRender.addEventListener(function (scene, time) {
    //重新计算位置
    particleSystemaArr[0].modelMatrix = computeModelMatrix(entity2, time);
    particleSystemaArr[1].modelMatrix = computeModelMatrix(entity2, time);
  });
});

onUnmounted(() => {});
</script>
<style scoped lang='less'>
.btn {
  position: absolute;
  left: 300px;
  top: 30px;
  z-index: 999;
}
</style>

  • 9
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
Cesium是一个用于创建地球和其他天体的3D地理信息系统(GIS)的开源JavaScript库。它提供了丰富的功能和效果,包括粒子系统。粒子系统是一种模拟和渲染大量小粒子的技术,可以用来创建各种特效,如雨雪雾天气、烟火、爆炸、喷泉等。 要在Cesium中实现粒子效果,你可以使用ParticleSystem类。通过实例化ParticleSystem对象,并调整其参数,你可以控制单个粒子对象随时间变化的外观和行为。例如,你可以设置粒子的发射速率、生命周期、颜色、大小和运行速度等。 下面是一个示例代码,演示了如何在Cesium中创建一个简单的粒子效果: ```javascript // 创建一个粒子系统 var particleSystem = new Cesium.ParticleSystem({ image: 'path/to/particle/image.png', // 粒子的图片 startScale: 1.0, // 初始缩放比例 endScale: 0.5, // 最终缩放比例 startColor: Cesium.Color.RED, // 初始颜色 endColor: Cesium.Color.YELLOW, // 最终颜色 particleLife: 5.0, // 粒子生命周期 speed: 10.0, // 粒子运行速度 emissionRate: 100.0 // 粒子发射速率 }); // 将粒子系统添加到场景中 viewer.scene.primitives.add(particleSystem); ``` 这段代码创建了一个粒子系统,使用了一个粒子图片,并设置了一些参数,如初始缩放比例、最终缩放比例、初始颜色、最终颜色、粒子生命周期、粒子运行速度和粒子发射速率。然后,将粒子系统添加到Cesium的场景中。 通过调整这些参数,你可以实现不同的粒子效果。例如,你可以更改粒子的图片、颜色、大小、速度等,以创建不同的特效。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

m0_63701303

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值