|
|
@@ -36,15 +36,20 @@
|
|
|
</template>
|
|
|
|
|
|
<script>
|
|
|
+import * as Cesium from "cesium";
|
|
|
import cloud from "/public/static/exportData/cloud/layer.json";
|
|
|
-import rainJson from "/public/static/exportData/rain/layer.json";
|
|
|
-import tempJson from "/public/static/exportData/tmp/layer.json";
|
|
|
-import windJson from "/public/static/exportData/wind/layer.json";
|
|
|
+import rain from "/public/static/exportData/rain/layer.json";
|
|
|
+import temp from "/public/static/exportData/tmp/layer.json";
|
|
|
+import wind from "/public/static/exportData/wind/layer.json";
|
|
|
|
|
|
import { VideoPlay, VideoPause } from "@element-plus/icons-vue";
|
|
|
|
|
|
import { ElMessage } from "element-plus";
|
|
|
|
|
|
+import { createWind } from "../../assets/wind/Windy.js";
|
|
|
+
|
|
|
+import axios from "axios";
|
|
|
+
|
|
|
export default {
|
|
|
props: {
|
|
|
mode: {
|
|
|
@@ -53,10 +58,17 @@ export default {
|
|
|
return "";
|
|
|
},
|
|
|
},
|
|
|
+ viewer: {
|
|
|
+ type: Object,
|
|
|
+ default: () => {
|
|
|
+ return {};
|
|
|
+ },
|
|
|
+ },
|
|
|
},
|
|
|
|
|
|
data() {
|
|
|
return {
|
|
|
+ cv: null,
|
|
|
sTimeRange: [0, 0],
|
|
|
sliderMax: 0,
|
|
|
progressLeft: 0,
|
|
|
@@ -64,16 +76,59 @@ export default {
|
|
|
percentage: 0,
|
|
|
marks: {},
|
|
|
cloudJson: [],
|
|
|
- setpLeft: 1,
|
|
|
+ rainJson: [],
|
|
|
+ tempJson: [],
|
|
|
+ windJson: [],
|
|
|
+ setpLeft: 0,
|
|
|
VideoPlay,
|
|
|
VideoPause,
|
|
|
isPlay: false,
|
|
|
playRange: [0, 0],
|
|
|
+ adUrls: [],
|
|
|
+ adLayers: [],
|
|
|
+ CONTROL_COLOR: {
|
|
|
+ uv: [
|
|
|
+ { color: "#f4f4f4", min: 0, max: 5, label: "0m/s ~ 5m/s" },
|
|
|
+ { color: "#fff465", min: 5, max: 10, label: "5m/s ~ 10m/s" },
|
|
|
+ { color: "#c5171e", min: 10, max: 15, label: "10m/s ~ 15m/s" },
|
|
|
+ { color: "#930f00", min: 15, max: 20, label: "15m/s ~ 20m/s" },
|
|
|
+ ],
|
|
|
+ shr: [
|
|
|
+ { color: "#00BFFF", min: 0, max: 0.034, label: "0 ~ 0.034-轻度" },
|
|
|
+ {
|
|
|
+ color: "#1E90FF",
|
|
|
+ min: 0.034,
|
|
|
+ max: 0.068,
|
|
|
+ label: "0.034 ~ 0.068-中度",
|
|
|
+ },
|
|
|
+ ],
|
|
|
+ edr: [
|
|
|
+ { color: "#87CEFA", min: 0, max: 0.22, label: "0 ~ 0.22-轻度" },
|
|
|
+ {
|
|
|
+ color: "#4169E1",
|
|
|
+ min: 0.22,
|
|
|
+ max: 0.35,
|
|
|
+ label: "0.22 ~ 0.35-中度",
|
|
|
+ },
|
|
|
+ {
|
|
|
+ color: "#0000CD",
|
|
|
+ min: 0.35,
|
|
|
+ max: 0.5,
|
|
|
+ label: "0.35 ~ 0.5-重度",
|
|
|
+ },
|
|
|
+ ],
|
|
|
+ },
|
|
|
+ windLayer: null,
|
|
|
+ needClearLayer: false,
|
|
|
};
|
|
|
},
|
|
|
|
|
|
created() {
|
|
|
+ this.cv = this.viewer;
|
|
|
this.cloudJson = cloud.reverse();
|
|
|
+ this.rainJson = rain.reverse();
|
|
|
+ this.tempJson = temp.reverse();
|
|
|
+ this.windJson = wind.reverse();
|
|
|
this.controlMode = this.mode || "";
|
|
|
this.sliderMax = this.cloudJson.length - 1;
|
|
|
this.sTimeRange = [0, this.sliderMax];
|
|
|
@@ -84,26 +139,53 @@ export default {
|
|
|
}
|
|
|
});
|
|
|
this.marks = marks;
|
|
|
+ window.addEventListener("keydown", this.handleKeyDown);
|
|
|
},
|
|
|
|
|
|
unmounted() {
|
|
|
clearInterval(this.progressTimmer);
|
|
|
this.progressTimmer = null;
|
|
|
+ window.removeEventListener("keydown", this.handleKeyDown);
|
|
|
},
|
|
|
|
|
|
methods: {
|
|
|
+ handleKeyDown(event) {
|
|
|
+ if (!this.isPlay && this.cv.scene.id) {
|
|
|
+ let changeLayer = false;
|
|
|
+ const scrollRange = this.sTimeRange[1] + 1 - (this.sTimeRange[0] + 1);
|
|
|
+ if (event.key.toLowerCase() === "a") {
|
|
|
+ this.setpLeft - 1 < 0
|
|
|
+ ? (this.setpLeft = scrollRange)
|
|
|
+ : (this.setpLeft -= 1);
|
|
|
+ changeLayer = true;
|
|
|
+ } else if (event.key.toLowerCase() === "d") {
|
|
|
+ this.setpLeft + 1 > scrollRange
|
|
|
+ ? (this.setpLeft = 0)
|
|
|
+ : (this.setpLeft += 1);
|
|
|
+ changeLayer = true;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (changeLayer) {
|
|
|
+ let p = parseInt((this.setpLeft / scrollRange) * 100);
|
|
|
+ this.percentage = p >= 100 ? 100 : p;
|
|
|
+
|
|
|
+ this.switchMapLayer();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
sliderFormatTooltip(value) {
|
|
|
let descStr = "";
|
|
|
if (value === this.sTimeRange[0]) {
|
|
|
- descStr = "起始时间: ";
|
|
|
+ descStr = "起始时间:";
|
|
|
} else if (value === this.sTimeRange[1]) {
|
|
|
- descStr = "截止时间: ";
|
|
|
+ descStr = "截止时间:";
|
|
|
}
|
|
|
- return `${descStr}${this.cloudJson[value].date}`;
|
|
|
+ return `${descStr} ${this.cloudJson[value].date}`;
|
|
|
},
|
|
|
|
|
|
progressFormat() {
|
|
|
- return this.cloudJson[this.sTimeRange[0] + (this.setpLeft - 1)].date;
|
|
|
+ return this.cloudJson[this.sTimeRange[0] + this.setpLeft].date;
|
|
|
},
|
|
|
|
|
|
sliderChange(value) {
|
|
|
@@ -112,11 +194,33 @@ export default {
|
|
|
);
|
|
|
this.progressWidth =
|
|
|
(value[1] / (this.cloudJson.length - 1)) * 96 - this.progressLeft;
|
|
|
+ this.setpLeft = 0;
|
|
|
+ this.resetData();
|
|
|
+ },
|
|
|
+
|
|
|
+ resetData() {
|
|
|
this.percentage = 0;
|
|
|
+ this.adLayers.forEach((ele) => {
|
|
|
+ this.cv.imageryLayers.remove(ele);
|
|
|
+ });
|
|
|
+ if (this.windLayer) {
|
|
|
+ this.windLayer.destroy();
|
|
|
+ }
|
|
|
},
|
|
|
|
|
|
playProgress() {
|
|
|
this.isPlay = !this.isPlay;
|
|
|
+
|
|
|
+ if (this.needClearLayer) {
|
|
|
+ this.adLayers.forEach((ele) => {
|
|
|
+ this.cv.imageryLayers.remove(ele);
|
|
|
+ });
|
|
|
+ if (this.windLayer) {
|
|
|
+ this.windLayer.destroy();
|
|
|
+ }
|
|
|
+ this.needClearLayer = false;
|
|
|
+ }
|
|
|
+
|
|
|
if (this.isPlay) {
|
|
|
const setpRight = this.sTimeRange[1];
|
|
|
|
|
|
@@ -129,36 +233,268 @@ export default {
|
|
|
) {
|
|
|
const [l, r] = this.sTimeRange;
|
|
|
this.playRange = [l, r];
|
|
|
- this.setpLeft = 1;
|
|
|
+ // this.setpLeft = 0;
|
|
|
}
|
|
|
|
|
|
ElMessage({
|
|
|
type: "primary",
|
|
|
plain: true,
|
|
|
showClose: true,
|
|
|
- message: `开始回滚 ${st} ~ ${et} 之间的数据`,
|
|
|
+ message:
|
|
|
+ st === et
|
|
|
+ ? `开始展示 ${st} 数据`
|
|
|
+ : `开始回滚 ${st} ~ ${et} 之间的数据`,
|
|
|
});
|
|
|
|
|
|
const scrollRange = this.sTimeRange[1] + 1 - (this.sTimeRange[0] + 1);
|
|
|
|
|
|
- this.progressTimmer = setInterval(() => {
|
|
|
- if (this.setpLeft > scrollRange) {
|
|
|
- this.setpLeft = 0;
|
|
|
- }
|
|
|
- let p = parseInt((this.setpLeft / scrollRange) * 100);
|
|
|
- this.percentage = p >= 100 ? 100 : p;
|
|
|
- this.setpLeft++;
|
|
|
- }, 1000);
|
|
|
+ const adUrls = this.getAddedUrls(
|
|
|
+ this.sTimeRange[0],
|
|
|
+ this.sTimeRange[1]
|
|
|
+ );
|
|
|
+
|
|
|
+ let adLayers = [];
|
|
|
+
|
|
|
+ adUrls.forEach((url) => {
|
|
|
+ const provider = new Cesium.SingleTileImageryProvider({
|
|
|
+ url,
|
|
|
+ rectangle: Cesium.Rectangle.fromDegrees(-180.0, -90.0, 180.0, 90.0), // 全球覆盖
|
|
|
+ tileWidth: 1440, // 根据你的图片实际宽度修改
|
|
|
+ tileHeight: 721,
|
|
|
+ });
|
|
|
+
|
|
|
+ const layer = this.viewer.imageryLayers.addImageryProvider(provider);
|
|
|
+ layer.alpha = 0.8; // 透明度
|
|
|
+ layer.brightness = 1; // 亮度
|
|
|
+ layer.contrast = 1; // 对比度
|
|
|
+ layer.show = false; // 初始隐藏
|
|
|
+ adLayers.push(layer);
|
|
|
+ });
|
|
|
+
|
|
|
+ this.adUrls = adUrls;
|
|
|
+
|
|
|
+ this.adLayers = adLayers;
|
|
|
+
|
|
|
+ if (this.setpLeft > scrollRange) {
|
|
|
+ this.setpLeft = 0;
|
|
|
+ }
|
|
|
+ let p = parseInt((this.setpLeft / scrollRange) * 100);
|
|
|
+ this.percentage = p >= 100 ? 100 : p;
|
|
|
+ this.switchMapLayer();
|
|
|
+
|
|
|
+ this.progressTimmer = setInterval(
|
|
|
+ () => {
|
|
|
+ this.setpLeft++;
|
|
|
+ if (this.setpLeft > scrollRange) {
|
|
|
+ this.setpLeft = 0;
|
|
|
+ }
|
|
|
+ let p = parseInt((this.setpLeft / scrollRange) * 100);
|
|
|
+ this.percentage = p >= 100 ? 100 : p;
|
|
|
+ this.switchMapLayer();
|
|
|
+ },
|
|
|
+ this.controlMode === "wind" ? 20000 : 2000
|
|
|
+ );
|
|
|
} else {
|
|
|
clearInterval(this.progressTimmer);
|
|
|
this.progressTimmer = null;
|
|
|
}
|
|
|
},
|
|
|
+
|
|
|
+ getAddedUrls(starIndex, endIndex) {
|
|
|
+ let imageUrls = [];
|
|
|
+ if (this?.cv?.scene?.id) {
|
|
|
+ if (this.controlMode) {
|
|
|
+ for (let i = starIndex; i <= endIndex; i++) {
|
|
|
+ imageUrls.push(`/static${this[`${this.controlMode}Json`][i].path}`);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return imageUrls;
|
|
|
+ },
|
|
|
+
|
|
|
+ async switchMapLayer() {
|
|
|
+ if (this.controlMode === "wind" && this.adUrls?.length) {
|
|
|
+ if (this.windLayer) {
|
|
|
+ this.windLayer.destroy();
|
|
|
+ }
|
|
|
+ const res = await axios.get(this.adUrls[this.setpLeft]);
|
|
|
+ this.windLayer = await createWind(
|
|
|
+ this.cv,
|
|
|
+ this.trJsonData(res.data),
|
|
|
+ this.CONTROL_COLOR
|
|
|
+ );
|
|
|
+ } else {
|
|
|
+ this.adLayers?.forEach((ele, index) => {
|
|
|
+ if (index === this.setpLeft) {
|
|
|
+ ele.show = true;
|
|
|
+ } else {
|
|
|
+ ele.show = false;
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ trJsonData(jsonData) {
|
|
|
+ function arrayMin(arr) {
|
|
|
+ let min = Infinity;
|
|
|
+ for (let i = 0; i < arr.length; i++) {
|
|
|
+ if (arr[i] < min) min = arr[i];
|
|
|
+ }
|
|
|
+ return min;
|
|
|
+ }
|
|
|
+
|
|
|
+ function arrayMax(arr) {
|
|
|
+ let max = -Infinity;
|
|
|
+ for (let i = 0; i < arr.length; i++) {
|
|
|
+ if (arr[i] > max) max = arr[i];
|
|
|
+ }
|
|
|
+ return max;
|
|
|
+ }
|
|
|
+ const uData = jsonData.find((ele) => {
|
|
|
+ return ele.header.parameterNumberName === "U-component_of_wind";
|
|
|
+ });
|
|
|
+ const uMin = arrayMin(uData.data);
|
|
|
+ const uMax = arrayMax(uData.data);
|
|
|
+
|
|
|
+ const vData = jsonData.find((ele) => {
|
|
|
+ return ele.header.parameterNumberName === "V-component_of_wind";
|
|
|
+ });
|
|
|
+ const vMin = arrayMin(vData.data);
|
|
|
+ const vMax = arrayMax(vData.data);
|
|
|
+
|
|
|
+ const bounds = {
|
|
|
+ west: uData.header.lo1,
|
|
|
+ south: uData.header.la2,
|
|
|
+ east: uData.header.lo2,
|
|
|
+ north: uData.header.la1,
|
|
|
+ };
|
|
|
+
|
|
|
+ return {
|
|
|
+ u: {
|
|
|
+ array: uData.data,
|
|
|
+ min: uMin,
|
|
|
+ max: uMax,
|
|
|
+ },
|
|
|
+ v: {
|
|
|
+ array: vData.data,
|
|
|
+ min: vMin,
|
|
|
+ max: vMax,
|
|
|
+ },
|
|
|
+ width: uData.header.nx,
|
|
|
+ height: uData.header.ny,
|
|
|
+ bounds,
|
|
|
+ };
|
|
|
+ },
|
|
|
},
|
|
|
|
|
|
watch: {
|
|
|
mode(val) {
|
|
|
this.controlMode = val;
|
|
|
+
|
|
|
+ this.adLayers.forEach((ele) => {
|
|
|
+ this.cv.imageryLayers.remove(ele);
|
|
|
+ });
|
|
|
+
|
|
|
+ if (this.windLayer) {
|
|
|
+ this.windLayer.destroy();
|
|
|
+ }
|
|
|
+
|
|
|
+ if (this.controlMode) {
|
|
|
+ if (this.isPlay) {
|
|
|
+ clearInterval(this.progressTimmer);
|
|
|
+ this.progressTimmer = null;
|
|
|
+
|
|
|
+ const scrollRange = this.sTimeRange[1] + 1 - (this.sTimeRange[0] + 1);
|
|
|
+
|
|
|
+ const adUrls = this.getAddedUrls(
|
|
|
+ this.sTimeRange[0],
|
|
|
+ this.sTimeRange[1]
|
|
|
+ );
|
|
|
+
|
|
|
+ let adLayers = [];
|
|
|
+
|
|
|
+ adUrls.forEach((url) => {
|
|
|
+ const provider = new Cesium.SingleTileImageryProvider({
|
|
|
+ url,
|
|
|
+ rectangle: Cesium.Rectangle.fromDegrees(
|
|
|
+ -180.0,
|
|
|
+ -90.0,
|
|
|
+ 180.0,
|
|
|
+ 90.0
|
|
|
+ ), // 全球覆盖
|
|
|
+ tileWidth: 1440, // 根据你的图片实际宽度修改
|
|
|
+ tileHeight: 721,
|
|
|
+ });
|
|
|
+
|
|
|
+ const layer =
|
|
|
+ this.viewer.imageryLayers.addImageryProvider(provider);
|
|
|
+ layer.alpha = 0.8; // 透明度
|
|
|
+ layer.brightness = 1; // 亮度
|
|
|
+ layer.contrast = 1; // 对比度
|
|
|
+ layer.show = false; // 初始隐藏
|
|
|
+ adLayers.push(layer);
|
|
|
+ });
|
|
|
+
|
|
|
+ this.adUrls = adUrls;
|
|
|
+
|
|
|
+ this.adLayers = adLayers;
|
|
|
+
|
|
|
+ this.switchMapLayer();
|
|
|
+ this.progressTimmer = setInterval(
|
|
|
+ () => {
|
|
|
+ this.setpLeft++;
|
|
|
+ if (this.setpLeft > scrollRange) {
|
|
|
+ this.setpLeft = 0;
|
|
|
+ }
|
|
|
+ let p = parseInt((this.setpLeft / scrollRange) * 100);
|
|
|
+ this.percentage = p >= 100 ? 100 : p;
|
|
|
+ this.switchMapLayer();
|
|
|
+ },
|
|
|
+ this.controlMode === "wind" ? 20000 : 2000
|
|
|
+ );
|
|
|
+ } else {
|
|
|
+ const adUrls = this.getAddedUrls(
|
|
|
+ this.sTimeRange[0],
|
|
|
+ this.sTimeRange[1]
|
|
|
+ );
|
|
|
+
|
|
|
+ let adLayers = [];
|
|
|
+
|
|
|
+ adUrls.forEach((url) => {
|
|
|
+ const provider = new Cesium.SingleTileImageryProvider({
|
|
|
+ url,
|
|
|
+ rectangle: Cesium.Rectangle.fromDegrees(
|
|
|
+ -180.0,
|
|
|
+ -90.0,
|
|
|
+ 180.0,
|
|
|
+ 90.0
|
|
|
+ ), // 全球覆盖
|
|
|
+ tileWidth: 1440, // 根据你的图片实际宽度修改
|
|
|
+ tileHeight: 721,
|
|
|
+ });
|
|
|
+
|
|
|
+ const layer =
|
|
|
+ this.viewer.imageryLayers.addImageryProvider(provider);
|
|
|
+ layer.alpha = 0.8; // 透明度
|
|
|
+ layer.brightness = 1; // 亮度
|
|
|
+ layer.contrast = 1; // 对比度
|
|
|
+ layer.show = false; // 初始隐藏
|
|
|
+ adLayers.push(layer);
|
|
|
+ });
|
|
|
+
|
|
|
+ this.adUrls = adUrls;
|
|
|
+
|
|
|
+ this.adLayers = adLayers;
|
|
|
+
|
|
|
+ this.switchMapLayer();
|
|
|
+
|
|
|
+ this.needClearLayer = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ viewer(cv) {
|
|
|
+ this.cv = cv;
|
|
|
},
|
|
|
},
|
|
|
};
|