From 2eeaa4693e7389df008b6763074c48e9ffa367ca Mon Sep 17 00:00:00 2001 From: guonan <guonan201020@163.com> Date: 星期四, 17 四月 2025 15:23:57 +0800 Subject: [PATCH] 更新雨 --- src/utils/rain.js | 82 +++++++++++++ src/utils/snow.js | 82 +++++++++++++ src/components/tools/Rain.vue | 55 +++++++++ src/assets/css/global.css | 8 + src/utils/tools.js | 35 ++++- src/components/tools/SlopeAnalysis.vue | 9 - src/components/tools/Tools.vue | 31 +++- 7 files changed, 277 insertions(+), 25 deletions(-) diff --git a/src/assets/css/global.css b/src/assets/css/global.css index 103df06..4291542 100644 --- a/src/assets/css/global.css +++ b/src/assets/css/global.css @@ -62,3 +62,11 @@ .el-input__inner { color: #fff !important; } +.el-slider__bar { + background-color: #009688 !important; + border-color: #009688 !important; +} + +.el-slider__button { + border-color: rgb(0, 150, 136) !important; +} diff --git a/src/components/tools/Rain.vue b/src/components/tools/Rain.vue new file mode 100644 index 0000000..f87598b --- /dev/null +++ b/src/components/tools/Rain.vue @@ -0,0 +1,55 @@ +<template> + <el-form :model="form" label-width="80px" class="terrain-settings"> + <el-form-item label="澶у皬"> + <el-slider + :step="0.1" + v-model="form.rainSize" + :min="0" + :max="1" + ></el-slider> + </el-form-item> + <el-form-item label="閫熷害"> + <el-slider v-model="form.rainSpeed" :min="0" :max="150"></el-slider> + </el-form-item> + <el-form-item label="棰滆壊"> + <el-color-picker v-model="form.rainColor" /> + </el-form-item> + </el-form> +</template> + +<script setup> +import { reactive, watch } from "vue"; +const form = reactive({ + rainSize: 0.5, + rainSpeed: 50, + rainColor: "#99B3CC", +}); + +// 瀹氫箟 props 鍜� emit +const props = defineProps({ + modelValue: { + type: Object, + default: () => ({}), + }, +}); +const emit = defineEmits(["update-rain"]); + +// 鐩戝惉 form 鐨勫彉鍖栵紝骞跺皢鏈�鏂板�间紶閫掔粰鐖剁粍浠� +watch( + () => ({ ...form }), // 娣辨嫹璐濅互纭繚鍝嶅簲寮忚Е鍙� + (newVal) => { + emit("update-rain", newVal); + }, + { deep: true } // 娣卞害鐩戝惉 +); +</script> +<style lang="less" scoped> +.terrain-settings { + padding: 20px; + width: 290px; + background: url("@/assets/img/tools/plotting_new.png") no-repeat; + filter: opacity(83%); + background-size: 100% 100%; + box-sizing: border-box; +} +</style> diff --git a/src/components/tools/SlopeAnalysis.vue b/src/components/tools/SlopeAnalysis.vue index 23b690d..7609ef4 100644 --- a/src/components/tools/SlopeAnalysis.vue +++ b/src/components/tools/SlopeAnalysis.vue @@ -48,7 +48,7 @@ const form = reactive({ terrainRender: 0, contourLines: false, - color: "", + color: "red", spacing: 50, lineWidth: 5, }); @@ -78,14 +78,7 @@ display: flex; } -/deep/ .el-slider__bar { - background-color: #009688; - border-color: #009688; -} -/deep/ .el-slider__button { - border-color: rgb(0, 150, 136); -} /deep/ .el-switch.is-checked .el-switch__core { background-color: #009688; diff --git a/src/components/tools/Tools.vue b/src/components/tools/Tools.vue index 79bda9b..53139b3 100644 --- a/src/components/tools/Tools.vue +++ b/src/components/tools/Tools.vue @@ -54,6 +54,12 @@ class="popup-menu-see" @update-slope="onUpdateSlope" /> + <!-- 闆� --> + <Rain + v-show="showRain" + class="popup-menu-see" + @update-rain="onUpdateRain" + /> </div> <!-- 宸ュ叿鏍忓唴瀹� --> @@ -85,12 +91,12 @@ import Aspect from "@/components/tools/Aspect.vue"; import SlopeAnalysis from "@/components/tools/SlopeAnalysis.vue"; import mapUtils from "@/utils/tools.js"; +import Rain from "@/components/tools/Rain.vue"; // 鍒囨崲灞曞紑/鏀剁缉鐘舵�� function toggleCollapse() { // isCollapsed.value = !isCollapsed.value; } - const showLayerTree = ref(false); @@ -101,7 +107,7 @@ const isflfx = ref(false); const isFlood = ref(false); const isContourLabel = ref(false); -const isRain = ref(false); +const showRain = ref(false); const isSnow = ref(false); // 鍓栭潰鍒嗘瀽寮圭獥 @@ -197,6 +203,7 @@ echartsShow.value = false; //鍓栭潰echarts showAspect.value = false; //鍧″悜绠ご showSlope.value = false; //鍧″悜绠ご + showRain.value = false; //闆ㄥぉ return; } @@ -209,6 +216,7 @@ echartsShow.value = false; //鍓栭潰echarts showAspect.value = false; //鍧″悜绠ご showSlope.value = false; //鍧″悜绠ご + showRain.value = false; //闆ㄥぉ } // 澶勭悊寮圭獥閫夐」鐐瑰嚮浜嬩欢 @@ -219,12 +227,7 @@ 鏄剧ず鍥惧眰: () => (showLayerTree.value = true), 闅愯棌鍥惧眰: () => (showLayerTree.value = false), 闆ㄥぉ妯″紡: () => { - isRain.value = !isRain.value; - if (isRain.value === false) { - mapUtils.toggleRain("rain", false); - } else { - mapUtils.toggleRain("rain", true); - } + showRain.value = true; }, 闆ぉ妯″紡: () => { isSnow.value = !isSnow.value; @@ -402,6 +405,18 @@ Object.assign(formData, newOption); mapUtils.pdfx(formData); }; + +// 闆� +const rainForm = reactive({ + rainSize: 0.5, + rainSpeed: 50, + rainColor: "#99B3CC", +}); +const onUpdateRain = (newOption) => { + console.log(newOption, "new"); + Object.assign(rainForm, newOption); + mapUtils.toggleRain(rainForm, true); +}; </script> <style lang="less" scoped> diff --git a/src/utils/rain.js b/src/utils/rain.js new file mode 100644 index 0000000..a7499e5 --- /dev/null +++ b/src/utils/rain.js @@ -0,0 +1,82 @@ +class RainEffect { + constructor(viewer, options) { + if (!viewer) throw new Error("no viewer object!"); + options = options || {}; + //鍊炬枩瑙掑害锛岃礋鏁板悜鍙筹紝姝f暟鍚戝乏 + this.tiltAngle = Cesium.defaultValue(options.tiltAngle, -0.6); + this.rainSize = Cesium.defaultValue(options.rainSize, 0.3); + this.rainSpeed = Cesium.defaultValue(options.rainSpeed, 60.0); + this.color = Cesium.defaultValue(options.color, new Cesium.Color(0.6, 0.7, 0.8, 1.0)); + this.viewer = viewer; + this.init(); + } + + init() { + this.rainStage = new Cesium.PostProcessStage({ + name: "czm_rain", + fragmentShader: this.rain(), + uniforms: { + tiltAngle: () => { + return this.tiltAngle; + }, + rainSize: () => { + return this.rainSize; + }, + rainColor: () => { + return this.color; + }, + rainSpeed: () => { + return this.rainSpeed; + }, + }, + }); + this.viewer.scene.postProcessStages.add(this.rainStage); + } + + destroy() { + if (!this.viewer || !this.rainStage) return; + this.viewer.scene.postProcessStages.remove(this.rainStage); + const isDestroyed = this.rainStage.isDestroyed(); + // 鍏堟鏌ユ槸鍚﹁閿�姣佽繃锛屽鏋滃凡缁忚閿�姣佽繃鍐嶈皟鐢╠estroy浼氭姤閿� + if (!isDestroyed) { + this.rainStage.destroy(); + } + delete this.tiltAngle; + delete this.rainSize; + delete this.rainSpeed; + } + + show(visible) { + this.rainStage.enabled = visible; + } + + rain() { + return "uniform sampler2D colorTexture;\n\ + in vec2 v_textureCoordinates;\n\ + uniform float tiltAngle;\n\ + uniform vec4 rainColor;\n\ + uniform float rainSize;\n\ + uniform float rainSpeed;\n\ + float hash(float x) {\n\ + return fract(sin(x * 133.3) * 13.13);\n\ + }\n\ + out vec4 fragColor;\n\ + void main(void) {\n\ + float time = czm_frameNumber * (rainSpeed / 10000.0);\n\ + vec2 resolution = czm_viewport.zw;\n\ + vec2 uv = (gl_FragCoord.xy * 2. - resolution.xy) / min(resolution.x, resolution.y);\n\ + vec3 c = rainColor.rgb;\n\ + float a = tiltAngle;\n\ + float si = sin(a), co = cos(a);\n\ + uv *= mat2(co, -si, si, co);\n\ + uv *= length(uv + vec2(0, 4.9)) / (rainSize * 3.0 + 0.1) + 0.5;\n\ + float v = 1. - sin(hash(floor(uv.x * 100.)) * 2.);\n\ + float b = clamp(abs(sin(20. * time * v + uv.y * (5. / (2. + v)))) - .95, 0., 1.) * 20.;\n\ + c *= v * b;\n\ + fragColor = mix(texture(colorTexture, v_textureCoordinates), vec4(c, 1), .5);\n\ + }\n\ + "; + } +} + +export default RainEffect; diff --git a/src/utils/snow.js b/src/utils/snow.js new file mode 100644 index 0000000..2c8eeaa --- /dev/null +++ b/src/utils/snow.js @@ -0,0 +1,82 @@ +class SnowEffect { + constructor(viewer, options) { + if (!viewer) throw new Error("no viewer object!"); + options = options || {}; + this.snowSize = Cesium.defaultValue(options.snowSize, 0.02); // 鉂勶笍澶у皬锛屾渶濂藉皬浜�0.02 + this.snowSpeed = Cesium.defaultValue(options.snowSpeed, 100.0); // 閫熷害 + this.snowColor = Cesium.defaultValue(options.snowColor, new Cesium.Color(1.0, 1.0, 1.0, 1.0)); // 棰滆壊 + this.viewer = viewer; + this.init(); + } + + init() { + this.snowStage = new Cesium.PostProcessStage({ + name: "czm_snow", + fragmentShader: this.snow(), + uniforms: { + snowSize: () => { + return this.snowSize; + }, + snowSpeed: () => { + return this.snowSpeed; + }, + snowColor: () => { + return this.snowColor; + }, + }, + }); + this.viewer.scene.postProcessStages.add(this.snowStage); + } + + destroy() { + if (!this.viewer || !this.snowStage) return; + this.viewer.scene.postProcessStages.remove(this.snowStage); + const isDestroyed = this.snowStage.isDestroyed(); + // 鍏堟鏌ユ槸鍚﹁閿�姣佽繃锛屽鏋滃凡缁忚閿�姣佽繃鍐嶈皟鐢╠estroy浼氭姤閿� + if (!isDestroyed) { + this.snowStage.destroy(); + } + delete this.snowSize; + delete this.snowSpeed; + } + show(visible) { + this.snowStage.enabled = visible; + } + + snow() { + return "uniform sampler2D colorTexture;\n\ + in vec2 v_textureCoordinates;\n\ + uniform float snowSpeed;\n\ + uniform float snowSize;\n\ + uniform vec4 snowColor;\n\ + float snow(vec2 uv,float scale)\n\ + {\n\ + float time=czm_frameNumber/snowSpeed;\n\ + float w=smoothstep(1.,0.,-uv.y*(scale/10.));if(w<.1)return 0.;\n\ + uv+=time/scale;uv.y+=time*2./scale;uv.x+=sin(uv.y+time*.5)/scale;\n\ + uv*=scale;vec2 s=floor(uv),f=fract(uv),p;float k=3.,d;\n\ + p=.5+.35*sin(11.*fract(sin((s+p+scale)*mat2(7,3,6,5))*5.))-f;d=length(p);k=min(d,k);\n\ + k=smoothstep(0.,k,sin(f.x+f.y)*snowSize);\n\ + return k*w;\n\ + }\n\ + out vec4 fragColor;\n\ + void main(void){\n\ + vec2 resolution=czm_viewport.zw;\n\ + vec2 uv=(gl_FragCoord.xy*2.-resolution.xy)/min(resolution.x,resolution.y);\n\ + vec3 finalColor=vec3(0);\n\ + //float c=smoothstep(1.,0.3,clamp(uv.y*.3+.8,0.,.75));\n\ + float c=0.;\n\ + c+=snow(uv,30.)*.0;\n\ + c+=snow(uv,20.)*.0;\n\ + c+=snow(uv,15.)*.0;\n\ + c+=snow(uv,10.);\n\ + c+=snow(uv,8.);\n\ + c+=snow(uv,6.);\n\ + c+=snow(uv,5.);\n\ + finalColor=(vec3(c) * snowColor.rgb);\n\ + fragColor=mix(texture(colorTexture,v_textureCoordinates),vec4(finalColor,1),.5);\n\ + }\n\ + "; + } +} +export default SnowEffect; diff --git a/src/utils/tools.js b/src/utils/tools.js index 9b23612..6604c70 100644 --- a/src/utils/tools.js +++ b/src/utils/tools.js @@ -2,6 +2,7 @@ // import cameraIcon from "../assets/images/base/瑙嗛娴嬬偣.png" // import cameraIconSel from "../assets/images/base/瑙嗛娴嬬偣sel.png" import { ElLoading, ElMessage } from "element-plus"; +import RainEffect from './rain' let layerIsOpen = false; const Cesium = SmartEarth.Cesium; const colorAll = { @@ -19,10 +20,33 @@ analysisDXPMRes: [], slopeArrow: null, elevationTool: null, + rainEffect: null, init(earthCtrl) { this.earthCtrl = earthCtrl; return this; + }, + hexToColor(hexColor) { + const hex = hexColor.replace('#', ''); + const r = parseInt(hex.substring(0, 2), 16) / 255; + const g = parseInt(hex.substring(2, 4), 16) / 255; + const b = parseInt(hex.substring(4, 6), 16) / 255; + return new Cesium.Color(r, g, b, 1.0); + }, + // 澶╂皵 + toggleRain(option, show) { + console.log(option, 'option') + // 鍏堥攢姣佹棫瀹炰緥 + if (this.rainEffect) { + this.rainEffect.destroy() + this.rainEffect = null + } + this.rainEffect = new RainEffect(earthCtrl.viewer, { + tiltAngle: -0.2, //鍊炬枩瑙掑害 + rainSize: option.rainSize, // 闆ㄧ殑澶у皬 + rainSpeed: option.rainSpeed, // 闆ㄧ殑閫熷害 + color: this.hexToColor(option.rainColor) // 闆ㄧ殑棰滆壊 + }) }, // 鍧″害鍒嗘瀽 pdfx(option) { @@ -69,7 +93,7 @@ this.slopeArrow.setPositions(polygonPosition); this.slopeArrow.setSlopeType(1); this.slopeArrow.setRegionEnabled(true); - console.log(this.slopeArrow,'slope') + console.log(this.slopeArrow, 'slope') }); }, // 鍏抽棴鍧″悜绠ご @@ -79,14 +103,7 @@ } }, - // 澶╂皵 - toggleRain(weather = "rain", show) { - if (show) { - earthCtrl.environment.showEffect(weather); - } else { - earthCtrl.environment.disableEffect(weather); - } - }, + toggleSnow(weather = "snow", show) { if (show) { earthCtrl.environment.showEffect(weather); -- Gitblit v1.9.3