cesium通过着色器实现水波纹告警动画效果,如下图:
具体实现步骤:
1、新建CircleWaveMaterialProperty.js,加入下面的代码:
import * as Cesium from "cesium"; function CircleWaveMaterialProperty(ob) { this._definitionChanged = new Cesium.Event(); this._color = undefined; this._colorSubscription = undefined; this.color = ob.color; this.duration = Cesium.defaultValue(ob.duration, 1000); this.count = Cesium.defaultValue(ob.count, 2); if (this.count <= 0) { this.count = 1; } this.gradient = Cesium.defaultValue(ob.gradient, 0.1); if (this.gradient === 0) { this.gradient = 0; } if (this.gradient > 1) { this.gradient = 1; } this._time = new Date().getTime(); } Object.defineProperties(CircleWaveMaterialProperty.prototype, { isConstant: { get: function () { return false; }, }, definitionChanged: { get: function () { return this._definitionChanged; }, }, color: Cesium.createPropertyDescriptor("color"), duration: Cesium.createPropertyDescriptor("duration"), count: Cesium.createPropertyDescriptor("count"), }); CircleWaveMaterialProperty.prototype.getType = function (_time) { return Cesium.Material.CircleWaveMaterialType; }; CircleWaveMaterialProperty.prototype.getValue = function (time, result) { if (!Cesium.defined(result)) { result = {}; } result.color = Cesium.Property.getValueOrClonedDefault( this._color, time, Cesium.Color.WHITE, result.color ); result.time = ((new Date().getTime() - this._time) % this.duration) / this.duration; result.count = this.count; result.gradient = 1 + 10 * (1 - this.gradient); return result; }; CircleWaveMaterialProperty.prototype.equals = function (other) { const reData = this === other || (other instanceof CircleWaveMaterialProperty && Cesium.Property.equals(this._color, other._color)); return reData; }; // Cesium.CircleWaveMaterialProperty = CircleWaveMaterialProperty Cesium.Material.CircleWaveMaterialType = "CircleWaveMaterial"; Cesium.Material.CircleWaveSource = ` czm_material czm_getMaterial(czm_materialInput materialInput) { czm_material material = czm_getDefaultMaterial(materialInput); material.diffuse = 1.5 * color.rgb; vec2 st = materialInput.st; vec3 str = materialInput.str; float dis = distance(st, vec2(0.5, 0.5)); float per = fract(time); if (abs(str.z) > 0.001) { discard; } if (dis > 0.5) { discard; } else { float perDis = 0.5 / count; float disNum; float bl = .0; for (int i = 0; i <= 9; i++) { if (float(i) <= count) { disNum = perDis *float(i) - dis + per / count; if (disNum > 0.0) { if (disNum < perDis) { bl = 1.0 - disNum / perDis; } else if(disNum - perDis < perDis) { bl = 1.0 - abs(1.0 - disNum / perDis); } material.alpha = pow(bl, gradient); } } } } return material; } `; Cesium.Material._materialCache.addMaterial( Cesium.Material.CircleWaveMaterialType, { fabric: { type: Cesium.Material.CircleWaveMaterialType, uniforms: { color: new Cesium.Color(1, 0, 0, 1), time: 1, count: 1, gradient: 0.1, }, source: Cesium.Material.CircleWaveSource, }, translucent: function (material) { return true; }, } ); export default CircleWaveMaterialProperty
2、引入CircleWaveMaterialProperty
import CircleWaveMaterialProperty from "./lib/CircleWaveMaterialProperty";
3、通过ellipse的材质,将水波纹告警动画加入到场景中:
let circleWave = viewer.entities.add({ id: '1', position: Cesium.Cartesian3.fromDegrees(116.20, 39.53, 0), ellipse: { // height: position[2], semiMinorAxis: 1000, semiMajorAxis: 1000, material: new CircleWaveMaterialProperty({ duration: 3000, gradient: 0.5, color: new Cesium.Color.fromCssColorString('red'), count: 2, }), }, });