This commit is contained in:
Aifeilong 2023-10-20 19:19:42 +08:00
parent 894f2af5d0
commit 5f19682bab
35 changed files with 316 additions and 703 deletions

BIN
src/assets/Heatflux.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.9 KiB

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

BIN
src/assets/Rain.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 696 B

View File

@ -0,0 +1,18 @@
import ReactECharts from "echarts-for-react";
import classNames from "classnames";
import styles from "./index.module.less";
export default function ChartPanel({ option, className }) {
return (
<div className={classNames(styles.chartPanel, { className })}>
<ReactECharts
option={option}
lazyUpdate={true}
style={{
height: "100%",
width: "100%",
}}
/>
</div>
);
}

View File

@ -0,0 +1,11 @@
.chartPanel :global {
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

@ -1,4 +1,4 @@
import ReactECharts from "echarts-for-react"; import ChartPanel from "@/components/common/ChartPanel";
const years = []; const years = [];
@ -16,7 +16,7 @@ const predictedData = [
-0.34866039, 0.93110625, 0.19143088, 0.5760311, -0.34866039, 0.93110625, 0.19143088, 0.5760311,
]; ];
function ChartPanel() { function CustomChartPanel() {
const option = { const option = {
title: { title: {
// text: "Stacked Line", // text: "Stacked Line",
@ -26,7 +26,7 @@ function ChartPanel() {
}, },
legend: { legend: {
data: ["观测结果", "预测结果"], data: ["观测结果", "预测结果"],
textStyle: { color: "#04fbfd", cursor: "point" }, textStyle: { color: "#04fbfd", cursor: "point", fontSize: 20 },
}, },
animationDuration: years.length * 1000, animationDuration: years.length * 1000,
animationEasing: "cubicInOut", animationEasing: "cubicInOut",
@ -102,18 +102,7 @@ function ChartPanel() {
], ],
}; };
return ( return <ChartPanel option={option} />;
<div className="chart-info-panel">
<ReactECharts
option={option}
lazyUpdate={true}
style={{
height: "100%",
width: "100%",
}}
/>
</div>
);
} }
export default ChartPanel; export default CustomChartPanel;

View File

@ -4,7 +4,7 @@ import CustomClock from "@/components/common/CustomClock";
import TextInfoPanel from "@/components/common/TextInfoPanel"; import TextInfoPanel from "@/components/common/TextInfoPanel";
import CustomFlyTo from "./CustomFlyTo"; import CustomFlyTo from "./CustomFlyTo";
import FormPanel from "./FormPanel"; import FormPanel from "./FormPanel";
import ChartPanel from "./ChartPanel"; import CustomChartPanel from "./CustomChartPanel";
import RectangleLayer from "./RectangleLayer"; import RectangleLayer from "./RectangleLayer";
import { useState } from "react"; import { useState } from "react";
import Labels from "./Labels"; import Labels from "./Labels";
@ -28,7 +28,7 @@ XGBoos是基于梯度提升决策树方法的分类和回归模型。 LightGBM
<div className="top-panel"> <div className="top-panel">
<FormPanel setShow={setShow} /> <FormPanel setShow={setShow} />
</div> </div>
<div className="bottom-panel">{show && <ChartPanel />}</div> <div className="bottom-panel">{show && <CustomChartPanel />}</div>
</div> </div>
<Labels /> <Labels />
<RectangleLayer /> <RectangleLayer />

View File

@ -1,7 +1,6 @@
import ReactECharts from "echarts-for-react";
import cls from "classnames";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { useCesium } from "resium"; import { useCesium } from "resium";
import ChartPanel from "@/components/common/ChartPanel";
const years = []; const years = [];
@ -29,7 +28,7 @@ const laBrudata = [
0.9844907, 0.9088836, 0.7977505, 0.7049671, 0.644415, 0.6330437, 0.9844907, 0.9088836, 0.7977505, 0.7049671, 0.644415, 0.6330437,
]; ];
function ChartPanel() { function CustomChartPanel() {
const { viewer } = useCesium(); const { viewer } = useCesium();
const [isHighlight, setIsHighlight] = useState(false); const [isHighlight, setIsHighlight] = useState(false);
@ -53,7 +52,7 @@ function ChartPanel() {
}, },
legend: { legend: {
data: ["拉布拉多海夏季海温(异常值)", "高原夏季气温(异常值)"], data: ["拉布拉多海夏季海温(异常值)", "高原夏季气温(异常值)"],
textStyle: { color: "#04fbfd", cursor: "point" }, textStyle: { color: "#04fbfd", cursor: "point", fontSize: 20 },
}, },
animationDuration: years.length * 1000, animationDuration: years.length * 1000,
animationEasing: "cubicInOut", animationEasing: "cubicInOut",
@ -136,18 +135,7 @@ function ChartPanel() {
], ],
}; };
return ( return <ChartPanel option={option} />;
<div className={cls("chart-info-panel", { highlight: isHighlight })}>
<ReactECharts
option={option}
lazyUpdate={true}
style={{
height: "100%",
width: "100%",
}}
/>
</div>
);
} }
export default ChartPanel; export default CustomChartPanel;

