效果
封装类
优化了着色器代码;增加了边框大小调整参数,增加了清除效果方法
注:在页面销毁时需要调用清除方法
CircleDiffusion.clear()
/*** circleDiffusion:圆扩散特效封装类**/// 圆扩散
class CircleDiffusion {viewer;lastStageList;constructor(viewer) {this.viewer = viewer;this.lastStageList = [];// js语法的每行结尾的“分号”可写可不写}add(position,scanColor,maxRadius,duration,border) {this.lastStageList.push(this.showCircleScan(position, scanColor, maxRadius, duration, border))}clear() {this.lastStageList.forEach((ele) => {this.clearScanEffects(ele)})this.lastStageList = []}/*** 圆扩散* @param {*} position 扫描中心 如[117.270739,31.84309,32]* @param {*} scanColor 扫描颜色 如"rgba(0,255,0,1)"* @param {*} maxRadius 扫描半径,单位米 如1000米* @param {*} duration 持续时间,单位毫秒 如4000* @param {*} border 边框,如10*/showCircleScan(position,scanColor,maxRadius,duration,border) {const cartographicCenter = new Cesium.Cartographic(Cesium.Math.toRadians(position[0]),Cesium.Math.toRadians(position[1]),position[2])scanColor = new Cesium.Color.fromCssColorString(scanColor)const lastStage = this._addCircleScanPostStage(cartographicCenter,maxRadius,scanColor,duration,border)return lastStage}/*** 添加扩散效果扫描线* @param {*} cartographicCenter 扫描中心* @param {*} maxRadius 扫描半径* @param {*} scanColor 扫描颜色* @param {*} duration 持续时间* @param {*} border 边框,如10*/_addCircleScanPostStage(cartographicCenter,maxRadius,scanColor,duration,border) {const _Cartesian3Center =Cesium.Cartographic.toCartesian(cartographicCenter)const _Cartesian4Center = new Cesium.Cartesian4(_Cartesian3Center.x,_Cartesian3Center.y,_Cartesian3Center.z,1)const _CartograhpicCenter1 = new Cesium.Cartographic(cartographicCenter.longitude,cartographicCenter.latitude,cartographicCenter.height + 500)const _Cartesian3Center1 =Cesium.Cartographic.toCartesian(_CartograhpicCenter1)const _Cartesian4Center1 = new Cesium.Cartesian4(_Cartesian3Center1.x,_Cartesian3Center1.y,_Cartesian3Center1.z,1)const _time = new Date().getTime()const _scratchCartesian4Center = new Cesium.Cartesian4()const _scratchCartesian4Center1 = new Cesium.Cartesian4()const _scratchCartesian3Normal = new Cesium.Cartesian3()const _this = thisconst ScanPostStage = new Cesium.PostProcessStage({fragmentShader: _this._getScanSegmentShader(border),uniforms: {u_scanCenterEC: function() {const temp = Cesium.Matrix4.multiplyByVector(_this.viewer.camera._viewMatrix,_Cartesian4Center,_scratchCartesian4Center)return temp},u_scanPlaneNormalEC: function() {const temp = Cesium.Matrix4.multiplyByVector(_this.viewer.camera._viewMatrix,_Cartesian4Center,_scratchCartesian4Center)const temp1 = Cesium.Matrix4.multiplyByVector(_this.viewer.camera._viewMatrix,_Cartesian4Center1,_scratchCartesian4Center1)_scratchCartesian3Normal.x = temp1.x - temp.x_scratchCartesian3Normal.y = temp1.y - temp.y_scratchCartesian3Normal.z = temp1.z - temp.zCesium.Cartesian3.normalize(_scratchCartesian3Normal,_scratchCartesian3Normal)return _scratchCartesian3Normal},u_radius: function() {return ((maxRadius * ((new Date().getTime() - _time) % duration)) / duration)},u_scanColor: scanColor,},})this.viewer.scene.postProcessStages.add(ScanPostStage)return ScanPostStage}/*** 扩散效果Shader*/_getScanSegmentShader(border) {const scanSegmentShader =" uniform sampler2D colorTexture;\n\uniform sampler2D depthTexture;\n\in vec2 v_textureCoordinates;\n\uniform vec4 u_scanCenterEC;\n\uniform vec3 u_scanPlaneNormalEC;\n\uniform float u_radius;\n\out vec4 myOutputColor;\n\uniform vec4 u_scanColor;\n\\n\vec4 toEye(in vec2 uv, in float depth){\n\vec2 xy = vec2((uv.x * 2.0 - 1.0),(uv.y * 2.0 - 1.0));\n\vec4 posInCamera = czm_inverseProjection * vec4(xy, depth, 1.0);\n\posInCamera =posInCamera / posInCamera.w;\n\return posInCamera;\n\}\n\\n\vec3 pointProjectOnPlane(in vec3 planeNormal, in vec3 planeOrigin, in vec3 point){\n\vec3 v01 = point - planeOrigin;\n\float d = dot(planeNormal, v01) ;\n\return (point - planeNormal * d);\n\}\n\\n\float getDepth(in vec4 depth){\n\float z_window = czm_unpackDepth(depth);\n\z_window = czm_reverseLogDepth(z_window);\n\float n_range = czm_depthRange.near;\n\float f_range = czm_depthRange.far;\n\return (2.0 * z_window - n_range - f_range) / (f_range - n_range);\n\}\n\\n\void main(){\n\myOutputColor = texture(colorTexture, v_textureCoordinates);\n\float depth = getDepth(texture(depthTexture, v_textureCoordinates));\n\vec4 viewPos = toEye(v_textureCoordinates, depth);\n\vec3 prjOnPlane = pointProjectOnPlane(u_scanPlaneNormalEC.xyz, u_scanCenterEC.xyz, viewPos.xyz);\n\float dis = length(prjOnPlane.xyz - u_scanCenterEC.xyz);\n\if(dis < u_radius){\n\float f = 1.0 - abs(u_radius - dis) / u_radius;\n\f = pow(f, float(" +border +"));\n\myOutputColor = mix(myOutputColor, u_scanColor, f);\n\}\n\}\n\"return scanSegmentShader}/*** 清除特效对象* @param {*} lastStage 特效对象*/clearScanEffects(lastStage) {this.viewer.scene.postProcessStages.remove(lastStage)}
}
调用方式
circleDiffusion = new CircleDiffusion(this.c_viewer);circleDiffusion.add([104.08985268964015, 30.635443158056148, 10.0], "rgba(0,255,0,1)", 3000, 3500,10);