Cesium实现的光柱效果

Cesium实现的光柱效果

效果展示:

image-20230305084843285

可以通过拼接两个entity来实现这个效果:

全部代码;

index.html

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <title>光柱</title>


    <script src="https://cdn.bootcdn.net/ajax/libs/cesium/1.97.0/Cesium.js"></script>
    <link href="https://cdn.bootcdn.net/ajax/libs/cesium/1.102.0/Widgets/widgets.min.css" rel="stylesheet">

    <style>
        html,
        body,
        #cesiumContainer {
            width: 100%;
            height: 100%;
            margin: 0;
            padding: 0;
            overflow: hidden;
        }
    </style>
</head>

<body>

    <div id="cesiumContainer"></div>



    <script type="module">


        import { ConeGlow } from './ConeGlow.js'



        const viewer = new Cesium.Viewer('cesiumContainer', {

            infoBox: false,
            selectionIndicator: false,
            navigation: false,
            animation: false,
            shouldAnimate: false,
            timeline: false,
            baseLayerPicker: false,
            geocoder: false,
            homeButton: false,
            sceneModePicker: false,
            navigationHelpButton: false,

            imageryProvider: new Cesium.UrlTemplateImageryProvider({
                url: "https://webst02.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}"
            })

        });





 ;
        let goneGlow = new ConeGlow(viewer, Cesium.Cartesian3.fromDegrees(113.222 , 23.222 ), {
            height: 5000,
            bottomRadius: 200,
            color: Cesium.Color.RED
        });


        new ConeGlow(viewer, Cesium.Cartesian3.fromDegrees(113.233 , 23.223 ), {
            height: 5000,
            bottomRadius: 200,
            color: Cesium.Color.GREEN
        });


 
        viewer.scene.camera.flyTo({  destination: Cesium.Cartesian3.fromDegrees(113.222 , 23.222  , 30000)  });




    </script>
</body>

</html>

ConeGlow.js

import "./ConeGlowMaterial/BottomCircle.js";
import "./ConeGlowMaterial/BottomRotateCircle.js";

export   class ConeGlow {
    constructor(viewer, position, options) {
        this.viewer = viewer;
        this.position = position;

        this.options = options; //color 颜色 height 光柱高度 bottomRadius 底部圆的半径
        this.height = options.height || 300;
        this.bottomRadius = options.bottomRadius || 30;
        this.color = options.color || Cesium.Color.AQUA; //给个亮亮的颜色

        this.addCone();
        this.addBottomCircle();
        this.addBottomRotateCircle();
    }

    //添加圆锥体
    addCone() {
        var modelMatrix = Cesium.Matrix4.multiplyByTranslation(
            Cesium.Transforms.eastNorthUpToFixedFrame(this.position),
            new Cesium.Cartesian3(0.0, 0.0, this.height * 0.5), new Cesium.Matrix4()
        );

        var cylinderGeometry = new Cesium.CylinderGeometry({
            length: this.height,
            topRadius: 0.0,
            bottomRadius: this.bottomRadius * 0.7,
            vertexFormat: Cesium.MaterialAppearance.MaterialSupport.TEXTURED.vertexFormat
        });
        var cone = new Cesium.GeometryInstance({
            geometry: cylinderGeometry,
            modelMatrix: modelMatrix,
        });
        this.cylinderPrimitive = this.viewer.scene.primitives.add(new Cesium.Primitive({
            geometryInstances: [cone],
            appearance: new Cesium.MaterialAppearance({
                material: new Cesium.Material({
                    fabric: {
                        type: "VtxfShader1",
                        uniforms: {
                            color: this.color,
                            alpha: 2
                        },
                        source: `
                                uniform vec4 color;   
                                czm_material czm_getMaterial(czm_materialInput materialInput)
                                {
                                    czm_material material = czm_getDefaultMaterial(materialInput);
                                    vec2 st = materialInput.st;
                                    float dis = distance(st, vec2(0.5)); 
                                    material.diffuse =2.9 * color.rgb;
                                    material.alpha = color.a * dis * alpha ;
                                    return material;
                                }
                            `
                    },
                    translucent: false
                }),
                faceForward: false, // 当绘制的三角面片法向不能朝向视点时,自动翻转法向,从而避免法向计算后发黑等问题
                closed: true // 是否为封闭体,实际上执行的是是否进行背面裁剪
            }),
        }));
        this.viewer.scene.preUpdate.addEventListener(this.preUpdateHandle, this);
    }

