ソースを参照

动态墙接口

DESKTOP-CRQ4N2U\jintian 1 年間 前
コミット
c2c25c21c4

+ 138 - 0
src/jtMap3d/Widgets/WallObject.js

@@ -0,0 +1,138 @@
+/* 引入Cesium */
+// import * as Cesium from 'Cesium';
+
+import {
+	setSessionid
+} from "./common/common.js";
+
+/**
+ *流动纹理
+ */
+import DynamicWallMaterialProperty from "./WallObject/DynamicWallMaterialProperty.js";
+import WallDiffuseMaterialProperty from "./WallObject/WallDiffuseMaterialProperty.js";
+import WallMaterialProperty from "./WallObject/WallMaterialProperty.js";
+
+/**
+ * 墙体对象
+ */
+class WallObject {
+	/**
+	 * 默认初始化
+	 */
+	constructor(viewer) {
+		if (!viewer) throw new Cesium.DeveloperError('no viewer object!');
+		this._viewer = viewer;
+	}
+}
+
+/**
+ * 通用对外公开函数 
+ */
+Object.assign(WallObject.prototype, /** @lends WallObject.prototype */ {
+
+	/**
+	 * @description 根据GeoJson绘制墙体对象
+	 * @param {String} geoJsonUrl geoJson文件路径
+	 * @param {Object} [options] 线的样式,具有以下属性:
+	 * @param {Number} [options.id] 用于移除
+	 * @param {Number} [options.clampToGround=true] 是否贴地
+	 * @param {Number} [options.minimunHeights=0] 最低高度
+	 * @param {Number} [options.maximumHeights=100] 最高高度
+	 * @param {Number} [options.imgUrl] 动态墙图片
+	 * @param {String} [options.color="#FF0000"] 指定墙的颜色
+	 * @param {Number} [options.duration=3000] 持续时间 毫秒,越小越快
+	 * @param {Number} [options.count] 重复次数
+	 * @param {String} [options.direction='horizontal'] 方向 vertical纵,垂直方向,horizontal横,水平方向
+	 * @param {String} [options.order] 方向正负 
+	 *                                        vertical 纵:'-'(由下到上) , '+"(由上到下)
+	 *                                        horizontal 横:'-'(顺时针) , '+'(逆时针)
+	 */
+	drawWallByGeoJson: function(geoJsonUrl, options) {
+		return new Promise((resolve, reject) => {
+
+			let _self = this;
+			let viewer = this._viewer;
+
+			if (!Cesium.defined(geoJsonUrl)) {
+				throw new Cesium.DeveloperError("geoJsonUrl is required.");
+			}
+
+			options = options || {};
+			options.id = options.id || setSessionid();
+			options.clampToGround = Cesium.defaultValue(options.clampToGround, true);
+
+			options.minimunHeights = options.minimunHeights !== undefined && typeof options.minimunHeights === 'number' ? options.minimunHeights : 0;
+			options.maximumHeights = options.maximumHeights !== undefined && typeof options.maximumHeights === 'number' ? options.maximumHeights : 1000;
+
+			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");
+				}
+			}
+
+			options.trailImage = Cesium.defaultValue(options.trailImage, 'jt3dSDK/imgs/wallmaterial/wl.png');
+			options.duration = Cesium.defaultValue(options.duration, 3000);
+			options.count = Cesium.defaultValue(options.count, 1);
+			options.direction = Cesium.defaultValue(options.direction, 'vertical');
+			options.order = Cesium.defaultValue(options.order, '-');
+
+			fetch(geoJsonUrl).then(res => {
+				return res.json();
+			}).then(res => {
+
+				for (var i = 0; i < res.features.length; i++) {
+					let coordinates = res.features[i].geometry.coordinates;
+					let positions = coordinates.map(point => {
+						return Cesium.Cartesian3.fromDegrees(point[0], point[1], point[2] || 0);
+					});
+
+					//先创建一个CustomDataSource源,然后把entity存入这里面
+					let wall = new Cesium.CustomDataSource(options.id);
+					viewer.dataSources.add(wall);
+
+					let entity = new Cesium.Entity({
+						name: "立体墙效果",
+						wall: {
+							positions: positions,
+							// 设置高度
+							maximumHeights: new Array(positions.length).fill(options.maximumHeights),
+							minimunHeights: new Array(positions.length).fill(options.minimunHeights),
+							// 扩散墙材质
+							// material: new Cesium.WallDiffuseMaterialProperty({
+							//     color: new Cesium.Color(1.0, 1.0, 0.0, 1.0)
+							// }),
+							material: new WallMaterialProperty(viewer, {
+								trailImage: options.trailImage,
+								color: options.color,
+								duration: options.duration,
+								param: {
+									count: options.count,
+									direction: options.direction,
+									order: options.order,
+								},
+							}),
+
+							// material: new Cesium.DynamicWallMaterialProperty({
+							// 	trailImage: 'jt3dSDK/imgs/wallmaterial/wl.png',
+							// 	color: Cesium.Color.CYAN,
+							// 	duration: 1500
+							// })
+						}
+					});
+
+					// 绘制墙体
+					wall.entities.add(entity)
+				}
+
+				resolve(options.id);
+			});
+
+		});
+	},
+});
+
+export default WallObject;

