cesium 圈区域渐变一次性实现

359 阅读2分钟

在项目中,总会遇到一些 需要 逐渐变大的区域的实现效果,而变大到一定程度消失,需要保证页面不卡顿,如果采用 callbackProperty 或有卡顿现象,跳针现象,无法保证区域可操纵性,常使用方式:


window.viewer.entities.add({

position: Cesium.Cartesian3.fromDegrees(100, 21),

name: 'xxx',

ellipse: {

semiMinorAxis: new Cesium.CallbackProperty(changeR, false),

semiMajorAxis: new Cesium.CallbackProperty(changeR, false),

Material: Cesium.Color.RED,

}

})

  


function changeR () {

// increateR 增加量

// 增加量 为 增加速度 * 时间

return r + increateR (increateR = (newDate - oldDate) * speed)

}

为保证,需求,我们直接使材质发生变化,也就是直接作用到GPU 上,cesium 采用 material方式,常见的方法


// 创建一个圆形几何体

var circleGeometry = new Cesium.EllipseGeometry({

center: Cesium.Cartesian3.fromDegrees(100, 21), // 圆心位置

semiMinorAxis: explode.DamageRange,

semiMajorAxis: explode.DamageRange,

vertexFormat: Cesium.PerInstanceColorAppearance.VERTEX_FORMAT // 使用PerInstanceColorAppearance格式

});

  


// 创建一个实体实例

var instance = new Cesium.GeometryInstance({

geometry: circleGeometry,

attributes: {

color: new Cesium.ColorGeometryInstanceAttribute(0.0, 1.0, 1.0, 1.0) // 设置实体的颜色

},

id: 'circle' // 设置实例的id

});

window.viewer.scene.primitives.add({

geometryInstances: [instance],

appearance: new Cesium.EllipsoidSurfaceAppearance({

//

material: new Cesium.Material({

fabric: {

uniforms: {

u_color: new Cesium.Color(1.0, 0.0, 0.0, 0.3),

u_duration: explode.TimeToLast,

czm_frameNumberFraction: 1000,

},

source: `

czm_material czm_getMaterial(czm_materialInput materialInput) {

czm_material material = czm_getDefaultMaterial(materialInput);

vec2 st = materialInput.st;

float radius = length(st - vec2(0.5));

float t = fract(czm_frameNumber / (czm_frameNumberFraction * u_duration));

float timePercent = min(1.0, t);

if (timePercent >= 1.0) {

return material;

} else {

material.alpha = alpha;

material.diffuse = u_color.rgb;

return material.diffuse = u_color.rgb;

}

}

`

}

})

})

});

这种方法,实时计算alpha 值,可以做到区域随着变化而变化,但是并不能保证区域从零开始,于是


// 创建一个圆形几何体

var circleGeometry = new Cesium.EllipseGeometry({

center: Cesium.Cartesian3.fromDegrees(100, 21), // 圆心位置

semiMinorAxis: explode.DamageRange,

semiMajorAxis: explode.DamageRange,

vertexFormat: Cesium.PerInstanceColorAppearance.VERTEX_FORMAT // 使用PerInstanceColorAppearance格式

});

  


// 创建一个实体实例

var instance = new Cesium.GeometryInstance({

geometry: circleGeometry,

attributes: {

color: new Cesium.ColorGeometryInstanceAttribute(0.0, 1.0, 1.0, 1.0) // 设置实体的颜色

},

id: 'circle' // 设置实例的id

});

window.viewer.scene.primitives.add({

geometryInstances: [instance],

appearance: new Cesium.EllipsoidSurfaceAppearance({

//

material: new Cesium.Material({

fabric: {

uniforms: {

u_color: new Cesium.Color(1.0, 0.0, 0.0, 0.3),

u_duration: explode.TimeToLast,

u_frameNumber: 0.0,

czm_frameNumberFraction: 1000,

},

source: `

czm_material czm_getMaterial(czm_materialInput materialInput) {

czm_material material = czm_getDefaultMaterial(materialInput);

vec2 st = materialInput.st;

float radius = length(st - vec2(0.5));

float t = fract(u_frameNumber / (czm_frameNumberFraction * u_duration));

float timePercent = min(1.0, t);

if (timePercent >= 1.0) {

return material;

} else {

material.alpha = alpha;

material.diffuse = u_color.rgb;

return material.diffuse = u_color.rgb;

}

}

`

}

})

})

});

  


// 实时监控 u_frameNumber 变化

function timeExp () {

let _requestId = 0;

let _now = Date.now();

let that = this;

let _primitive = null;

function animationFrame () {

if (Math.floor(Date.now() - _now) > explode.TimeToLast * 1000) {

explodesCollection.remove(_primitive)

Cesium.cancelAnimationFrame(_requestId)

} else {

if (_primitive) {

_primitive.appearance.material.uniforms.u_frameNumber = Date.now() - _now;

} else {

_primitive = that.getById(explode.Handle)

}

_requestId = Cesium.requestAnimationFrame(animationFrame)

}

}

}

采用 此方法,可是实时计算区域变化,随着时间的推移从而采用 js控制 GPU 变化

如此,可实现,区域随时间的推演而材质发生变化的需求,如果量比较大,不会影响渲染效果