    preUpdateHandle() {
        //圆锥闪烁动画
        this.cylinderPrimitive.appearance.material.uniforms.alpha += 0.05;
        if (this.cylinderPrimitive.appearance.material.uniforms.alpha > 2.5) {
            this.cylinderPrimitive.appearance.material.uniforms.alpha = 2;
        }
    }

    //添加底部圆
    addBottomCircle() {
        this.bottomCircle = this.viewer.entities.add({
            position: this.position,
            ellipse: {
                semiMinorAxis: this.bottomRadius * 2,
                semiMajorAxis: this.bottomRadius * 2,
                height: 0.0,
                material: new Cesium.ConeGlowBottomCircleMaterialProperty(this.color),
            }
        });
    }

    //添加底部旋转圆
    addBottomRotateCircle() {
        let stRotation = 360;
        this.bottomRotateCircle = this.viewer.entities.add({
            position: this.position,
            ellipse: {
                semiMinorAxis: this.bottomRadius * 1.45,
                semiMajorAxis: this.bottomRadius * 1.45,
                height: 0.0,
                material: new Cesium.ConeGlowBottomRotateCircleMaterialProperty(this.color),
                stRotation: new Cesium.CallbackProperty(e => {
                    stRotation--;
                    stRotation < 0 && (stRotation = 360);
                    return Cesium.Math.toRadians(stRotation);
                }, false),
            }
        });
    }

    //移除光柱体
    remove() {
        //移除事件监听
        this.viewer.scene.preUpdate.removeEventListener(this.preUpdateHandle, this);
        this.viewer.entities.remove(this.bottomRotateCircle);
        this.viewer.entities.remove(this.bottomCircle);
        this.viewer.scene.primitives.remove(this.cylinderPrimitive);
    }
}

ConeGlowMaterial/BottomCircle.js

import { createBottomCircleTexture } from "./Texture.js"

function ConeGlowBottomCircleMaterialProperty(color) {
    this._definitionChanged = new Cesium.Event();
    this._color = undefined;
    this._colorSubscription = undefined;
    this.color = color;
}
Object.defineProperties(ConeGlowBottomCircleMaterialProperty.prototype, {
    isConstant: {
        get: function() {
            return false;
        }
    },
    definitionChanged: {
        get: function() {
            return this._definitionChanged;
        }
    },
    color: Cesium.createPropertyDescriptor("color")
});
ConeGlowBottomCircleMaterialProperty.prototype.getType = function(time) {
    return "ConeGlowBottomCircle";
}
ConeGlowBottomCircleMaterialProperty.prototype.getValue = function(time, result) {
    if (!Cesium.defined(result)) {
        result = {};
    }
    result.color = Cesium.Property.getValueOrClonedDefault(this._color, time, Cesium.Color.WHITE, result.color);
    result.image = Cesium.Material.ConeGlowBottomCircleImage;
    return result;
}
ConeGlowBottomCircleMaterialProperty.prototype.equals = function(other) {
    return this === other ||
        (other instanceof ConeGlowBottomCircleMaterialProperty &&
            Cesium.Property.equals(this._color, other._color))
}
Cesium.ConeGlowBottomCircleMaterialProperty = ConeGlowBottomCircleMaterialProperty;
Cesium.Material.ConeGlowBottomCircleType = "ConeGlowBottomCircle";
Cesium.Material.ConeGlowBottomCircleImage = createBottomCircleTexture();
Cesium.Material.ConeGlowBottomCircleSource =
    "czm_material czm_getMaterial(czm_materialInput materialInput)\n\
{\n\
     czm_material material = czm_getDefaultMaterial(materialInput);\n\
     vec2 st = materialInput.st;\n\
     vec4 colorImage = texture2D(image,  vec2(st ));\n\
     material.alpha = colorImage.a * color.a;\n\
     material.diffuse =  1.5* color.rgb  ;\n\
     return material;\n\
 }";

Cesium.Material._materialCache.addMaterial(Cesium.Material.ConeGlowBottomCircleType, {
    fabric: {
        type: Cesium.Material.ConeGlowBottomCircleType,
        uniforms: {
            color: new Cesium.Color(1.0, 0.0, 0.0, 0.5),
            image: Cesium.Material.ConeGlowBottomCircleImage,
            time: 0
        },
        source: Cesium.Material.ConeGlowBottomCircleSource
    },
    translucent: function(material) {
        return true;
    }
});


 

ConeGlowMaterial/BottomRotateCircle.js

import { createBottomRotateCircleTexture } from "./Texture.js"