View File

@ -1,14 +1,7 @@
import { Fragment, useCallback } from "react"; import { useCallback } from "react";
import { Entity, LabelGraphics, ModelGraphics, useCesium } from "resium"; import { Entity, ModelGraphics, useCesium } from "resium";
import arrowRound from "@/assets/arrow_round.glb"; import arrowRound from "@/assets/arrow_round.glb";
import { import { CallbackProperty, Cartesian3, Color, ColorBlendMode } from "cesium";
CallbackProperty,
Cartesian2,
Cartesian3,
Color,
ColorBlendMode,
LabelStyle,
} from "cesium";
let totalSeconds = 60; let totalSeconds = 60;
let numberOfSamples = 120; let numberOfSamples = 120;
@ -59,186 +52,95 @@ function Cyclone() {
const anticycloneColor = Color.fromCssColorString("#f70000"); const anticycloneColor = Color.fromCssColorString("#f70000");
const cycloneColor = Color.fromCssColorString("#00AC4D"); const cycloneColor = Color.fromCssColorString("#00AC4D");
const cycloneList = [
{
type: "anticyclone",
showTime: 5,
position: Cartesian3.fromDegrees(-62, 69, height),
},
{
type: "cyclone",
showTime: 7.5,
position: Cartesian3.fromDegrees(-45, 59, height),
},
{
type: "anticyclone",
showTime: 10,
position: Cartesian3.fromDegrees(-20, 55, height),
},
{
type: "cyclone",
showTime: 12.5,
position: Cartesian3.fromDegrees(5, 53, height),
},
{
type: "anticyclone",
showTime: 15,
position: Cartesian3.fromDegrees(29, 49, height),
},
{
type: "cyclone",
showTime: 17.5,
position: Cartesian3.fromDegrees(46, 46, height),
},
{
type: "anticyclone",
showTime: 20,
position: Cartesian3.fromDegrees(62, 45, height),
},
{
type: "cyclone",
showTime: 22.5,
position: Cartesian3.fromDegrees(81, 46.5, height),
},
{
type: "anticyclone",
showTime: 25,
position: Cartesian3.fromDegrees(98, 48, height),
},
{
type: "anticyclone",
showTime: 25,
position: Cartesian3.fromDegrees(98, 48, 0),
},
];
return cycloneList.map((cyclone, index) => {
const { type, showTime, position } = cyclone;
return ( return (
<Fragment>
<Entity <Entity
id={"Anticyclone-1"} key={`${type}-${index}`}
id={`${type}-${index}`}
position={ position={
new CallbackProperty(function (time, result) { new CallbackProperty(function (time, result) {
const passTime = getPassTime(); const passTime = getPassTime();
if (passTime < 5) return; if (passTime < showTime) return;
return Cartesian3.fromDegrees(-62, 69, height); return position;
}, true) }, true)
} }
> >
<ModelGraphics <ModelGraphics
uri={arrowRound} uri={arrowRound}
minimumPixelSize={128} minimumPixelSize={128}
// nodeTransformations={{ color={type === "anticyclone" ? anticycloneColor : cycloneColor}
//
// group_0: new Cesium.NodeTransformationProperty({
// rotation: rotationProperty,
// }),
// }}
color={anticycloneColor}
colorBlendMode={ColorBlendMode.REPLACE} colorBlendMode={ColorBlendMode.REPLACE}
/> />
</Entity> </Entity>
<Entity
id={"Anticyclone-add-1"}
position={
new CallbackProperty(function (time, result) {
const passTime = getPassTime();
if (passTime < 7.5) return;
return Cartesian3.fromDegrees(-45, 59, height);
}, true)
}
>
<ModelGraphics
uri={arrowRound}
minimumPixelSize={128}
color={anticycloneColor}
colorBlendMode={ColorBlendMode.REPLACE}
/>
</Entity>
<Entity
id={"Cyclone-1"}
position={
new CallbackProperty(function (time, result) {
const passTime = getPassTime();
if (passTime < 10) return;
return Cartesian3.fromDegrees(-20, 55, height);
}, true)
}
>
<ModelGraphics
uri={arrowRound}
minimumPixelSize={128}
color={cycloneColor}
colorBlendMode={ColorBlendMode.REPLACE}
/>
</Entity>
<Entity
id={"Cyclone-add-1"}
position={
new CallbackProperty(function (time, result) {
const passTime = getPassTime();
if (passTime < 12.5) return;
return Cartesian3.fromDegrees(5, 53, height);
}, true)
}
>
<ModelGraphics
uri={arrowRound}
minimumPixelSize={128}
color={cycloneColor}
colorBlendMode={ColorBlendMode.REPLACE}
/>
</Entity>
<Entity
id={"Anticyclone-2"}
position={
new CallbackProperty(function (time, result) {
const passTime = getPassTime();
if (passTime < 15) return;
return Cartesian3.fromDegrees(29, 49, height);
}, true)
}
>
<ModelGraphics
uri={arrowRound}
minimumPixelSize={128}
color={anticycloneColor}
colorBlendMode={ColorBlendMode.REPLACE}
/>
</Entity>
<Entity
id={"Anticyclone-add-2"}
position={
new CallbackProperty(function (time, result) {
const passTime = getPassTime();
if (passTime < 17.5) return;
return Cartesian3.fromDegrees(46, 46, height);
}, true)
}
>
<ModelGraphics
uri={arrowRound}
minimumPixelSize={128}
color={anticycloneColor}
colorBlendMode={ColorBlendMode.REPLACE}
/>
</Entity>
<Entity
id={"Cyclone-2"}
position={
new CallbackProperty(function (time, result) {
const passTime = getPassTime();
if (passTime < 20) return;
return Cartesian3.fromDegrees(62, 45, height);
}, true)
}
>
<ModelGraphics
uri={arrowRound}
minimumPixelSize={128}
color={cycloneColor}
colorBlendMode={ColorBlendMode.REPLACE}
/>
</Entity>
<Entity
id={"Cyclone-add-2"}
position={
new CallbackProperty(function (time, result) {
const passTime = getPassTime();
if (passTime < 22.5) return;
return Cartesian3.fromDegrees(81, 46.5, height);
}, true)
}
>
<ModelGraphics
uri={arrowRound}
minimumPixelSize={128}
color={cycloneColor}
colorBlendMode={ColorBlendMode.REPLACE}
/>
</Entity>
<Entity
id={"Anticyclone-3"}
position={
new CallbackProperty(function (time, result) {
const passTime = getPassTime();
if (passTime < 25) return;
return Cartesian3.fromDegrees(98, 48, height);
}, true)
}
>
<ModelGraphics
uri={arrowRound}
minimumPixelSize={128}
color={anticycloneColor}
colorBlendMode={ColorBlendMode.REPLACE}
/>
</Entity>
<Entity
id={"Anticyclone-4"}
position={
new CallbackProperty(function (time, result) {
const passTime = getPassTime();
if (passTime < 25) return;
return Cartesian3.fromDegrees(98, 48, 0);
}, true)
}
>
<ModelGraphics
uri={arrowRound}
minimumPixelSize={128}
color={anticycloneColor}
colorBlendMode={ColorBlendMode.REPLACE}
/>
</Entity>
</Fragment>
); );
});
// <ModelGraphics
// uri={arrowRound}
// minimumPixelSize={128}
// // nodeTransformations={{
// //
// // group_0: new Cesium.NodeTransformationProperty({
// // rotation: rotationProperty,
// // }),
// // }}
// color={anticycloneColor}
// colorBlendMode={ColorBlendMode.REPLACE}
// />
} }
export default Cyclone; export default Cyclone;

