This commit is contained in:
Aifeilong 2023-10-16 17:24:22 +08:00
parent 0345e29ce0
commit 20f2a8fa81
21 changed files with 779 additions and 4 deletions

View File

@ -4,7 +4,9 @@ import DomainOne from "@/components/domain/One";
import DomainTwo from "@/components/domain/Two"; import DomainTwo from "@/components/domain/Two";
import DomainThree from "@/components/domain/Three"; import DomainThree from "@/components/domain/Three";
import DomainFour from "@/components/domain/Four"; import DomainFour from "@/components/domain/Four";
import DomainFive from "./components/domain/Five"; import DomainFive from "@/components/domain/Five";
import DomainSix from "@/components/domain/Six";
import ClimateReconDataAssim from "@/components/catalog/IntegrationAndOnlineCalc/ClimateReconDataAssim";
import "./App.less"; import "./App.less";
function App() { function App() {
@ -16,6 +18,11 @@ function App() {
<Route path="map/3" element={<DomainThree />}></Route> <Route path="map/3" element={<DomainThree />}></Route>
<Route path="map/4" element={<DomainFour />}></Route> <Route path="map/4" element={<DomainFour />}></Route>
<Route path="map/5" element={<DomainFive />}></Route> <Route path="map/5" element={<DomainFive />}></Route>
<Route path="map/6" element={<DomainSix />}></Route>
<Route
path="map/climateReconDataAssim"
element={<ClimateReconDataAssim />}
></Route>
<Route path="*" element={<Navigate to={"/"} replace={true} />} /> <Route path="*" element={<Navigate to={"/"} replace={true} />} />
</Routes> </Routes>
); );

View File

@ -0,0 +1,75 @@
import { Button, Form, Input, InputNumber, Select } from "antd";
const layout = {
labelCol: { span: 10 },
wrapperCol: { span: 12 },
};
const tailLayout = {
wrapperCol: { offset: 10, span: 14 },
};
export default function FormPanel({ setShow }) {
const [form] = Form.useForm();
return (
<div className="form-panel">
<Form
{...layout}
form={form}
name="control-hooks"
initialValues={{
N: 100,
MCMC: 50,
randFlag: 1,
proxyFlag: 1,
L: 5000,
}}
onFinish={(values) => {
// valuescharts
// setShow(true);
}}
>
<Form.Item
name="N"
label="背景场集合数量"
rules={[{ required: true, message: "背景场集合数量是必填项" }]}
>
<InputNumber precision={0} placeholder="请输入背景场集合数量" />
</Form.Item>
<Form.Item
name="MCMC"
label="蒙特卡罗采样次数"
rules={[{ required: true, message: "蒙特卡罗采样次数是必填项" }]}
>
<InputNumber precision={0} placeholder="请输入蒙特卡罗采样次数" />
</Form.Item>
<Form.Item
name="randFlag"
label="随机数生成方式"
rules={[{ required: true, message: "随机数生成方式是必选项" }]}
>
<Select options={[{ label: "随机数生成方式一", value: 1 }]} />
</Form.Item>
<Form.Item
name="proxyFlag"
label="同化代用资料的方式"
rules={[{ required: true, message: "同化代用资料的方式是必选项" }]}
>
<Select options={[{ label: "同化代用资料方式一", value: 1 }]} />
</Form.Item>
<Form.Item
name="L"
label="协方差局地化半径(KM)"
rules={[{ required: true, message: "协方差局地化半径是必填项" }]}
>
<InputNumber placeholder="请输入协方差局地化半径" />
</Form.Item>
<Form.Item {...tailLayout}>
<Button type="primary" htmlType="submit">
提交
</Button>
</Form.Item>
</Form>
</div>
);
}

View File

@ -0,0 +1,36 @@
import styles from "./index.module.less";
// const colorBar = [
// #830000
// #000083
// ];
function Legend({ style }) {
return (
<div className={styles.legend} style={{ ...style }}>
<div className="legend-title">Temperature anomaly()</div>
<div
className="colorbar"
style={{ background: "linear-gradient(to right,#000083,#fff,#830000)" }}
></div>
<div className="legend-text">
{[-1, -0.5, 0, 0.5, 1].map((item, index) => {
return (
<div
key={`legend-text-item-${index}`}
className="legend-text-item"
style={{
textAlign:
index === 2 ? "center" : index < 2 ? "left" : "right",
}}
>
{item}
</div>
);
})}
</div>
</div>
);
}
export default Legend;

View File

@ -0,0 +1,19 @@
import MapLayout from "@/components/map/Layout";
import FormPanel from "./FormPanel";
import styles from "./index.module.less";
import Legend from "./Legend";
function ClimateReconDataAssim() {
return (
<div className={styles.climateReconDataAssim}>
<MapLayout>
<div className="formPanel">
<FormPanel />
</div>
<Legend />
</MapLayout>
</div>
);
}
export default ClimateReconDataAssim;

View File

@ -0,0 +1,98 @@
.climateReconDataAssim :global {
.formPanel {
position: absolute;
top: 84px;
right: 12px;
width: 450px;
background-color: #000000e7;
.form-panel {
width: 100%;
height: 100%;
pointer-events: auto;
padding: 12px;
border: 1px solid #04fbfd;
color: #02f9ff !important;
background-color: #000000e7;
border-radius: 8px;
.ant-form-item-label {
label {
color: white;
}
}
.ant-form-item-control {
.ant-select-multiple {
max-height: 300px;
overflow-y: scroll;
&::-webkit-scrollbar {
width: 6px;
height: 1px;
}
&::-webkit-scrollbar-thumb {
border-radius: 6px;
background: #00a2a2;
}
&::-webkit-scrollbar-track {
border-radius: 6px;
background: none;
}
}
}
}
}
}
.legend :global {
position: absolute;
bottom: 14px;
width: 50%;
left: 25%;
z-index: 1000;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
background-color: #000000e7;
border: 1px solid #04fbfd;
border-radius: 8px;
padding: 8px;
.legend-title {
color: #04fbfd;
}
.colorbar {
width: 100%;
height: 14px;
display: flex;
margin: 8px 0;
.colorbar-item {
flex: 1;
height: 100%;
border: 1px black solid;
&:not(:nth-child(1)) {
border-left: none;
}
}
}
.legend-text {
display: flex;
justify-content: space-evenly;
width: 100%;
height: 20px;
.legend-text-item {
flex: 1;
text-align: right;
font-weight: 600;
color: white;
-webkit-text-stroke: #04fbfd 1px;
}
}
}

View File

@ -17,6 +17,56 @@ function CustomToolbar() {
}, },
key: "/", key: "/",
}, },
{
label: "数据集成和共享",
title: "数据集成和共享",
value: "/map/",
icon: <MenuUnfoldOutlined />,
onClick: () => {
navigate("/", { replace: true });
},
// key: "/ ",
},
{
label: "随机森林方法在线计算案例",
title: "随机森林方法在线计算案例",
value: "/map/",
icon: <MenuUnfoldOutlined />,
onClick: () => {
navigate("/", { replace: true });
},
// key: "/ ",
},
{
label: "过去千年气候重建数据同化",
title: "过去千年气候重建数据同化",
value: "/map/",
icon: <MenuUnfoldOutlined />,
onClick: () => {
navigate("/map/climateReconDataAssim", { replace: true });
},
key: "/map/climateReconDataAssim",
},
{
label: "北极海冰预报",
title: "北极海冰预报",
value: "/map/",
icon: <MenuUnfoldOutlined />,
onClick: () => {
navigate("/", { replace: true });
},
// key: "/ ",
},
{
label: "北极航线智能规划",
title: "北极航线智能规划",
value: "/map/",
icon: <MenuUnfoldOutlined />,
onClick: () => {
navigate("/", { replace: true });
},
// key: "/ ",
},
{ {
label: "两极协同—拉布拉多海海温偏暖控制夏季高原年代际增温", label: "两极协同—拉布拉多海海温偏暖控制夏季高原年代际增温",
title: "两极协同—拉布拉多海海温偏暖控制夏季高原年代际增温", title: "两极协同—拉布拉多海海温偏暖控制夏季高原年代际增温",
@ -67,6 +117,16 @@ function CustomToolbar() {
}, },
key: "/map/5", key: "/map/5",
}, },
{
label: "三极冰盖/冰川表面冰雪冻融对比关联与科学认知",
title: "三极冰盖/冰川表面冰雪冻融对比关联与科学认知",
value: "/map/6",
icon: <MenuUnfoldOutlined />,
onClick: () => {
navigate("/map/6", { replace: true });
},
key: "/map/6",
},
]; ];
return ( return (

View File

@ -0,0 +1,138 @@
import ReactECharts from "echarts-for-react";
const years = [];
for (let year = 1961; year <= 2010; year++) {
years.push(year);
}
//
const AntarcticaData = [];
//
const ArcticData = [];
//
const TibetanData = [];
function ChartPanel() {
const option = {
title: {
// text: "Stacked Line",
},
tooltip: {
trigger: "axis",
},
legend: {
data: ["南极", "北极", "青藏高原"],
textStyle: { color: "#04fbfd", cursor: "point" },
},
animationDuration: 10 * 1000,
animationEasing: "cubicInOut",
grid: {
left: "3%",
right: "4%",
bottom: "3%",
containLabel: true,
},
// toolbox: {
// feature: {
// //
// saveAsImage: {},
// },
// },
xAxis: {
type: "category",
boundaryGap: false,
data: years,
axisLine: {
onZero: false,
symbol: ["none", "arrow"],
symbolOffser: [0, 10],
lineStyle: {
color: "#04fbfd",
},
},
axisLabel: {
interval: 4,
},
},
yAxis: {
type: "value",
min: 0,
max: 1800000,
// interval: 0.5,
// splitNumber: 5,
splitLine: { show: false },
axisLine: {
onZero: false,
show: true,
symbol: ["none", "arrow"],
symbolOffset: [0, 1],
lineStyle: {
color: "#04fbfd",
},
},
axisLabel: {
show: true,
interval: 300000,
},
axisTick: { show: true },
scale: true,
},
dataZoom: { type: "inside", start: 0, end: 100 },
series: [
{
name: "北极",
type: "line",
stack: "Total",
data: AntarcticaData,
smooth: true,
color: "red",
symbol: "none",
itemStyle: {
color: "red",
},
},
{
name: "南极",
type: "line",
// stack: "Total",
data: ArcticData,
smooth: true,
color: "blue",
symbol: "none",
itemStyle: {
color: "blue",
},
},
{
name: "青藏高原",
type: "line",
// stack: "Total",
data: TibetanData,
smooth: true,
color: "green",
symbol: "none",
itemStyle: {
color: "green",
},
},
],
};
return (
<div className="chart-info-panel">
<ReactECharts
option={option}
lazyUpdate={true}
style={{
height: "100%",
width: "100%",
}}
/>
</div>
);
}
export default ChartPanel;

View File

@ -0,0 +1,48 @@
const colorBar = [
"#FB2421",
"#FF0000",
"#FF3602",
"#FF8103",
"#FFC207",
"#F8F805",
"#CEFE4C",
"#95FF8C",
"#94FF8D",
"#15FEC8",
"#0AFEFB",
"#00C3FF",
"#3D74FD",
"#4C08FF",
"#4600FF",
];
function Legend() {
return (
<div
className="legend"
style={{
background: `linear-gradient(to right,#FB2421,#FF0000,#FF3602,#FF8103,#FFC207,#F8F805,#CEFE4C,#95FF8C,#94FF8D,#15FEC8,#0AFEFB,#00C3FF,#3D74FD,#4C08FF,#4600FF)`,
}}
>
<div className="legend-title">1</div>
<div className="legend-text">
{[-0.8, -0.4, 0, 0.4, 0.8].map((item, index) => {
return (
<div
key={`legend-text-item-${index}`}
className="legend-text-item"
style={{
textAlign:
index === 2 ? "center" : index < 2 ? "left" : "right",
}}
>
{item}
</div>
);
})}
</div>
</div>
);
}
export default Legend;

View File

@ -0,0 +1,24 @@
import { Cartesian3 } from "cesium";
import { CameraFlyTo } from "resium";
import WavePoint from "@/components/common/WavePoint";
import MapLayout from "@/components/map/Layout";
function ViewerOne() {
return (
<div className="domain-viewer one">
<MapLayout>
<div className="title" style={{ zIndex: 1 }}>
三极冰盖/冰川表面冰雪融化时空变化特征对比及其变化原因异同
</div>
<CameraFlyTo
duration={5}
destination={Cartesian3.fromDegrees(100, -89.9, 10000000)}
/>
<WavePoint stationLon={100} stationLat={-85} labelText={"南极"} />
</MapLayout>
<div className="name">南极冻融天数</div>
</div>
);
}
export default ViewerOne;

View File

@ -0,0 +1,21 @@
import { Cartesian3 } from "cesium";
import { CameraFlyTo } from "resium";
import WavePoint from "@/components/common/WavePoint";
import MapLayout from "@/components/map/Layout";
function ViewerThree() {
return (
<div className="domain-viewer three">
<MapLayout>
<CameraFlyTo
duration={5}
destination={Cartesian3.fromDegrees(90, 33, 10000000)}
/>
<WavePoint stationLon={90} stationLat={33} labelText={"青藏高原"} />
</MapLayout>
<div className="name">青藏高原冻融天数</div>
</div>
);
}
export default ViewerThree;

View File

@ -0,0 +1,21 @@
import { Cartesian3 } from "cesium";
import { CameraFlyTo } from "resium";
import WavePoint from "@/components/common/WavePoint";
import MapLayout from "@/components/map/Layout";
function ViewerTwo() {
return (
<div className="domain-viewer two">
<MapLayout>
<CameraFlyTo
duration={5}
destination={Cartesian3.fromDegrees(-40, 70, 10000000)}
/>
<WavePoint stationLon={-40} stationLat={70} labelText={"格陵兰岛"} />
</MapLayout>
<div className="name">格陵兰岛冻融天数</div>
</div>
);
}
export default ViewerTwo;

View File

@ -0,0 +1,33 @@
import TextInfoPanel from "@/components/common/TextInfoPanel";
import ViewerOne from "./ViewerOne";
import ViewerThree from "./ViewerThree";
import ViewerTwo from "./ViewerTwo";
import ChartPanel from "./ChartPanel";
import styles from "./index.module.less";
import Legend from "./Legend";
function SceneOne() {
return (
<div className={styles.sceneOne}>
<div className="domain-viewers">
<ViewerOne />
<ViewerTwo />
<ViewerThree />
{/* <Legend /> */}
</div>
<div className="domain-info">
<div className="left-panel one">
<TextInfoPanel
content={`基于长时序的被动微波辐射亮温数据,改进了基于小波分析的冰盖表面冻融探测算法,并研发长时序的三极地区冰川/冰盖冻融据集基于自主研发的近40年三极冰盖/冰川冻融产品,对三极冰盖/冰川表面冰雪冻融进行了对比分析研究,分析其变化特征、关联机制及影响。
受青藏高原增温影响该地区积雪融化开始时间提前结束时间推迟持续时间增长受北极放大效应影响格陵兰冰盖融化开始时间提前结束时间推迟持续时间增长受海--气相互作用影响南极冰盖融化开始时间推迟结束时间也推迟持续时间缩短进一步我们对南北极冰盖冻融的变化特征进行了关联分析研究发现在较长的时间尺度上南极冰盖冻融对北极冰盖冻融有强的负影响即南极冰盖冻融减弱或增强后相隔2年后北极冰盖冻融增强或减弱通过与北大西洋年代际振荡指数进行相关分析发现南北极冰盖冻融负相关变化可能受大西洋经向翻转环流强度变化影响南极冰雪冻融推迟的海--气作用机制研究发现南极融雪季推迟导致冰雪反照率反馈减弱由于冰盖表面融化季的整体推迟导致高反照率条件越过了太阳辐射峰值从而减少了地表净太阳辐射相比海冰增加造成的地表净太阳辐射变化融雪区域融化季推迟对辐射平衡总变化的影响更多该研究指出将冰盖表面融化过程纳入到气候和冰盖模型将有助于更好地改进对区域气候变化冰盖物质平衡和海平面上升的预测`}
/>
</div>
<div className="right-panel">
<ChartPanel />
</div>
</div>
</div>
);
}
export default SceneOne;

View File

@ -0,0 +1,136 @@
.sceneOne :global {
display: flex;
flex-direction: column;
width: 100%;
height: 100%;
background-color: darkslategray;
.domain-viewers {
width: 100%;
flex: 1;
display: flex;
position: relative;
.domain-viewer {
flex: 1;
position: relative;
.title {
pointer-events: none;
}
.name {
position: absolute;
bottom: 0;
left: 12px;
font-size: 18px;
color: white;
padding: 4px;
background-color: rgba(0, 0, 0, 0.5);
}
}
.legend {
position: absolute;
bottom: 0;
left: 25%;
color: #02f9ff;
width: 50%;
}
}
.domain-info {
flex: 1;
margin: 12px;
display: flex;
justify-content: space-between;
gap: 12px;
.left-panel {
width: 450px;
display: flex;
flex-direction: column;
height: 100%;
.text-info-panel {
width: 100%;
height: 100%;
padding: 12px;
border: 1px solid #04fbfd;
color: #02f9ff !important;
background-color: #000000e7;
pointer-events: auto;
font-size: 18px;
text-indent: 2em;
line-height: 1.5;
z-index: 999;
border-radius: 8px;
}
}
.right-panel {
flex: 1;
min-width: 450px;
display: flex;
flex-direction: column;
gap: 12px;
.top-panel {
flex: 1;
}
.bottom-panel {
flex: 1;
}
.form-panel {
width: 100%;
height: 100%;
pointer-events: auto;
padding: 12px;
border: 1px solid #04fbfd;
color: #02f9ff !important;
background-color: #000000e7;
border-radius: 8px;
.ant-form-item-label {
label {
color: white;
}
}
.ant-form-item-control {
.ant-select-multiple {
max-height: 300px;
overflow-y: scroll;
&::-webkit-scrollbar {
width: 6px;
height: 1px;
}
&::-webkit-scrollbar-thumb {
border-radius: 6px;
background: #00a2a2;
}
&::-webkit-scrollbar-track {
border-radius: 6px;
background: none;
}
}
}
}
.chart-info-panel {
width: 100%;
height: 100%;
pointer-events: auto;
padding: 12px;
border: 1px solid #04fbfd;
color: #02f9ff !important;
background-color: #000000e7;
transition: all 0.3s ease-in-out;
border-radius: 8px;
}
}
}
}

View File

@ -0,0 +1,15 @@
import { Button } from "antd";
function SceneSwitch({ scene, setScene }) {
const switchHandler = () => {
setScene(scene === 1 ? 2 : 1);
};
return (
<Button className="scene-switch" type="primary" onClick={switchHandler}>
切换到场景{scene === 1 ? "二" : "一"}
</Button>
);
}
export default SceneSwitch;

View File

@ -0,0 +1,12 @@
import MapLayout from "@/components/map/Layout";
import styles from "./index.module.less";
function SceneTwo() {
return (
<div className={styles.sceneTwo}>
<MapLayout></MapLayout>
</div>
);
}
export default SceneTwo;

View File

@ -0,0 +1,3 @@
.sceneTwo :global {
height: 100%;
}

View File

@ -0,0 +1,19 @@
import { useState } from "react";
import TextInfoPanel from "@/components/common/TextInfoPanel";
import styles from "./index.module.less";
import SceneOne from "./SceneOne";
import SceneTwo from "./SceneTwo";
import SceneSwitch from "./SceneSwitch";
function DomainSix() {
const [scene, setScene] = useState(1);
return (
<div className={styles.domainSix}>
{scene === 1 ? <SceneOne /> : <SceneTwo />}
<SceneSwitch scene={scene} setScene={setScene} />
</div>
);
}
export default DomainSix;

View File

@ -0,0 +1,10 @@
.domainSix :global {
width: 100%;
height: 100%;
.scene-switch {
position: absolute;
left: 8px;
top: 8px;
}
}

View File

@ -16,7 +16,6 @@ import SiteLegend from "./SiteLegend";
import Labels from "./Labels"; import Labels from "./Labels";
export default function DomainTwo() { export default function DomainTwo() {
console.log("111 :>> ", 111);
return ( return (
<MapLayout> <MapLayout>
<div className="title">两极协同南极涛动有效调节青藏高原降水和加热</div> <div className="title">两极协同南极涛动有效调节青藏高原降水和加热</div>

View File

@ -25,7 +25,7 @@ function NavBar() {
/> />
<NavBarButton <NavBarButton
text={"过去千年气候重建数据同化"} text={"过去千年气候重建数据同化"}
onClick={() => navigateHandler(1)} onClick={() => navigateHandler("climateReconDataAssim")}
/> />
<NavBarButton <NavBarButton
text={"北极海冰预报"} text={"北极海冰预报"}

View File

@ -33,6 +33,7 @@
flex: 1; flex: 1;
text-align: center; text-align: center;
max-width: 200px; max-width: 200px;
height: 200px;
.btn-table { .btn-table {
width: 20px; width: 20px;
@ -108,7 +109,7 @@
.nav-bar-title { .nav-bar-title {
font-size: 30px; font-size: 30px;
font-weight: 600; font-weight: 600;
color: #04fbfd; color: #00b2b2;
padding: 30px 0; padding: 30px 0;
margin-left: -60px; margin-left: -60px;
} }