This commit is contained in:
Aifeilong 2023-09-27 19:19:46 +08:00
parent 326f6e97da
commit 77d3af2f1b
22 changed files with 11930 additions and 37352 deletions

34717
.pnp.cjs generated

File diff suppressed because one or more lines are too long

2042
.pnp.loader.mjs generated

File diff suppressed because it is too large Load Diff

1
.yarnrc.yml Normal file
View File

@ -0,0 +1 @@
nodeLinker: node-modules

11051
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -3,6 +3,7 @@
"version": "0.1.0",
"private": true,
"dependencies": {
"@ant-design/aliyun-theme": "^0.0.5",
"@ant-design/colors": "^7.0.0",
"@craco/craco": "^7.1.0",
"@rematch/core": "^2.2.0",
@ -13,7 +14,7 @@
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
"ahooks": "^3.7.8",
"antd": "^5.8.4",
"antd": "4.24.9",
"cesium": "^1.108.0",
"craco-cesium": "^1.2.0",
"craco-less": "^3.0.1",

View File

@ -1,4 +1,4 @@
// @import "~antd/dist/antd.less";
@import "~antd/dist/antd.less";
html,
body,

View File

@ -1,6 +1,8 @@
import { useDispatch } from "react-redux";
import { useCesium } from "resium";
function AntarcticaFlytoQTP() {
const dispatch = useDispatch();
const { viewer } = useCesium();
const { camera } = viewer;
@ -16,7 +18,7 @@ function AntarcticaFlytoQTP() {
duration: 10,
complete: function () {
setTimeout(() => {
camera.flyTo(area1Options);
camera.flyTo(plateauOptions);
}, 1000);
},
};
@ -63,8 +65,8 @@ function AntarcticaFlytoQTP() {
//
const plateauOptions = {
destination: Cesium.Cartesian3.fromDegrees(95, -30, 6000000),
duration: 10,
destination: Cesium.Cartesian3.fromDegrees(90, 20, 1600000),
duration: 5,
orientation: {
heading: Cesium.Math.toRadians(-15.0),
pitch: -Cesium.Math.PI_OVER_FOUR,
@ -79,16 +81,23 @@ function AntarcticaFlytoQTP() {
//
const sideViewOptions = {
destination: Cesium.Cartesian3.fromDegrees(70, -60, 14000000),
destination: Cesium.Cartesian3.fromDegrees(80, -60, 16000000),
// destination: Cesium.Cartesian3.fromDegrees(130, -10.5, 20000000),
duration: 5,
orientation: {
heading: Cesium.Math.toRadians(-10.0),
pitch: Cesium.Math.toRadians(-90),
pitch: Cesium.Math.toRadians(-92),
roll: 6.0,
},
complete: () => {
viewer.clock.shouldAnimate = true;
dispatch.data.updateToolbar({ showPanel: true });
setTimeout(() => {
camera.flyTo({
duration: 5,
destination: Cesium.Cartesian3.fromDegrees(90, -12, 14000000),
});
}, 40 * 1000);
},
};

View File

@ -1,17 +1,35 @@
import { useParams } from "react-router-dom";
import { CameraFlyTo } from "resium";
import LabFlytoQTP from "./LabFlytoQTP";
import AntarcticaFlytoQTP from "./AntarcticaFlytoQTP";
function CustomFlyTo({}) {
const { type } = useParams();
return type === "1" ? (
<LabFlytoQTP />
) : type === "2" ? (
<AntarcticaFlytoQTP />
) : (
<></>
switch (type) {
case "1":
return <LabFlytoQTP />;
case "2":
return <AntarcticaFlytoQTP />;
case "3":
// 西
return (
<CameraFlyTo
duration={5}
destination={Cesium.Cartesian3.fromDegrees(-38.0, 27, 16000000)}
/>
);
default:
//
return (
<CameraFlyTo
duration={5}
destination={Cesium.Cartesian3.fromDegrees(93, 30, 16000000)}
/>
);
}
}
export default CustomFlyTo;

View File

@ -9,7 +9,6 @@ const url = "http://analysis.tpdc.ac.cn/gs/geoserver/phitrellis/wms";
function LayerAntarcticaToQTP() {
const { imageLayer } = useSelector((state) => state.data);
console.log("imageLayer :>> ", imageLayer);
const tempProvider = useMemo(
() =>
new WebMapServiceImageryProvider({

View File

@ -1,5 +1,6 @@
import { useEffect } from "react";
import { useState } from "react";
import { Entity, PointGraphics, useCesium } from "resium";
import { useInterval } from "ahooks";
//
const dataAntarcticaToQTP = [
@ -12,17 +13,20 @@ const dataAntarcticaToQTP = [
{ longitude: 95, latitude: -30, height: 0, time: 60 },
];
let property;
function PathAntarcticaToQTP() {
const { viewer } = useCesium();
const [delay, setDelay] = useState(1000);
const start = viewer.clock.startTime;
const stop = viewer.clock.stopTime;
const currentTime = viewer.clock.currentTime;
const pathMaterial = new Cesium.Color(4 / 255, 251 / 255, 253 / 255);
useInterval(() => {
if (viewer.clock?.shouldAnimate) setDelay(undefined);
}, delay);
/**
* 计算飞行路径
* 数据坐标
@ -51,10 +55,7 @@ function PathAntarcticaToQTP() {
return property;
}
useEffect(() => {
property = createProperty(dataAntarcticaToQTP);
console.log("property 2:>> ", start, stop, currentTime, property);
}, []);
const property = createProperty(dataAntarcticaToQTP);
return (
<Entity
@ -63,8 +64,8 @@ function PathAntarcticaToQTP() {
availability={
new Cesium.TimeIntervalCollection([
new Cesium.TimeInterval({
start: start,
stop: stop,
start,
stop,
}),
])
}

View File

@ -1,4 +1,6 @@
import { useState } from "react";
import { Entity, PointGraphics, useCesium } from "resium";
import { useInterval } from "ahooks";
//
const dataLabToQTP = [
@ -11,6 +13,7 @@ const dataLabToQTP = [
function PathLabToQTP() {
const { viewer } = useCesium();
const [delay, setDelay] = useState(1000);
const start = viewer.clock.startTime;
const stop = viewer.clock.stopTime;
@ -20,6 +23,10 @@ function PathLabToQTP() {
color: new Cesium.Color(4 / 255, 251 / 255, 253 / 255),
});
useInterval(() => {
if (viewer.clock?.shouldAnimate) setDelay(undefined);
}, delay);
/**
* 计算飞行路径
* 数据坐标
@ -28,8 +35,6 @@ function PathLabToQTP() {
function createProperty(source) {
let property = new Cesium.SampledPositionProperty();
for (let i = 0; i < source.length; i++) {
const start = viewer.clock.startTime;
const stop = viewer.clock.stopTime;
let time = Cesium.JulianDate.addSeconds(
start,
source[i].time,
@ -42,7 +47,6 @@ function PathLabToQTP() {
);
//
property.addSample(time, position);
console.log("property for:>> ", property, start, stop, viewer);
}
property.setInterpolationOptions({
interpolationDegree: 10,

View File

@ -1,4 +1,7 @@
const xx = [
import { Entity, EllipseGraphics } from "resium";
import { Cartesian3 } from "cesium";
const fluxData = [
0.03256254, -0.23182425, -0.040055223, -0.03476936, -0.40450656, -0.18742515,
0.045675285, -0.1613145, 0.06295018, -0.14455463, -0.30952197, 0.08164308,
0.019849295, 0.08785298, -0.22862722, -0.29176497, -0.1504006, 0.06978327,
@ -15,9 +18,82 @@ const xx = [
-0.04151492, -0.1793385,
];
const colorBar = [
"#73d13d",
"#95de64",
"#b7eb8f",
"#d9f7be",
"#f6ffed",
"#fff1f0",
"#ffccc7",
"#ffa39e",
"#ff7875",
"#ff4d4f",
];
const ranges = [
[-999, -0.4],
[-0.4, -0.3],
[-0.3, -0.2],
[-0.2, -0.1],
[-0.1, 0],
[0, 0.1],
[0.1, 0.2],
[0.2, 0.3],
[0.3, 0.4],
[0.4, 999],
];
let dataIndex = 0;
const height = 201000;
//
function HeatFlux() {
return "heatFlux";
function HeatFlux({ position, index }) {
const [lon, lat] = position;
for (let i = 0; i < ranges.length; i++) {
const start = ranges[i][0];
const end = ranges[i][1];
if (fluxData[index] >= start && fluxData[index] <= end) {
dataIndex = i;
break;
}
}
return (
<Entity
id={`site-heat-flux-${index}`}
position={Cartesian3.fromDegrees(lon, lat, 0)}
description={`
<table className="description-table" style='width:100%'>
<tbody>
<tr>
<th style='width:40%; background-color:#4b4b4b; padding: 3' >
感热通量数据
</th>
<td style='background-color:#4b4b4b; padding: 3'>
${fluxData[index]}
</td>
</tr>
<tr>
<th style=' width: 40%; background-color: #323232; padding: 3 ' >
站点坐标
</th>
<td style=' background-color: #323232; padding: 3 ' > ${lon}${lat} </td>
</tr>
</tbody>
</table>
`}
>
<EllipseGraphics
material={new Cesium.Color.fromCssColorString(colorBar[dataIndex])}
semiMinorAxis={30000.0}
semiMajorAxis={30000.0}
extrudedHeight={400000}
height={height}
/>
</Entity>
);
}
export default HeatFlux;

View File

@ -1,4 +1,7 @@
const xx = [
import { Entity, EllipseGraphics } from "resium";
import { Cartesian3 } from "cesium";
const rainData = [
0.25309432, 0.296679, 0.39937696, -0.15093477, 0.17799897, 0.1186297,
0.07794944, 0.086336374, -0.016019614, -0.10862, 0.026069753, -0.005777068,
-0.04960121, -0.13736366, 0.268846, 0.32549506, 0.16180113, 0.34738356,
@ -15,9 +18,80 @@ const xx = [
0.10854135, -0.10280543,
];
const colorBar = [
"#ffc53d",
"#ffd666",
"#ffe58f",
"#fff1b8",
"#fffbe6",
"#e6f7ff",
"#bae7ff",
"#91d5ff",
"#69c0ff",
"#40a9ff",
];
const ranges = [
[-999, -0.4],
[-0.4, -0.3],
[-0.3, -0.2],
[-0.2, -0.1],
[-0.1, 0],
[0, 0.1],
[0.1, 0.2],
[0.2, 0.3],
[0.3, 0.4],
[0.4, 999],
];
let dataIndex = 0;
//
function Rain() {
return "xx";
function Rain({ position, index }) {
const [lon, lat] = position;
for (let i = 0; i < ranges.length; i++) {
const start = ranges[i][0];
const end = ranges[i][1];
if (rainData[index] >= start && rainData[index] <= end) {
dataIndex = i;
break;
}
}
return (
<Entity
id={`site-rain-${index}`}
position={Cartesian3.fromDegrees(lon, lat, 2000000)}
description={`
<table className="description-table" style='width:100%'>
<tbody>
<tr>
<th style='width:40%; background-color:#4b4b4b; padding: 3' >
青藏高原降水
</th>
<td style='background-color:#4b4b4b; padding: 3'>
${rainData[index]}
</td>
</tr>
<tr>
<th style=' width: 40%; background-color: #323232; padding: 3 ' >
站点坐标
</th>
<td style=' background-color: #323232; padding: 3 ' > ${lon}${lat} </td>
</tr>
</tbody>
</table>
`}
>
<EllipseGraphics
material={new Cesium.Color.fromCssColorString(colorBar[dataIndex])}
semiMinorAxis={30000.0}
semiMajorAxis={30000.0}
extrudedHeight={200000}
/>
</Entity>
);
}
export default Rain;

View File

@ -1,19 +1,14 @@
import { Entity, Primitive } from "resium";
import { Fragment } from "react";
import Rain from "./Rain";
import HeatFlux from "./HeatFlux";
const positions = [
98, 38, 95, 37, 97, 37, 101, 37, 94, 36, 96, 36, 98, 36, 100, 36, 101, 36,
101, 36, 99, 35, 88, 29, 91, 29, 92, 28, 97, 33, 101, 34, 101, 33, 102, 35,
104, 34, 93, 31, 95, 31, 96, 32, 97, 31, 94, 29, 100, 29, 98, 28, 101, 29,
102, 28, 99, 27, 99, 27, 100, 26, 101, 26, 90, 38, 93, 38, 99, 38, 100, 38,
93, 36, 100, 37, 102, 37, 93, 35, 80, 32, 84, 32, 90, 31, 91, 32, 92, 31, 81,
30, 88, 30, 91, 30, 87, 29, 91, 29, 85, 28, 87, 28, 89, 28, 89, 27, 92, 34,
95, 32, 95, 34, 98, 34, 97, 33, 98, 32, 99, 33, 102, 33, 98, 31, 100, 31, 100,
32, 100, 32, 101, 30, 102, 31, 102, 32, 102, 31, 103, 32, 93, 30, 95, 29, 99,
30, 100, 30, 100, 30, 97, 29, 101, 30, 101, 27, 101, 27,
];
function Site() {
return <Entity></Entity>;
function Site({ position, index }) {
return (
<Fragment>
<HeatFlux position={position} index={index} />
<Rain position={position} index={index} />
</Fragment>
);
}
export default Site;

View File

@ -1,5 +1,30 @@
function Site() {
return "";
import { useParams } from "react-router-dom";
import Site from "./Site";
import { chunk } from "lodash-es";
import { useSelector } from "react-redux";
const positions = [
98, 38, 95, 37, 97, 37, 101, 37, 94, 36, 96, 36, 98, 36, 100, 36, 101, 36,
101, 36, 99, 35, 88, 29, 91, 29, 92, 28, 97, 33, 101, 34, 101, 33, 102, 35,
104, 34, 93, 31, 95, 31, 96, 32, 97, 31, 94, 29, 100, 29, 98, 28, 101, 29,
102, 28, 99, 27, 99, 27, 100, 26, 101, 26, 90, 38, 93, 38, 99, 38, 100, 38,
93, 36, 100, 37, 102, 37, 93, 35, 80, 32, 84, 32, 90, 31, 91, 32, 92, 31, 81,
30, 88, 30, 91, 30, 87, 29, 91, 29, 85, 28, 87, 28, 89, 28, 89, 27, 92, 34,
95, 32, 95, 34, 98, 34, 97, 33, 98, 32, 99, 33, 102, 33, 98, 31, 100, 31, 100,
32, 100, 32, 101, 30, 102, 31, 102, 32, 102, 31, 103, 32, 93, 30, 95, 29, 99,
30, 100, 30, 100, 30, 97, 29, 101, 30, 101, 27, 101, 27,
];
function Sites() {
const { type } = useParams();
const { showSite } = useSelector((state) => state.data);
if (type !== "2") return <></>;
if (!showSite) return <></>;
return chunk(positions, 2).map((position, index) => {
return <Site key={`site-${index}`} index={index} position={position} />;
});
}
export default Site;
export default Sites;

View File

@ -0,0 +1,105 @@
import { useSelector } from "react-redux";
import styles from "./index.module.less";
const colorBar = [
"#ffc53d",
"#ffd666",
"#ffe58f",
"#fff1b8",
"#fffbe6",
"#e6f7ff",
"#bae7ff",
"#91d5ff",
"#69c0ff",
"#40a9ff",
];
const colorBar2 = [
"#73d13d",
"#95de64",
"#b7eb8f",
"#d9f7be",
"#f6ffed",
"#fff1f0",
"#ffccc7",
"#ffa39e",
"#ff7875",
"#ff4d4f",
];
function Legend42() {
return (
<div>
<div className={styles.verticalLegend} style={{ bottom: 476 }}>
<div className="legend-title">青藏高原感热通量</div>
<div style={{ flex: 1, width: "100%", display: "flex", gap: 8 }}>
<div className="legend-text">
{[-0.5, -0.4, -0.3, -0.2, -0.1, 0, 0.1, 0.2, 0.3, 0.4, 0.5].map(
(item, index) => {
return (
<div
key={`legend-text-item-${index}`}
className="legend-text-item"
>
{item}
</div>
);
}
)}
</div>
<div className="colorbar">
{colorBar2.map((color, index) => {
return (
<div
key={`colorbar-item-${index}`}
className="colorbar-item"
style={{ backgroundColor: color }}
title={`${(-0.5 + index * 0.1).toFixed(1)}~${(
-0.5 +
(index + 1) * 0.1
).toFixed(1)}`}
/>
);
})}
</div>
</div>
</div>
<div className={styles.verticalLegend}>
<div className="legend-title">青藏高原降水量</div>
<div style={{ flex: 1, width: "100%", display: "flex", gap: 8 }}>
<div className="legend-text">
{[-0.5, -0.4, -0.3, -0.2, -0.1, 0, 0.1, 0.2, 0.3, 0.4, 0.5].map(
(item, index) => {
return (
<div
key={`legend-text-item-${index}`}
className="legend-text-item"
>
{item}
</div>
);
}
)}
</div>
<div className="colorbar">
{colorBar.map((color, index) => {
return (
<div
key={`colorbar-item-${index}`}
className="colorbar-item"
style={{ backgroundColor: color }}
title={`${(-0.5 + index * 0.1).toFixed(1)}~${(
-0.5 +
(index + 1) * 0.1
).toFixed(1)}`}
/>
);
})}
</div>
</div>
</div>
</div>
);
}
export default Legend42;

View File

@ -1,11 +1,17 @@
import { useParams } from "react-router-dom";
import Legend41 from "./Legend41";
import Legend42 from "./Legend42";
import Legend45 from "./Legend45";
import { useSelector } from "react-redux";
function Legends() {
const { type } = useParams();
const { toolbar } = useSelector((state) => state.data);
if (!toolbar.showPanel) return <></>;
if (type === "1") return <Legend41 />;
if (type === "2") return <Legend42 />;
else if (type === "5") return <Legend45 />;
else return <></>;
}

View File

@ -52,3 +52,58 @@
}
}
}
.verticalLegend :global {
position: absolute;
bottom: 168px;
right: 0;
height: 300px;
width: 130px;
display: flex;
flex-direction: column;
align-items: center;
background-color: #1f485690;
border: 1px solid #04fbfd;
border-radius: 8px;
padding: 8px;
.legend-title {
color: #04fbfd;
}
.colorbar {
width: 100px;
display: flex;
flex-direction: column;
justify-content: space-between;
height: 100%;
.colorbar-item {
flex: 1;
border: 2px black solid;
border-left: none;
border-right: none;
height: 25px;
width: 25px;
&:not(:nth-child(1)) {
border-top: none;
}
}
}
.legend-text {
display: flex;
flex-direction: column;
justify-content: space-between;
width: 100%;
.legend-text-item {
flex: 1;
text-align: right;
font-weight: 600;
color: white;
-webkit-text-stroke: #04fbfd 1px;
}
}
}

View File

@ -25,12 +25,13 @@ function MapLayout() {
homeButton={false}
sceneModePicker={false}
navigationHelpButton={false}
shouldAnimate={true}
shouldAnimate={false}
// infoBox={false}
timeline={false}
fullscreenButton={false}
geocoder={false}
baseLayerPicker={false}
animation={false}
>
<CustomClock />
<CustomFlyTo />

View File

@ -27,30 +27,30 @@
.ant-select-selector {
color: #02f9ff;
border: 1px solid #04fbfd !important;
background-color: #1f4856;
padding: 4px 12px;
border-radius: 8px;
height: 39px;
font-size: 16px;
background-color: #1f4856 !important;
padding: 4px 12px !important;
border-radius: 8px !important;
height: 39px !important;
font-size: 14px !important;
.ant-select-selection-item {
color: #02f9ff !important;
}
.ant-select-dropdown {
background-color: #1f4856;
background-color: #1f4856 !important;
.ant-select-item {
color: rgb(0, 242, 255);
font-size: 16px;
font-size: 14px;
&:hover {
background-color: #33a4a4;
background-color: #33a4a4 !important;
}
}
.ant-select-item-option-selected {
background-color: #33a4a4;
background-color: #33a4a4 !important;
}
}

View File

@ -201,14 +201,3 @@ export const COLORS = {
"Color.YELLOWGREEN": Color.YELLOWGREEN,
"Color.TRANSPARENT": Color.TRANSPARENT,
};
export const PATH = {
实时视频: "/台站数据/实时视频",
实时监测: "http://chinare.hbaa.cn/iot/yulong.php",
在线数据: "/台站数据/在线数据",
数据申请: "/数据申请",
离线数据: "/manage/offlinedata",
申请审核: "/manage/applydata",
数据分类: "/manage/datatype",
用户管理: "/manage/user",
};

967
yarn.lock

File diff suppressed because it is too large Load Diff