View File

@ -5,7 +5,7 @@ import { WebMapServiceImageryProvider } from "cesium";
const url = "http://analysis.tpdc.ac.cn/gs/geoserver/phitrellis/wms"; const url = "http://analysis.tpdc.ac.cn/gs/geoserver/phitrellis/wms";
const name1 = "phitrellis:4_1_sst_JJA_G_dif"; const name1 = "phitrellis:4_1_sst_JJA_G_dif";
const name2 = "phitrellis:4_1_t2m_JJA_TP_dif "; const name2 = "phitrellis:4_1_ts_tp_dif_mask";
function JJAImageLayer() { function JJAImageLayer() {
const tempProvider1 = useMemo( const tempProvider1 = useMemo(

View File

@ -35,7 +35,7 @@ function Labels() {
<Fragment> <Fragment>
<Entity position={Cartesian3.fromDegrees(-60, 65, 0)}> <Entity position={Cartesian3.fromDegrees(-60, 65, 0)}>
<LabelGraphics <LabelGraphics
text={"拉布拉多海海温偏暖"} text={"拉布拉多海海温上升"}
font="24px Helvetica" font="24px Helvetica"
fillColor={Color.fromCssColorString("#04fbfd")} fillColor={Color.fromCssColorString("#04fbfd")}
outlineColor={Color.BLACK} outlineColor={Color.BLACK}

View File

@ -10,7 +10,7 @@ import WavePoints from "./WavePoints";
import Updraft from "./Updraft"; import Updraft from "./Updraft";
import Legend from "./Legend"; import Legend from "./Legend";
import JJAImageLayer from "./JJAImageLayer"; import JJAImageLayer from "./JJAImageLayer";
import ChartPanel from "./ChartPanel"; import CustomChartPanel from "./CustomChartPanel";
import EntityLegend from "./EntityLegend"; import EntityLegend from "./EntityLegend";
import Labels from "./Labels"; import Labels from "./Labels";
// import WaterVaporPath from "./WaterVaporPath"; // import WaterVaporPath from "./WaterVaporPath";
@ -29,7 +29,7 @@ export default function DomainOne() {
<TextInfoPanel content="基于再分析资料JRA55和线性斜压模式LBM的试验结果在年代际尺度上拉布拉多海海温偏暖会引起北大西洋至欧洲地区大气环流异常导致青藏高原夏季出现年代际增温。" /> <TextInfoPanel content="基于再分析资料JRA55和线性斜压模式LBM的试验结果在年代际尺度上拉布拉多海海温偏暖会引起北大西洋至欧洲地区大气环流异常导致青藏高原夏季出现年代际增温。" />
</div> </div>
<div className="right-panel one"> <div className="right-panel one">
<ChartPanel /> <CustomChartPanel />
</div> </div>
<Cyclone /> <Cyclone />
<Barotropic /> <Barotropic />

View File

@ -1,4 +1,4 @@
import ReactECharts from "echarts-for-react"; import ChartPanel from "@/components/common/ChartPanel";
const years = []; const years = [];
@ -15,7 +15,7 @@ const ArcticData = [];
// //
const TibetanData = []; const TibetanData = [];
function ChartPanel() { function CustomChartPanel() {
const option = { const option = {
title: { title: {
// text: "Stacked Line", // text: "Stacked Line",
@ -25,7 +25,7 @@ function ChartPanel() {
}, },
legend: { legend: {
data: ["南极", "北极", "青藏高原"], data: ["南极", "北极", "青藏高原"],
textStyle: { color: "#04fbfd", cursor: "point" }, textStyle: { color: "#04fbfd", cursor: "point", fontSize: 20 },
}, },
animationDuration: 10 * 1000, animationDuration: 10 * 1000,
animationEasing: "cubicInOut", animationEasing: "cubicInOut",
@ -121,18 +121,7 @@ function ChartPanel() {
], ],
}; };
return ( return <ChartPanel option={option} />;
<div className="chart-info-panel">
<ReactECharts
option={option}
lazyUpdate={true}
style={{
height: "100%",
width: "100%",
}}
/>
</div>
);
} }
export default ChartPanel; export default CustomChartPanel;

View File

@ -2,7 +2,7 @@ import TextInfoPanel from "@/components/common/TextInfoPanel";
import ViewerOne from "./ViewerOne"; import ViewerOne from "./ViewerOne";
import ViewerThree from "./ViewerThree"; import ViewerThree from "./ViewerThree";
import ViewerTwo from "./ViewerTwo"; import ViewerTwo from "./ViewerTwo";
import ChartPanel from "./ChartPanel"; import CustomChartPanel from "./CustomChartPanel";
import styles from "./index.module.less"; import styles from "./index.module.less";
import Legend from "./Legend"; import Legend from "./Legend";
@ -23,7 +23,7 @@ function SceneOne() {
/> />
</div> </div>
<div className="right-panel"> <div className="right-panel">
<ChartPanel /> <CustomChartPanel />
</div> </div>
</div> </div>
</div> </div>

View File

@ -104,18 +104,6 @@
} }
} }
} }
.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

@ -1,4 +1,4 @@
import ReactECharts from "echarts-for-react"; import ChartPanel from "@/components/common/ChartPanel";
const years = []; const years = [];
@ -76,7 +76,7 @@ const TibetanData = [
0.010750252, 0.048064799, 0.010750252, 0.048064799,
]; ];
function ChartPanel() { function CustomChartPanel() {
const option = { const option = {
title: { title: {
// text: "Stacked Line", // text: "Stacked Line",
@ -86,7 +86,7 @@ function ChartPanel() {
}, },
legend: { legend: {
data: ["南极", "北极", "青藏高原"], data: ["南极", "北极", "青藏高原"],
textStyle: { color: "#04fbfd", cursor: "point" }, textStyle: { color: "#04fbfd", cursor: "point", fontSize: 20 },
}, },
animationDuration: 10 * 1000, animationDuration: 10 * 1000,
animationEasing: "cubicInOut", animationEasing: "cubicInOut",
@ -181,18 +181,7 @@ function ChartPanel() {
], ],
}; };
return ( return <ChartPanel option={option} />;
<div className="chart-info-panel">
<ReactECharts
option={option}
lazyUpdate={true}
style={{
height: "100%",
width: "100%",
}}
/>
</div>
);
} }
export default ChartPanel; export default CustomChartPanel;