function ConeGlowBottomRotateCircleMaterialProperty(color) {
    this._definitionChanged = new Cesium.Event();
    this._color = undefined;
    this._colorSubscription = undefined;
    this.color = color;
}
Object.defineProperties(ConeGlowBottomRotateCircleMaterialProperty.prototype, {
    isConstant: {
        get: function() {
            return false;
        }
    },
    definitionChanged: {
        get: function() {
            return this._definitionChanged;
        }
    },
    color: Cesium.createPropertyDescriptor("color")
});
ConeGlowBottomRotateCircleMaterialProperty.prototype.getType = function(time) {
    return "ConeGlowBottomRotateCircle";
}
ConeGlowBottomRotateCircleMaterialProperty.prototype.getValue = function(time, result) {
    if (!Cesium.defined(result)) {
        result = {};
    }
    result.color = Cesium.Property.getValueOrClonedDefault(this._color, time, Cesium.Color.WHITE, result.color);
    result.image = Cesium.Material.ConeGlowBottomRotateCircleImage;
    return result;
}
ConeGlowBottomRotateCircleMaterialProperty.prototype.equals = function(other) {
    return this === other ||
        (other instanceof ConeGlowBottomRotateCircleMaterialProperty &&
            Cesium.Property.equals(this._color, other._color))
}
Cesium.ConeGlowBottomRotateCircleMaterialProperty = ConeGlowBottomRotateCircleMaterialProperty;
Cesium.Material.ConeGlowBottomRotateCircleType = "ConeGlowBottomRotateCircle";
Cesium.Material.ConeGlowBottomRotateCircleImage = createBottomRotateCircleTexture();
Cesium.Material.ConeGlowBottomRotateCircleSource =
    "czm_material czm_getMaterial(czm_materialInput materialInput)\n\
{\n\
     czm_material material = czm_getDefaultMaterial(materialInput);\n\
     vec2 st = materialInput.st;\n\
     vec4 colorImage = texture2D(image, vec2(st ));\n\
     material.diffuse = 2.5 * color.rgb  ;\n\
     material.alpha = colorImage.a ;\n\
     return material;\n\
 }";
Cesium.Material._materialCache.addMaterial(Cesium.Material.ConeGlowBottomRotateCircleType, {
    fabric: {
        type: Cesium.Material.ConeGlowBottomRotateCircleType,
        uniforms: {
            color: new Cesium.Color(1.0, 0.0, 0.0, 0.5),
            image: Cesium.Material.ConeGlowBottomRotateCircleImage,
            time: 0
        },
        source: Cesium.Material.ConeGlowBottomRotateCircleSource
    },
    translucent: function(material) {
        return true;
    }
});


 

ConeGlowMaterial/Texture.js

 //底部圆材质图片
 export function createBottomCircleTexture() {
    let canvas = document.createElement("canvas");
    canvas.width = 512;
    canvas.height = 512;
    let ctx = canvas.getContext("2d");

    let gradient = ctx.createRadialGradient(256, 256, 0, 256, 256, 256);
    gradient.addColorStop(0.1, "rgba(255, 255, 255, 1.0)");
    gradient.addColorStop(0.2, "rgba(255, 255, 255, 0.0)");
    gradient.addColorStop(0.3, "rgba(255, 255, 255, 0.9)");
    gradient.addColorStop(0.5, "rgba(255, 255, 255, 0.0)");
    gradient.addColorStop(0.9, "rgba(255, 255, 255, 0.2)");
    gradient.addColorStop(1.0, "rgba(255, 255, 255, 1.0)");

    ctx.clearRect(0, 0, 512, 512);
    ctx.beginPath();
    ctx.arc(256, 256, 256, 0, Math.PI * 2, true);
    //ctx.fillStyle = "rgb(0, 155, 255)";
    ctx.fillStyle = gradient;
    ctx.fill();
    ctx.restore();
    return canvas.toDataURL("image/png").replace("image/png", "image/octet-stream");
}

//底部运动圆材质图片
export function createBottomRotateCircleTexture() {
    let canvas = document.createElement("canvas");
    canvas.width = 512;
    canvas.height = 512;
    let ctx = canvas.getContext("2d");
    ctx.clearRect(0, 0, 512, 512);
    ctx.strokeStyle = "rgb(255, 255, 0)";
    ctx.setLineDash([80, 80]);
    ctx.lineWidth = 30;
    ctx.arc(256, 256, 241, 0, Math.PI * 2, true);
    ctx.stroke();
    return canvas.toDataURL("image/png").replace("image/png", "image/octet-stream");
}
 
  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值