cesium实现圆扩散效果


Cesium实战系列文章总目录传送门

1.实现效果

在这里插入图片描述

2.实现方法

2.1调用

将实现过程封装成类js文件,在使用的过程中引入js直接调用即可。输入【中心点坐标、颜色、半径、持续时间】等参数即可。

// 圆扩散
const circleDiffusion = new CircleDiffusion(this.viewer);
circleDiffusion.add([113.944, 22.523, 20], "#F7EB08", 800, 9500);

2.2材质实现

CircleDiffusion类文件,不懂WebGL的朋友直接按上文调用即可,懂的朋友可参考代码自行修改。

/**
 * circleDiffusion:圆扩散
 * 参考gitee上的ts代码
 */

// 圆扩散
class CircleDiffusion {
    viewer;
    lastStageList;
    constructor(viewer) {
        this.viewer = viewer;
        this.lastStageList = [];
        // js语法的每行结尾的“分号”可写可不写
    }
    add(
        position,
        scanColor,
        maxRadius,
        duration
    ) {
        this.lastStageList.push(
            this.showCircleScan(position, scanColor, maxRadius, duration)
        )
    }
    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
         */
    showCircleScan(
            position,
            scanColor,
            maxRadius,
            duration
        ) {
            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
            )
            return lastStage
        }
        /**
         * 添加扩散效果扫描线
         * @param {*} cartographicCenter  扫描中心
         * @param {*} maxRadius 扫描半径
         * @param {*} scanColor  扫描颜色
         * @param {*} duration  持续时间
         */
    _addCircleScanPostStage(
            cartographicCenter,
            maxRadius,
            scanColor,
            duration
        ) {
            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 = this
            const ScanPostStage = new Cesium.PostProcessStage({
                fragmentShader: _this._getScanSegmentShader(),
                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.z
                        Cesium.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() {
            const inpram = 18
            const scanSegmentShader =
                ` uniform sampler2D colorTexture;
          uniform sampler2D depthTexture;
          varying vec2 v_textureCoordinates;
          uniform vec4 u_scanCenterEC;
          uniform vec3 u_scanPlaneNormalEC;
          uniform float u_radius;
          uniform vec4 u_scanColor;
          vec4 toEye(in vec2 uv, in float depth){
            vec2 xy = vec2((uv.x * 2.0 - 1.0),(uv.y * 2.0 - 1.0));
            vec4 posInCamera = czm_inverseProjection * vec4(xy, depth, 1.0);
            posInCamera =posInCamera / posInCamera.w;
            return posInCamera;
          }
          vec3 pointProjectOnPlane(in vec3 planeNormal, in vec3 planeOrigin, in vec3 point){
              vec3 v01 = point - planeOrigin;
              float d = dot(planeNormal, v01) ;
              return (point - planeNormal * d);
          }
          float getDepth(in vec4 depth){
              float z_window = czm_unpackDepth(depth);
              z_window = czm_reverseLogDepth(z_window);
              float n_range = czm_depthRange.near;
              float f_range = czm_depthRange.far;
              return (2.0 * z_window - n_range - f_range) / (f_range - n_range);
          }
          void main(){
              gl_FragColor = texture2D(colorTexture, v_textureCoordinates);
              float depth = getDepth(texture2D(depthTexture, v_textureCoordinates));
              vec4 viewPos = toEye(v_textureCoordinates, depth);
              vec3 prjOnPlane = pointProjectOnPlane(u_scanPlaneNormalEC.xyz, u_scanCenterEC.xyz, viewPos.xyz);
              float dis = length(prjOnPlane.xyz - u_scanCenterEC.xyz);
              if(dis < u_radius){
                float f = 1.0 - abs(u_radius - dis) / u_radius;
                f = pow(f, float(` + inpram + `));
                gl_FragColor = mix(gl_FragColor,u_scanColor,f);
              }
              gl_FragColor.a = gl_FragColor.a / 2.0;
          }
        `
            return scanSegmentShader
        }
        /**
         * 清除特效对象
         * @param {*} lastStage 特效对象
         */
    clearScanEffects(lastStage) {
        this.viewer.scene.postProcessStages.remove(lastStage)
    }
}
  • 5
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

右弦GISer

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

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

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

打赏作者

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

抵扣说明:

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

余额充值