View File

@ -1,5 +1,5 @@
import TextInfoPanel from "@/components/common/TextInfoPanel"; import TextInfoPanel from "@/components/common/TextInfoPanel";
import ChartPanel from "../ChartPanel"; import CustomChartPanel from "./CustomChartPanel";
import Legend from "./Legend"; import Legend from "./Legend";
import ViewerOne from "./ViewerOne"; import ViewerOne from "./ViewerOne";
import ViewerTwo from "./ViewerTwo"; import ViewerTwo from "./ViewerTwo";
@ -19,7 +19,7 @@ function SceneOne() {
<TextInfoPanel content="利用GISTEMP资料通过EEMD分解方法提取两极温度多年代际变化序列发现南北极温度变化的跷跷板现象与大西洋多年代际振荡AMO紧密相关。而AMO与热带大西洋经向模AMM在年代际尺度上显著相关。ERA5再分析资料显示AMM可以通过Rossby波影响西南极的气温与海冰偶极子。因此AMM可能在联系南北极气候变化的中起到了重要的媒介作用。" /> <TextInfoPanel content="利用GISTEMP资料通过EEMD分解方法提取两极温度多年代际变化序列发现南北极温度变化的跷跷板现象与大西洋多年代际振荡AMO紧密相关。而AMO与热带大西洋经向模AMM在年代际尺度上显著相关。ERA5再分析资料显示AMM可以通过Rossby波影响西南极的气温与海冰偶极子。因此AMM可能在联系南北极气候变化的中起到了重要的媒介作用。" />
</div> </div>
<div className="right-panel"> <div className="right-panel">
<ChartPanel /> <CustomChartPanel />
</div> </div>
</div> </div>
<Legend /> <Legend />

View File

@ -85,18 +85,6 @@
} }
} }
} }
.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

