DESKTOP-CRQ4N2U\jintian 1 жил өмнө
parent
commit
c480118e66

+ 160 - 0
src/jtMap3d/Widgets/CircleObject.js

@@ -0,0 +1,160 @@
+/* 引入Cesium */
+// import * as Cesium from 'Cesium';
+
+import {
+	setSessionid
+} from "./common/common.js";
+
+/**
+ *流动纹理
+ */
+import CircleMaterialProperty from "./CircleObject/CircleMaterialProperty.js";
+import CircleRippleMaterialProperty from "./CircleObject/CircleRippleMaterialProperty.js";
+
+/**
+ * 墙体对象
+ */
+class CircleObject {
+	/**
+	 * 默认初始化
+	 */
+	constructor(viewer) {
+		if (!viewer) throw new Cesium.DeveloperError('no viewer object!');
+		this._viewer = viewer;
+	}
+}
+
+/**
+ * 通用对外公开函数 
+ */
+Object.assign(CircleObject.prototype, /** @lends CircleObject.prototype */ {
+
+	/**
+	 * @description 绘制动态圆
+	 * @param {String} centerPoint 圆心坐标
+	 * @param {String} radius 圆半径
+	 * @param {Object} [options] 圆的样式,具有以下属性:
+	 * @param {Number} [options.id] 用于移除
+	 * @param {Number} [options.clampToGround=true] 是否贴地
+	 * @param {String} [options.color="#FF0000"] 指定圆的颜色
+
+	 * @param {String} [options.outlineColor="#FFFF00"] 指定点轮廓的颜色
+	 * @param {Number} [options.outlineWidth=0] 指定点轮廓的宽度
+	 * 
+	 * @param {Number} [options.CircleType='ColorCircle'] ColorCircle / DynamicCircle
+	 * @param {Number} [options.duration=3000] 持续时间 毫秒,越小越快
+	 * @param {Number} [options.count=1] 重复次数
+	 */
+	drawCircle: function(centerPoint, radius, options) {
+		return new Promise((resolve, reject) => {
+			let _self = this;
+			let viewer = this._viewer;
+
+			if (!Cesium.defined(centerPoint)) {
+				throw new Cesium.DeveloperError("centerPoint is required.");
+			}
+
+			if (!Cesium.defined(radius)) {
+				throw new Cesium.DeveloperError("radius is required.");
+			}
+
+			//坐标位置
+			let position;
+			if (centerPoint instanceof Cesium.Cartesian3) {
+				position = centerPoint;
+			} else {
+				position = Cesium.Cartesian3.fromDegrees(centerPoint[0], centerPoint[1], centerPoint[2] || 0);
+			}
+
+			//半径
+			if (typeof radius === 'number' && radius > 0) {
+				radius = radius;
+			} else {
+				radius = 100
+			}
+
+			options = options || {};
+			options.id = options.id || setSessionid();
+			options.clampToGround = Cesium.defaultValue(options.clampToGround, true);
+			options.CircleType = Cesium.defaultValue(options.CircleType, 'ColorCircle');
+
+			options.duration = Cesium.defaultValue(options.duration, 3000);
+			options.count = Cesium.defaultValue(options.count, 1);
+
+			if (options.color) {
+				if (options.color instanceof Array) {
+					options.color = new Cesium.Color(options.color[0] / 255, options.color[1] / 255, options.color[2] / 255, options.color[3]);
+				} else if (typeof(options.color) === 'string') {
+					options.color = new Cesium.Color.fromCssColorString(options.color);
+				} else {
+					options.color = new Cesium.Color.fromCssColorString("#FFFF00");
+				}
+			}
+
+			if (options.outlineColor) {
+				if (options.outlineColor instanceof Array) {
+					options.outlineColor = new Cesium.Color(options.outlineColor[0] / 255, options.outlineColor[1] / 255, options.outlineColor[2] / 255, options.outlineColor[3]);
+				} else if (typeof(options.outlineColor) === 'string') {
+					options.outlineColor = new Cesium.Color.fromCssColorString(options.outlineColor);
+				} else {
+					options.outlineColor = new Cesium.Color.fromCssColorString("#FFFF00");
+				}
+			}
+			options.outlineWidth = Cesium.defaultValue(options.outlineWidth, 0);
+
+
+			/* 创建面材质 */
+			let polygonMaterial = options.color;
+			/* 创建线材质 */
+			// let outlineMaterial = new Cesium.PolylineDashMaterialProperty({//虚线
+			// 	dashLength: 16,
+			// 	color: options.outlineColor
+			// });
+			let outlineMaterial = options.outlineColor;
+
+			if (options.CircleType === 'DynamicCircle') {
+				// polygonMaterial = new CircleMaterialProperty({
+				// 	viewer: viewer,
+				// 	duration: options.duration,
+				// 	color: options.color,
+				// 	count: options.count,
+				// });
+
+				polygonMaterial = new Cesium.CircleRippleMaterialProperty({
+					color: options.color,
+					speed: options.duration/1000,
+					count: options.count,
+					gradient: 0.2
+				})
+			}
+
+			let entity = new Cesium.Entity({
+				id: options.id,
+				//位置
+				position: position,
+				//椭圆
+				ellipse: {
+					//半短轴(画圆:半短轴和半长轴一致即可)
+					semiMinorAxis: radius,
+					// 半长轴
+					semiMajorAxis: radius,
+					// 填充色
+					material: polygonMaterial,
+					// 是否有边框
+					outline: true,
+					// 边框颜色
+					outlineColor: options.outlineColor,
+					// 边框宽度
+					outlineWidth: options.outlineWidth
+				}
+			});
+
+			let flyEntity = viewer.entities.add(entity);
+
+			resolve(entity, flyEntity)
+
+		});
+	},
+});
+
+export default CircleObject;