+ 107 - 0
src/jtMap3d/Widgets/WallObject/DynamicWallMaterialProperty.js

@@ -0,0 +1,107 @@
+/*
+    动态墙材质
+    color 颜色
+    duration 持续时间 毫秒
+    trailImage 贴图地址
+*/
+function DynamicWallMaterialProperty(options) {
+	this._definitionChanged = new Cesium.Event();
+	this._color = undefined;
+	this._colorSubscription = undefined;
+	this.color = options.color || Color.BLUE;
+	this.duration = options.duration || 1000;
+	this.trailImage = options.trailImage;
+	this._time = (new Date()).getTime();
+}
+
+/**
+ * 带方向的墙体
+ * @param {*} options.get:true/false
+ * @param {*} options.count:数量 
+ * @param {*} options.direction:vertical/standard
+ * @param {*} options.order:+/-
+ */
+function _getDirectionWallShader(options) {
+	if (options && options.get) {
+		var materail = "czm_material czm_getMaterial(czm_materialInput materialInput)\n\
+      {\n\
+          czm_material material = czm_getDefaultMaterial(materialInput);\n\
+          vec2 st = materialInput.st;";
+		if (options.direction == "vertical") { //(由下到上)
+			materail += "vec4 colorImage = texture2D(image, vec2(fract(st.s), fract(float(" + options.count + ")*st.t" + options.order + " time)));\n\ ";
+		} else { //(逆时针)
+			materail += "vec4 colorImage = texture2D(image, vec2(fract(float(" + options.count + ")*st.s " + options.order + " time), fract(st.t)));\n\ ";
+		}
+		//泛光
+		materail += "vec4 fragColor;\n\
+          fragColor.rgb = (colorImage.rgb+color.rgb) / 1.0;\n\
+          fragColor = czm_gammaCorrect(fragColor);\n\
+          material.diffuse = colorImage.rgb;\n\
+          material.alpha = colorImage.a;\n\
+          material.emission = fragColor.rgb;\n\
+          return material;\n\
+      }";
+		return materail
+	}
+}
+
+Object.defineProperties(DynamicWallMaterialProperty.prototype, {
+	isConstant: {
+		get: function() {
+			return false;
+		}
+	},
+	definitionChanged: {
+		get: function() {
+			return this._definitionChanged;
+		}
+	},
+	color: Cesium.createPropertyDescriptor('color')
+});
+
+var MaterialType = 'wallType' + parseInt(Math.random() * 1000);
+DynamicWallMaterialProperty.prototype.getType = function(time) {
+	return MaterialType;
+};
+
+DynamicWallMaterialProperty.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 = this.trailImage;
+	if (this.duration) {
+		result.time = (((new Date()).getTime() - this._time) % this.duration) / this.duration;
+	}
+	viewer.scene.requestRender();
+	return result;
+};
+
+DynamicWallMaterialProperty.prototype.equals = function(other) {
+	return this === other ||
+		(other instanceof DynamicWallMaterialProperty &&
+			Cesium.Property.equals(this._color, other._color))
+};
+
+Cesium.Material._materialCache.addMaterial(MaterialType, {
+	fabric: {
+		type: MaterialType,
+		uniforms: {
+			color: new Cesium.Color(1.0, 0.0, 0.0, 0.5),
+			image: Cesium.Material.DefaultImageId,
+			time: -20
+		},
+		source: _getDirectionWallShader({
+			get: true,
+			count: 3.0,
+			direction: 'vertical',
+			order: '-'
+		})
+	},
+	translucent: function(material) {
+		return true;
+	}
+});
+Cesium.DynamicWallMaterialProperty = DynamicWallMaterialProperty;
+
+export default DynamicWallMaterialProperty;

+ 79 - 0
src/jtMap3d/Widgets/WallObject/WallDiffuseMaterialProperty.js