@ -1,4 +1,4 @@
import ReactECharts from "echarts-for-react"; import ChartPanel from "@/components/common/ChartPanel";
const years = []; const years = [];
@ -48,7 +48,7 @@ function SceneChartPanel() {
}, },
legend: { legend: {
data: ["南极半岛", "热带大西洋"], data: ["南极半岛", "热带大西洋"],
textStyle: { color: "#04fbfd", cursor: "point" }, textStyle: { color: "#04fbfd", cursor: "point", fontSize: 20 },
}, },
animationDuration: 10 * 1000, animationDuration: 10 * 1000,
animationEasing: "cubicInOut", animationEasing: "cubicInOut",
@ -122,18 +122,7 @@ function SceneChartPanel() {
], ],
}; };
return ( return <ChartPanel option={option} className={"scene-chart-panel"} />;
<div className="scene-chart-panel chart-info-panel">
<ReactECharts
option={option}
lazyUpdate={true}
style={{
height: "100%",
width: "100%",
}}
/>
</div>
);
} }
export default SceneChartPanel; export default SceneChartPanel;

View File

@ -12,18 +12,6 @@
.title { .title {
pointer-events: none; pointer-events: 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

@ -66,15 +66,12 @@ function CustomFlyTo() {
}; };
const area5Options = { const area5Options = {
destination: Cartesian3.fromDegrees(90, -60, 10000000), destination: Cartesian3.fromDegrees(95, -35, 10000000),
duration: 4, duration: 4,
orientation: {
heading: 6,
pitch: -1.3,
roll: -6,
},
complete: function () { complete: function () {
setTimeout(() => {
camera.flyTo(IndiaOceanOptions); camera.flyTo(IndiaOceanOptions);
}, 2000);
}, },
easingFunction: EasingFunction.LINEAR_NONE, easingFunction: EasingFunction.LINEAR_NONE,
}; };
@ -102,13 +99,9 @@ function CustomFlyTo() {
}; };
const xx = { const xx = {
destination: Cartesian3.fromDegrees(80, 0, 14000000), destination: Cartesian3.fromDegrees(95, -35, 10000000),
duration: 5, duration: 4,
// orientation: {
// heading: 6,
// pitch: -1.3,
// roll: -6,
// },
easingFunction: EasingFunction.LINEAR_NONE, easingFunction: EasingFunction.LINEAR_NONE,
}; };

View File

@ -15,7 +15,7 @@ function IndianOceanSST() {
stopTime.secondsOfDay - currentTime.secondsOfDay stopTime.secondsOfDay - currentTime.secondsOfDay
); );
if (leftTime <= 10) { if (leftTime <= 8) {
setShow(true); setShow(true);
} else if (show) setShow(false); } else if (show) setShow(false);
}, [show]); }, [show]);

View File