+ 181 - 0
src/jtMap3d/Widgets/CircleObject/CircleMaterialProperty.js

@@ -0,0 +1,181 @@
+/**
+ * 创建者:王成
+ * 操作系统:MAC
+ * 创建日期:2022年12月29日
+ * 描述:动态扩散圆材质
+ */
+class CircleMaterialProperty {
+	/**
+	 * 构造方法
+	 * @ignore 无需公开
+	 * @param {JSON} options 配置项
+	 * @param {Cesium.Viewer} options.viewer 着色器运行所需的视图
+	 * @param {Cesium.Color} options.color [圆环的颜色,默认蓝色] 可选
+	 * @param {Number} options.duration [循环时间 默认1000] 可选
+	 * @param {Number} options.count [圆环的数量 可选 默认为1]
+	 */
+	constructor(options) {
+		/* 着色器运行依赖的视图 */
+		this._viewer = options.viewer;
+		/* 变更事件 */
+		this._definitionChanged = new Cesium.Event();
+		this._color = undefined;
+		/* 扩算圆环的颜色 */
+		this.color = options.color || Cesium.Color.BLUE;
+		/* 扩散圆环的数量 */
+		this.count = options.count || 1.0;
+		/* 动态循环周期 */
+		this.duration = options.duration || 1000;
+		/* 默认时间 */
+		this._time = (new Date()).getTime();
+		/* 材质类型名称 */
+		this._materialTypeName = 'jtCircleMaterial'
+		/* 存储相关参数的属性 以便后期进行追踪修改 */
+		this._param = {
+			color: this.color._value.toCssColorString(),
+			duration: this.duration,
+			count: this.count,
+		}
+		/* 将材质加入缓存 以便重复利用 */
+		Cesium.Material._materialCache.addMaterial(this._materialTypeName, {
+			fabric: {
+				type: this._materialTypeName,
+				uniforms: {
+					time: 0,
+					color: new Cesium.Color(1.0, 0.0, 0.0, 0.5),
+					count: 1.0,
+				},
+				source: this._getCircleMaterial(),
+			},
+			translucent: function(material) {
+				/* 材质是否半透明 */
+				return true;
+			}
+		});
+	}
+
+	/**
+	 * @ignore 无需公开
+	 * 获取材质着色器Shader
+	 */
+	_getCircleMaterial() {
+		let circleMaterial = "czm_material czm_getMaterial(czm_materialInput materialInput)\n" +
+			"{\n" +
+			"  czm_material material = czm_getDefaultMaterial(materialInput);\n" +
+			"  material.diffuse = 1.5 * color.rgb;\n" +
+			"  vec2 st = materialInput.st;\n" +
+			"  vec3 str = materialInput.str;\n" +
+			"  float dis = distance(st, vec2(0.5, 0.5));\n" +
+			"  float per = fract(time);\n" +
+			"  if (abs(str.z) > 0.001)\n" +
+			"  {\n" +
+			"     //着色器渲染停止,不在绘制内容  \n" +
+			"     discard;\n" +
+			"  }\n" +
+			"  if (dis > 0.5)\n" +
+			"  {\n" +
+			"     //超出半径范围时,着色器渲染停止  \n" +
+			"     discard;\n" +
+			"  } else {\n" +
+			"     //把半径分成count份,每两份之间的间隔距离  \n" +
+			"     float perDis = 0.5 / count;\n" +
+			"     float disNum;\n" +
+			"     float bl = 0.0;\n" +
+			"     //循环,最多999个环  \n" +
+			"     for (int i = 0; i <= 999; i++)\n" +
+			"     {\n" +
+			"        //判断是否属于数量内的环  \n" +
+			"        if (float(i) <= count)\n" +
+			"        {\n" +
+			"           disNum = perDis * float(i) - dis + per / count;\n" +
+			"           if (disNum > 0.0)\n" +
+			"           {\n" +
+			"               if (disNum < perDis)\n" +
+			"               {\n" +
+			"                  bl = 1.0 - disNum / perDis;\n" +
+			"               } else if (disNum - perDis < perDis) {\n" +
+			"                  bl = 1.0 - abs(1.0 - disNum / perDis);\n" +
+			"               }\n" +
+			"               material.alpha = color.a * pow(bl, 3.0);\n" +
+			"           }\n" +
+			"        }\n" +
+			"     }\n" +
+			"  }\n" +
+			"  return material;\n" +
+			"}\n";
+		return circleMaterial;
+	}
+}
+
+/**
+ * @ignore 无需公开
+ * 必须重写的方法
+ */
+Object.assign(CircleMaterialProperty.prototype, {
+	/**
+	 * 重新获取类型方法
+	 * @ignore 无需公开
+	 * @param {Cesium.JulianDate} time 时间
+	 */
+	getType: function(time) {
+		return this._materialTypeName;
+	},
+
+	/**
+	 * 重写获取值方法
+	 * @ignore 无需公开
+	 * @param {Cesium.JulianDate} time
+	 * @param {JSON} result 
+	 */
+	getValue: function(time, result) {
+		if (!Cesium.defined(result)) {
+			result = {};
+		}
+		result.color = Cesium.Property.getValueOrClonedDefault(this._color, time, Cesium.Color.BLUE, result
+			.color);
+		result.count = this.count;
+		if (this.duration) {
+			result.time = (((new Date()).getTime() - this._time) % this.duration) / this.duration;
+		}
+		this._viewer.scene.requestRender();
+		return result;
+	},
+
+	/**
+	 * 重写对比函数
+	 * @ignore 无需公开
+	 * @param {Object} other 传入对比对象
+	 */
+	equals: function(other) {
+		return (this === other || (other instanceof CircleMaterialProperty && Cesium.Property.equals(this
+			._color, other._color)));
+	}
+})
+
+/**
+ * 默认属性
+ */
+Object.defineProperties(CircleMaterialProperty.prototype, {
+	/**
+	 * 判断是否相等,返回false表示属性一直在变化中
+	 * @ignore 无需公开
+	 */
+	isConstant: {
+		get: function() {
+			return false;
+		}
+	},
+	/**
+	 * 事件变更
+	 * @ignore 无需公开
+	 */
+	definitionChanged: {
+		get: function() {
+			return this._definitionChanged;
+		}
+	},
+	/* 颜色属性 */
+	color: Cesium.createPropertyDescriptor('color')
+})
+
+export default CircleMaterialProperty;