@@ -0,0 +1,79 @@
+/*
+ * @Description: 动态扩散墙的墙体效果(参考开源代码)(不同高度透明度不同)
+ * @Version: 1.0
+ * @Author: Julian
+ * @Date: 2022-03-07 19:50:46
+ * @LastEditors: Julian
+ * @LastEditTime: 2022-03-08 13:34:04
+ */
+class WallDiffuseMaterialProperty {
+    constructor(options) {
+        this._definitionChanged = new Cesium.Event();
+        this._color = undefined;
+        this.color = options.color;
+    };
+
+    get isConstant() {
+        return false;
+    }
+
+    get definitionChanged() {
+        return this._definitionChanged;
+    }
+
+    getType(time) {
+        return Cesium.Material.WallDiffuseMaterialType;
+    }
+
+    getValue(time, result) {
+        if (!Cesium.defined(result)) {
+            result = {};
+        }
+
+        result.color = Cesium.Property.getValueOrDefault(this._color, time, Cesium.Color.RED, result.color);
+        return result
+    }
+
+    equals(other) {
+        return (this === other ||
+            (other instanceof WallDiffuseMaterialProperty &&
+                Cesium.Property.equals(this._color, other._color))
+        )
+    }
+}
+
+Object.defineProperties(WallDiffuseMaterialProperty.prototype, {
+    color: Cesium.createPropertyDescriptor('color'),
+})
+
+Cesium.WallDiffuseMaterialProperty = WallDiffuseMaterialProperty;
+Cesium.Material.WallDiffuseMaterialProperty = 'WallDiffuseMaterialProperty';
+Cesium.Material.WallDiffuseMaterialType = 'WallDiffuseMaterialType';
+Cesium.Material.WallDiffuseMaterialSource =
+    `
+    uniform vec4 color;
+    czm_material czm_getMaterial(czm_materialInput materialInput){
+    czm_material material = czm_getDefaultMaterial(materialInput);
+    vec2 st = materialInput.st;
+    material.diffuse = color.rgb * 2.0;
+    material.alpha = color.a * (1.0 - fract(st.t)) * 0.8;
+    return material;
+    }
+                                            
+    `
+
+Cesium.Material._materialCache.addMaterial(Cesium.Material.WallDiffuseMaterialType, {
+    fabric: {
+        type: Cesium.Material.WallDiffuseMaterialType,
+        uniforms: {
+            color: new Cesium.Color(1.0, 0.0, 0.0, 1.0),
+        },
+        source: Cesium.Material.WallDiffuseMaterialSource
+    },
+    translucent: function(material) {
+        return true;
+    }
+})
+
+
+export default WallDiffuseMaterialProperty;

+ 186 - 0
src/jtMap3d/Widgets/WallObject/WallMaterialProperty.js