@ -16,9 +16,12 @@ function Labels() {
if (leftTime < 5) { if (leftTime < 5) {
setShowIO(true); setShowIO(true);
setShowTB(true);
} else if (showIO) { } else if (showIO) {
setShowIO(false); setShowIO(false);
}
if (leftTime < 4) {
setShowTB(true);
} else if (showIO) {
setShowTB(false); setShowTB(false);
} }
}, [showIO]); }, [showIO]);
@ -51,7 +54,7 @@ function Labels() {
</Entity> </Entity>
<Entity show={showTB} position={Cartesian3.fromDegrees(94, 24, 0)}> <Entity show={showTB} position={Cartesian3.fromDegrees(94, 24, 0)}>
<LabelGraphics <LabelGraphics
text={"6月青藏高原降水和加热"} text={"高原上空降水增加、感热通量降低"}
font="24px Helvetica" font="24px Helvetica"
fillColor={Color.fromCssColorString("#04fbfd")} fillColor={Color.fromCssColorString("#04fbfd")}
outlineColor={Color.BLACK} outlineColor={Color.BLACK}

View File

@ -20,7 +20,7 @@ const dataAntarcticaToQTP = [
{ longitude: 30, latitude: -40, height: 1000000, time: 12 }, { longitude: 30, latitude: -40, height: 1000000, time: 12 },
{ longitude: 65, latitude: -35, height: 1000000, time: 16 }, { longitude: 65, latitude: -35, height: 1000000, time: 16 },
{ longitude: 95, latitude: -30, height: 1000000, time: 20 }, { longitude: 95, latitude: -30, height: 1000000, time: 20 },
{ longitude: 95, latitude: -30, height: 0, time: 23 }, { longitude: 95, latitude: -30, height: 0, time: 25 },
]; ];
function Point() { function Point() {

View File

@ -1,99 +0,0 @@
import { Entity, EllipseGraphics } from "resium";
import { Cartesian3, Color } 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,
0.10036364, -0.1807746, -0.21565104, -0.28437, -0.16798478, -0.214204,
-0.049326606, -0.094635, -0.09530785, -0.3044696, -0.28540367, -0.032144096,
-0.20508154, -0.1721087, -0.12554182, -0.11001358, 0.002132158, 0.055833075,
-0.1926637, -0.313678, 0.45139277, -0.22535999, -0.24989001, -0.024313157,
-0.2859986, 0.019246876, -0.02536043, -0.46465757, -0.32723987, -0.1926801,
-0.28803313, 0.005735828, 0.055759758, 0.10569655, -0.14558661, -0.1924466,
-0.035115488, -0.48584095, -0.15169029, -0.0734382, -0.21065243, -0.1338741,
-0.5154115, -0.19396217, -0.10661117, -0.24887498, -0.36621347, -0.39322242,
-0.14620663, -0.1848758, -0.36631036, -0.07608904, -0.161032, 0.08955761,
-0.46289977, -0.19713691, -0.237024, -0.10819046, -0.10532822, -0.20728564,
-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({ 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 Color.fromCssColorString(colorBar[dataIndex])}
semiMinorAxis={30000.0}
semiMajorAxis={30000.0}
extrudedHeight={400000}
height={height}
/>
</Entity>
);
}
export default HeatFlux;

View File

@ -1,97 +0,0 @@
import { Entity, EllipseGraphics } from "resium";
import { Cartesian3, Color } 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,
0.21825098, 0.56309533, 0.15624292, 0.1915884, -0.08074772, -0.021623861,
-0.03270335, 0.011358996, -0.09346678, -0.07257225, 0.19685836, -0.004689489,
0.018297506, 0.089315325, 0.07057168, 0.13153072, 0.036938984, -0.17923261,
0.3985438, 0.171897, -0.113426015, 0.4553916, 0.1476996, 0.158635,
-0.041355144, 0.14970288, 0.19565174, 0.213287, 0.0603011, 0.35724494,
-0.13986075, 0.16652703, -0.016419323, -0.09197042, -0.04890049, 0.22730026,
0.4451923, 0.102407545, 0.28357506, 0.259764, 0.2361199, 0.32204336,
0.39939404, 0.4786999, 0.12142443, -0.1493137, 0.3154582, 0.39657483,
-0.08021964, 0.20489447, 0.26629895, -0.34400544, 0.29385626, 0.15458098,
0.016143948, 0.04906382, -0.043581244, 0.1752981, -0.18351379, 0.071934514,
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({ 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 Color.fromCssColorString(colorBar[dataIndex])}
semiMinorAxis={30000.0}
semiMajorAxis={30000.0}
extrudedHeight={200000}
/>
</Entity>
);
}
export default Rain;

View File

@ -65,7 +65,7 @@ function Rain({ position, index }) {
lat, lat,
length, length,
])} ])}
material={new PolylineArrowMaterialProperty(Color.SKYBLUE)} material={new PolylineArrowMaterialProperty(Color.BLUE)}
arcType={"NONE"} arcType={"NONE"}
width={10} width={10}
/> />

View File