+ 132 - 0
src/jtMap3d/Widgets/CircleObject/CircleRippleMaterialProperty.js

@@ -0,0 +1,132 @@
+/*
+ * @Description: 波纹圆效果(和水波纹扩散类似,参考开源代码)
+ * @Version: 1.0
+ * @Author: Julian
+ * @Date: 2022-03-03 21:59:17
+ * @LastEditors: Julian
+ * @LastEditTime: 2022-03-03 23:09:02
+ */
+class CircleRippleMaterialProperty {
+    constructor(options) {
+        this._definitionChanged = new Cesium.Event();
+        this._color = undefined;
+        this._speed = undefined;
+        this.color = options.color;
+        this.speed = options.speed;
+        this.count = options.count;
+        this.gradient = options.gradient;
+    };
+
+    get isConstant() {
+        return false;
+    }
+
+    get definitionChanged() {
+        return this._definitionChanged;
+    }
+
+    getType(time) {
+        return Cesium.Material.CircleRippleMaterialType;
+    }
+
+    getValue(time, result) {
+        if (!Cesium.defined(result)) {
+            result = {};
+        }
+
+        result.color = Cesium.Property.getValueOrDefault(this._color, time, Cesium.Color.RED, result.color);
+        result.speed = Cesium.Property.getValueOrDefault(this._speed, time, 10, result.speed);
+        result.count = this.count;
+        result.gradient = this.gradient;
+        return result
+    }
+
+    equals(other) {
+        return (this === other ||
+            (other instanceof CircleRippleMaterialProperty &&
+                Cesium.Property.equals(this._color, other._color) &&
+                Cesium.Property.equals(this._speed, other._speed) &&
+                Cesium.Property.equals(this.count, other.count) &&
+                Cesium.Property.equals(this.gradient, other.gradient))
+        )
+    }
+}
+
+Object.defineProperties(CircleRippleMaterialProperty.prototype, {
+    color: Cesium.createPropertyDescriptor('color'),
+    speed: Cesium.createPropertyDescriptor('speed'),
+    count: Cesium.createPropertyDescriptor('count'),
+    gradient: Cesium.createPropertyDescriptor('gradient')
+})
+
+Cesium.CircleRippleMaterialProperty = CircleRippleMaterialProperty;
+Cesium.Material.CircleRippleMaterialProperty = 'CircleRippleMaterialProperty';
+Cesium.Material.CircleRippleMaterialType = 'CircleRippleMaterialType';
+Cesium.Material.CircleRippleMaterialSource = `
+                                            uniform vec4 color;
+                                            uniform float speed;
+                                            uniform float count;
+                                            uniform float gradient;
+
+                                            czm_material czm_getMaterial(czm_materialInput materialInput)
+                                            {
+                                            czm_material material = czm_getDefaultMaterial(materialInput);
+                                            material.diffuse = 1.5 * color.rgb;
+                                            vec2 st = materialInput.st;
+                                            float dis = distance(st, vec2(0.5, 0.5));
+                                            float per = fract(czm_frameNumber * speed / 1000.0);
+                                            if(count == 1.0){
+                                                if(dis > per * 0.5){
+                                                discard;
+                                                }else {
+                                                material.alpha = color.a  * dis / per / 2.0;
+                                                }
+                                            } else {
+                                                vec3 str = materialInput.str;
+                                                if(abs(str.z)  > 0.001){
+                                                discard;
+                                                }
+                                                if(dis > 0.5){
+                                                discard;
+                                                } else {
+                                                float perDis = 0.5 / count;
+                                                float disNum;
+                                                float bl = 0.0;
+                                                for(int i = 0; i <= 999; 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,(1.0 + 10.0 * (1.0 - gradient)));
+                                                    }
+                                                    }
+                                                }
+                                                }
+                                            }
+                                            return material;
+                                            }
+                                            `
+
+Cesium.Material._materialCache.addMaterial(Cesium.Material.CircleRippleMaterialType, {
+    fabric: {
+        type: Cesium.Material.CircleRippleMaterialType,
+        uniforms: {
+            color: new Cesium.Color(1.0, 0.0, 0.0, 1.0),
+            speed: 3.0,
+            count: 4,
+            gradient: 0.2
+        },
+        source: Cesium.Material.CircleRippleMaterialSource
+    },
+    translucent: function(material) {
+        return true;
+    }
+})
+
+
+export default CircleRippleMaterialProperty;