@@ -0,0 +1,186 @@
+class WallMaterialProperty {
+	/**
+	 * 构造方法
+	 * @ignore 无需公开
+	 * @param {Cesium.Viewer} viewer 着色器运行所需的视图
+	 * @param {JSON} options 配置项
+	 * @param {Cesium.Color} options.color [墙的颜色,默认蓝色] 可选
+	 * @param {Number} options.duration [循环时间 默认1000] 可选
+	 * @param {String} options.trailImage 墙的贴图
+	 * @param {JSON} options.param 着色器参数
+	 * @param {Number} options.param.count [数量 可选 默认为1]
+	 * @param {String} options.param.direction [方向 可选 默认竖直 ] 取值vertical/horizontal
+	 * @param {String} options.param.order [顺序 可选 上下/下上/顺时针/逆时针 与方向配合使用 ] 取值+/-
+	 */
+	constructor(viewer, options) {
+		
+
+		/* 着色器运行依赖的视图 */
+		this._viewer = viewer;
+		options = options || {};
+
+		/* 变更事件 */
+		this._definitionChanged = new Cesium.Event();
+		this._color = undefined;
+		/* 墙的颜色 */
+		this.color = options.color || Cesium.Color.BLUE;
+		/* 动态循环周期 */
+		this.duration = options.duration || 1000;
+		
+		this.count = options.duration || 1;	
+		this.direction = options.duration || 'vertical';
+		this.order = options.duration || '-';
+		
+		
+		
+		/* 墙的贴图 */
+		this.trailImage = Cesium.defaultValue(options.trailImage, 'jt3dSDK/imgs/wallmaterial/wl.png');
+		/* 默认时间 */
+		this._time = (new Date()).getTime();
+		/* 材质类型名称 */
+		this._materialTypeName = 'WallMaterial' + this._guid();
+		/* 存储相关参数的属性 以便后期进行追踪修改 */
+		this._param = {
+			color: this.color._value.toCssColorString(),
+			image: this.trailImage,
+			duration: this.duration,
+			count: this.count,
+			direction: this.direction,
+			order: this.order,
+		}
+		/* 将材质加入缓存 以便重复利用 */
+		Cesium.Material._materialCache.addMaterial(this._materialTypeName, {
+			fabric: {
+				type: this._materialTypeName,
+				uniforms: {
+					time: -20,
+					color: new Cesium.Color(1.0, 0.0, 0.0, 0.5),
+					image: options.trailImage,
+				},
+				source: this._getDirectionWallShader(options.param)
+			},
+			translucent: function(material) {
+				/* 材质是否半透明 */
+				return true;
+			}
+		});
+	}
+
+	/**
+	 * 生成GUID随机数
+	 * @ignore 无需公开
+	 */
+	_guid() {
+		function S4() {
+			return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
+		}
+		return (S4() + S4() + "-" + S4() + "-" + S4() + "-" + S4() + "-" + S4() + S4() + S4());
+	}
+
+	/**
+	 * 重新获取类型方法
+	 * @ignore 无需公开
+	 * @param {Cesium.JulianDate} time 时间
+	 */
+	getType(time) {
+		return this._materialTypeName;
+	}
+
+	/**
+	 * 重写获取值方法
+	 * @ignore 无需公开
+	 * @param {Cesium.JulianDate} time
+	 * @param {JSON} result 
+	 */
+	getValue(time, result) {
+		if (!Cesium.defined(result)) {
+			result = {};
+		}
+		result.color = Cesium.Property.getValueOrClonedDefault(this._color, time, Cesium.Color.BLUE, result.color);
+		result.image = this.trailImage;
+		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(other) {
+		return (this === other || (other instanceof WallMaterialProperty && Cesium.Property.equals(this
+				._color, other._color) && other._param.order === this._param.order && other._param.count ===
+			this._param.count && other._param.direction === this._param.direction && other.duration === this
+			.duration));
+	}
+
+	/**
+	 * 创建着色器资源
+	 * @ignore 无需公开
+	 * @param {JSON} options 配置项
+	 * @param {Number} options.count [数量 可选 默认为1]
+	 * @param {String} options.direction [方向 可选 默认竖直 ] 取值vertical/horizontal
+	 * @param {String} options.order [顺序 可选 上下/下上/顺时针/逆时针 与方向配合使用 ] 取值+/-
+	 */
+	_getDirectionWallShader(options) {
+		let op = Cesium.defaultValue(options, {});
+		// console.log('>>>op===', op);
+		let count = op.count !== undefined && typeof op.count === 'number' && op.count > 0 ? op.count : 1;
+		let direction = op.direction === 'horizontal' ? 'horizontal' : 'vertical';
+		let order = op.order === '+' ? '+' : '-';
+		this._param.count = count;
+		this._param.direction = direction;
+		this._param.order = order;
+		let materail = '';
+		/* 补充参数 */
+		// console.log('_param', this._param);
+		materail += 'czm_material czm_getMaterial(czm_materialInput materialInput){\n' +
+			'  czm_material material = czm_getDefaultMaterial(materialInput);\n' +
+			'  vec2 st = materialInput.st;\n';
+		if (direction === 'vertical') {
+			materail += '  vec4 colorImage = texture2D(image,vec2(st.s,fract(float(' + count + ')*st.t ' + order + ' time)));\n';
+		} else if (direction === 'horizontal') {
+			materail += '  vec4 colorImage = texture2D(image, vec2(fract(float(' + count + ')*st.s ' + order + ' time), st.t));\n'
+		}
+		materail += '  vec4 fragColor;\n' +
+			'  fragColor.rgb = color.rgb / 1.0;\n' +
+			'  fragColor = czm_gammaCorrect(fragColor);\n' +
+			'  material.alpha = colorImage.a * color.a;\n' +
+			'  material.diffuse = color.rgb;\n' +
+			'  material.emission = fragColor.rgb;\n' +
+			'  return material;\n' +
+			'}';
+		return materail;
+	}
+}
+
+/**
+ * 增加默认属性
+ */
+Object.defineProperties(WallMaterialProperty.prototype, {
+	/**
+	 * @ignore 无需公开
+	 * 判断是否相等,返回false表示属性一直在变化中
+	 */
+	isConstant: {
+		get: function() {
+			return false;
+		}
+	},
+	/**
+	 * @ignore 无需公开
+	 * 事件变更
+	 */
+	definitionChanged: {
+		get: function() {
+			return this._definitionChanged;
+		}
+	},
+	/* 颜色属性 */
+	color: Cesium.createPropertyDescriptor('color')
+})
+
+export default WallMaterialProperty;