@ -1,5 +1,5 @@
import rain from "@/assets/rain.png"; import rain from "@/assets/Rain.png";
import heatflux from "@/assets/heatflux.png"; import heatflux from "@/assets/Heatflux.png";
import styles from "./index.module.less"; import styles from "./index.module.less";
function SiteLegend() { function SiteLegend() {
@ -7,35 +7,35 @@ function SiteLegend() {
<div className={styles.siteLegend}> <div className={styles.siteLegend}>
<div className="site-legend-item"> <div className="site-legend-item">
<div> <div>
<img src={rain} alt="rain-increase" width={32} /> <img
src={rain}
alt="rain-increase"
width={32}
style={{ transform: "rotate(180deg)" }}
/>
</div> </div>
<div className="site-legend-item-name">降水异常增加</div> <div className="site-legend-item-name">降水异常增加</div>
</div> </div>
<div className="site-legend-item"> <div className="site-legend-item">
<div> <div>
<img <img src={rain} alt="rain-decrease" width={32} />
src={rain}
alt="rain-decrease"
width={32}
style={{ transform: "rotate(180deg)" }}
/>
</div> </div>
<div className="site-legend-item-name">降水异常降低</div> <div className="site-legend-item-name">降水异常降低</div>
</div> </div>
<div className="site-legend-item"> <div className="site-legend-item">
<div> <div>
<img src={heatflux} alt="heatflux-increase" width={32} /> <img
src={heatflux}
alt="heatflux-increase"
width={32}
style={{ transform: "rotate(180deg)" }}
/>
</div> </div>
<div className="site-legend-item-name">感热通量异常增加</div> <div className="site-legend-item-name">感热通量异常增加</div>
</div> </div>
<div className="site-legend-item"> <div className="site-legend-item">
<div> <div>
<img <img src={heatflux} alt="heatflux-decrease" width={32} />
src={heatflux}
alt="heatflux-decrease"
width={32}
style={{ transform: "rotate(180deg)" }}
/>
</div> </div>
<div className="site-legend-item-name">感热通量异常降低</div> <div className="site-legend-item-name">感热通量异常降低</div>
</div> </div>

View File

@ -35,7 +35,7 @@
.timeline-panel-item { .timeline-panel-item {
color: white; color: white;
padding: 4px 8px; padding: 4px 8px;
font-size: 18px; font-size: 20px;
span { span {
padding: 4px; padding: 4px;

View File

@ -1,69 +1,130 @@
import { Fragment, useCallback } from "react"; import { Fragment } from "react";
import { useNavigate } from "react-router-dom"; import { Dropdown } from "antd";
import NavBarButton from "./NavBarButton"; import NavBarButton from "./NavBarButton";
import styles from "./index.module.less";
const itemsTwo = [
{
key: "1",
label: (
<a target="_blank" rel="noopener noreferrer" href="/#">
随机森林方法在线计算案例
</a>
),
},
{
key: "2",
label: (
<a
target="_blank"
rel="noopener noreferrer"
href="/map/climateReconDataAssim"
>
过去千年气候重建数据同化
</a>
),
},
];
const itemsThree = [
{
key: "1",
label: (
<a target="_blank" rel="noopener noreferrer" href="/#">
北极海冰预报
</a>
),
},
{
key: "2",
label: (
<a target="_blank" rel="noopener noreferrer" href="/#">
北极航线智能规划
</a>
),
},
];
const itemsFour = [
{
key: "1",
label: (
<a target="_blank" rel="noopener noreferrer" href="/map/1">
两极协同拉布拉多海海温偏暖控制夏季高原年代际增温
</a>
),
},
{
key: "2",
label: (
<a target="_blank" rel="noopener noreferrer" href="/map/2">
两极协同南极涛动有效调节青藏高原降水和加热
</a>
),
},
{
key: "3",
label: (
<a target="_blank" rel="noopener noreferrer" href="/map/3">
两极协同连接南极和北极的热带大西洋经向模的媒介作用
</a>
),
},
{
key: "4",
label: (
<a target="_blank" rel="noopener noreferrer" href="/map/4">
三极联动影响青藏高原上层温度
</a>
),
},
{
key: "5",
label: (
<a target="_blank" rel="noopener noreferrer" href="/map/5">
三极联动影响东亚夏季风
</a>
),
},
{
key: "6",
label: (
<a target="_blank" rel="noopener noreferrer" href="/map/6">
三极冰盖/冰川表面冰雪冻融对比关联与科学认知
</a>
),
},
];
function NavBar() { function NavBar() {
const navigate = useNavigate(); const navigateHandler = (type) => window.open(`/map/${type}`, "_blank");
const navigateHandler = useCallback(
(type) => {
navigate(`/map/${type}`, { replace: true });
},
[navigate]
);
return ( return (
<Fragment> <Fragment>
<div className="nav-bar-first"> <div className="nav-bar-first">
<NavBarButton <NavBarButton
text={"数据集成和共享"} text={"数据集成和共享"}
onClick={() => navigateHandler(1)} onClick={() => navigateHandler("")}
/> />
<NavBarButton <Dropdown
text={"随机森林方法在线计算案例"} menu={{ items: itemsTwo }}
onClick={() => navigateHandler(1)} trigger={["click"]}
/> overlayClassName={styles.navDropdown}
<NavBarButton >
text={"过去千年气候重建数据同化"} <NavBarButton text={"方法库集成与在线计算"} />
onClick={() => navigateHandler("climateReconDataAssim")} </Dropdown>
/> <Dropdown
<NavBarButton menu={{ items: itemsThree }}
text={"北极海冰预报"} trigger={["click"]}
onClick={() => navigateHandler(1)} overlayClassName={styles.navDropdown}
/> >
<NavBarButton <NavBarButton text={"在线决策支持服务"} />
text={"北极航线智能规划"} </Dropdown>
onClick={() => navigateHandler(1)} <Dropdown
/> menu={{ items: itemsFour }}
</div> trigger={["click"]}
<div className="nav-bar-second"> overlayClassName={styles.navDropdown}
<div className="nav-bar-title">三极联动</div> >
<div className="nav-bar-container"> <NavBarButton text={"三极联动"} />
<NavBarButton </Dropdown>
text={"两极协同—拉布拉多海海温偏暖控制夏季高原年代际增温"}
onClick={() => navigateHandler(1)}
/>
<NavBarButton
text={"两极协同—南极涛动有效调节青藏高原降水和加热"}
onClick={() => navigateHandler(2)}
/>
<NavBarButton
text={"两极协同—连接南极和北极的热带大西洋经向模的媒介作用"}
onClick={() => navigateHandler(3)}
/>
<NavBarButton
text={"三极联动影响青藏高原上层温度"}
onClick={() => navigateHandler(4)}
/>
<NavBarButton
text={"三极联动影响东亚夏季风"}
onClick={() => navigateHandler(5)}
/>
<NavBarButton
text={"三极冰盖/冰川表面冰雪冻融对比关联与科学认知"}
onClick={() => navigateHandler(6)}
/>
</div>
</div> </div>
</Fragment> </Fragment>
); );

View File

@ -20,7 +20,7 @@
.nav-bar-first { .nav-bar-first {
width: 100%; width: 100%;
max-width: 1200px; max-width: 1200px;
margin: 100px auto 0; margin: 250px auto 0;
color: #fff; color: #fff;
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
@ -30,10 +30,7 @@
cursor: pointer; cursor: pointer;
@btn-table-color: #04fbfd; @btn-table-color: #04fbfd;
transition: all 0.3s ease; transition: all 0.3s ease;
flex: 1;
text-align: center; text-align: center;
max-width: 200px;
height: 200px;
.btn-table { .btn-table {
width: 20px; width: 20px;
@ -68,102 +65,9 @@
} }
.nav-bar-content { .nav-bar-content {
padding: 20px; padding: 32px 20px;
font-size: 20px; font-size: 32px;
color: @btn-table-color;
background-color: #081633;
height: 100%;
display: flex;
justify-content: space-evenly;
align-items: center;
gap: 8px;
.anticon {
font-size: 40px;
}
.nav-bar-content-text {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
}
&:hover {
transform: translate(0, -4px);
.nav-bar-content {
background-color: #112f6a;
}
}
}
}
.nav-bar-second {
width: 100%;
max-width: 1200px;
margin: 0px auto;
color: #fff;
.nav-bar-title {
font-size: 30px;
font-weight: 600; font-weight: 600;
color: #00b2b2;
padding: 30px 0;
margin-left: -60px;
}
.nav-bar-container {
display: grid;
grid-template-columns: 350px auto 350px;
justify-content: space-between;
gap: 32px 0;
}
.nav-bar-button {
position: relative;
cursor: pointer;
@btn-table-color: #04fbfd;
transition: all 0.3s ease;
text-align: center;
max-width: 350px;
.btn-table {
width: 20px;
height: 10px;
position: absolute;
background-color: transparent;
&.left-top {
left: 0;
top: 0;
border-left: 1px solid @btn-table-color;
border-top: 1px solid @btn-table-color;
}
&.left-bottom {
left: 0;
bottom: 0;
border-left: 1px solid @btn-table-color;
border-bottom: 1px solid @btn-table-color;
}
&.right-top {
right: 0;
top: 0;
border-right: 1px solid @btn-table-color;
border-top: 1px solid @btn-table-color;
}
&.right-bottom {
right: 0;
bottom: 0;
border-right: 1px solid @btn-table-color;
border-bottom: 1px solid @btn-table-color;
}
}
.nav-bar-content {
padding: 20px;
font-size: 20px;
color: @btn-table-color; color: @btn-table-color;
background-color: #081633; background-color: #081633;
height: 100%; height: 100%;
@ -185,7 +89,7 @@
} }
&:hover { &:hover {
transform: translate(0, -4px); // transform: translate(0, -4px);
.nav-bar-content { .nav-bar-content {
background-color: #112f6a; background-color: #112f6a;
@ -194,3 +98,24 @@
} }
} }
} }
.navDropdown :global {
.ant-dropdown-menu-root {
background-color: #081633;
.ant-dropdown-menu-item {
padding: 18px;
&:hover {
color: #04fbfd;
background-color: #105185;
}
}
}
.ant-dropdown-menu-item {
color: #00b2b2;
font-size: 24px;
font-weight: 600;
}
}

View File

@ -101,18 +101,6 @@
} }
} }
.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;
}
.highlight { .highlight {
outline: 4px solid #04fbfd; outline: 4px solid #04fbfd;
box-shadow: 0 0 30px #04e0fd; box-shadow: 0 0 30px #04e0fd;