import { Cesium } from '../../../namespace'
import {
calculateAngle,
changeHeight,
transformCartesianToWGS84,
} from '../Coordinate'
import { getStaticFile, mergedObj } from '../Generate'
import { getDistanceTwo } from '../Measure'
/**
* 水枪粒子
* @class
*/
class WaterGunEffect {
/**
* 构造函数
* @param {Object} viewer 地图场景对象
* @param {Cartesian3} sourcePos 起始点位置,笛卡尔坐标
* @param {Cartesian3} targetPos 目标点位置,笛卡尔坐标
* @param {WaterGunOption} options 粒子参数
*/
constructor(viewer, sourcePos, targetPos, options = {}) {
this.viewer = viewer
const pos0 = transformCartesianToWGS84(sourcePos)
const pos1 = transformCartesianToWGS84(targetPos)
const angleX = calculateAngle(pos0, pos1)
const dis = getDistanceTwo(
{ x: pos0.x, y: pos0.y },
{ x: pos1.x, y: pos1.y }
)
const DEF_WATER_GUN = {
angle: 30,
gravity: (-2.0 * dis) / (pos0.z - pos1.z),
speed: Math.ceil(dis / 5),
}
this.options = mergedObj(DEF_WATER_GUN, options)
this.viewModel = {
startScale: 1,
endScale: 5,
minimumParticleLife: 25,
maximumParticleLife: 30,
minimumSpeed: this.options.speed,
maximumSpeed: this.options.speed + 1,
emissionRate: 150,
}
this.emitterModelMatrix = new Cesium.Matrix4()
this.translation = new Cesium.Cartesian3()
this.rotation = new Cesium.Quaternion()
this.hpr = new Cesium.HeadingPitchRoll()
this.trs = new Cesium.TranslationRotationScale()
this.scene = this.viewer.scene
this.particleSystem = ''
let center = new Cesium.Cartesian3()
Cesium.Cartesian3.midpoint(sourcePos, targetPos, center)
this.position = changeHeight(center, dis * 5)
this.entity = this.viewer.entities.add({
//选择粒子放置的坐标
position: sourcePos,
})
this.angleX = angleX + 90
this._gravity = options.gravity
this.angleY = options.angle
this.init()
}
/**
* 发射角度
* @type {Number}
*/
get angle() {
return this.angleY
}
set angle(val) {
this.angleY = val
}
/**
* 重力因子
* @type {Number}
*/
get gravity() {
return this._gravity
}
set gravity(val) {
this._gravity = val
}
init() {
const _this = this
this.viewer.clock.shouldAnimate = true
var particleSystem = this.scene.primitives.add(
new Cesium.ParticleSystem({
image: getStaticFile('water1.png'), //生成所需粒子的图片路径
//粒子在生命周期开始时的颜色
startColor: new Cesium.Color(1, 1, 1, 0.6),
//粒子在生命周期结束时的颜色
endColor: new Cesium.Color(0.8, 0.86, 1, 0.4),
//粒子在生命周期开始时初始比例
startScale: _this.viewModel.startScale,
//粒子在生命周期结束时比例
endScale: _this.viewModel.endScale,
//粒子发射的最小速度
minimumParticleLife: _this.viewModel.minimumParticleLife,
//粒子发射的最大速度
maximumParticleLife: _this.viewModel.maximumParticleLife,
//粒子质量的最小界限
minimumSpeed: _this.viewModel.minimumSpeed,
//粒子质量的最大界限
maximumSpeed: _this.viewModel.maximumSpeed,
//以像素为单位缩放粒子图像尺寸
imageSize: new Cesium.Cartesian2(10, 10),
//每秒发射的粒子数
emissionRate: _this.viewModel.emissionRate,
//粒子系统发射粒子的时间(秒)
lifetime: 16.0,
//设置粒子的大小是否以米或像素为单位
sizeInMeters: true,
//系统的粒子发射器
emitter: new Cesium.CircleEmitter(2.0), //BoxEmitter 盒形发射器,ConeEmitter 锥形发射器,SphereEmitter 球形发射器,CircleEmitter圆形发射器
//回调函数,实现各种喷泉、烟雾效果
updateCallback: (p, dt) => {
return this.applyGravity(p, dt)
},
})
)
this.particleSystem = particleSystem
this.preUpdateEvent()
}
//场景渲染事件
preUpdateEvent() {
let _this = this
this.viewer.scene.preUpdate.addEventListener(function (scene, time) {
_this.particleSystem.modelMatrix = _this.computeModelMatrix(
_this.entity,
time
)
_this.particleSystem.emitterModelMatrix =
_this.computeEmitterModelMatrix()
})
}
computeModelMatrix(entity, time) {
return entity.computeModelMatrix(time, new Cesium.Matrix4())
}
computeEmitterModelMatrix() {
this.hpr = Cesium.HeadingPitchRoll.fromDegrees(
this.angleX,
this.angleY,
0.0,
this.hpr
) // 倾斜角度
this.trs.translation = Cesium.Cartesian3.fromElements(
0,
0,
0.1,
this.translation
) // 发射高度
this.trs.rotation = Cesium.Quaternion.fromHeadingPitchRoll(
this.hpr,
this.rotation
)
return Cesium.Matrix4.fromTranslationRotationScale(
this.trs,
this.emitterModelMatrix
)
}
applyGravity(p, dt) {
var gravityScratch = new Cesium.Cartesian3()
var position = p.position
Cesium.Cartesian3.normalize(position, gravityScratch)
Cesium.Cartesian3.multiplyByScalar(
gravityScratch,
this.gravity * dt,
gravityScratch
)
p.velocity = Cesium.Cartesian3.add(p.velocity, gravityScratch, p.velocity)
}
removeEvent() {
this.viewer.scene.preUpdate.removeEventListener(this.preUpdateEvent, this)
this.emitterModelMatrix = undefined
this.translation = undefined
this.rotation = undefined
this.hpr = undefined
this.trs = undefined
}
/**
* 移除水枪粒子
*/
remove() {
;() => {
return this.removeEvent()
} //清除事件
this.viewer.scene.primitives.remove(this.particleSystem) //删除粒子对象
this.viewer.entities.remove(this.entity) //删除entity
}
}
export default WaterGunEffect