fix some needs
This commit is contained in:
parent
70421f0b9c
commit
2258496fd7
@ -1,4 +1,4 @@
|
||||
import { Button, Form, Input, InputNumber, Select } from "antd";
|
||||
import { Button, Form, InputNumber, Select } from "antd";
|
||||
|
||||
const layout = {
|
||||
labelCol: { span: 10 },
|
||||
@ -8,7 +8,7 @@ const tailLayout = {
|
||||
wrapperCol: { offset: 10, span: 14 },
|
||||
};
|
||||
|
||||
export default function FormPanel({ setShow }) {
|
||||
export default function FormPanel({ setShowResult }) {
|
||||
const [form] = Form.useForm();
|
||||
|
||||
return (
|
||||
@ -25,8 +25,7 @@ export default function FormPanel({ setShow }) {
|
||||
L: 5000,
|
||||
}}
|
||||
onFinish={(values) => {
|
||||
// 根据values生成charts
|
||||
// setShow(true);
|
||||
setShowResult(true);
|
||||
}}
|
||||
>
|
||||
<Form.Item
|
||||
|
@ -3,9 +3,9 @@ import { ImageryLayer } from "resium";
|
||||
import { WebMapServiceImageryProvider } from "cesium";
|
||||
|
||||
const url = "http://analysis.tpdc.ac.cn/gs/geoserver/phitrellis/wms";
|
||||
const name = "phitrellis:4_3_1_tas_Layer1";
|
||||
const name = "phitrellis:4_5_heatmap_htmp";
|
||||
|
||||
function LandImageLayer() {
|
||||
export default function ImageLayer({ yearRange }) {
|
||||
const tempProvider = useMemo(
|
||||
() =>
|
||||
new WebMapServiceImageryProvider({
|
||||
@ -19,14 +19,14 @@ function LandImageLayer() {
|
||||
}),
|
||||
[name, url]
|
||||
);
|
||||
|
||||
return null;
|
||||
return (
|
||||
<ImageryLayer
|
||||
key={`ImageryLayer-${name}`}
|
||||
imageryProvider={tempProvider}
|
||||
show={true}
|
||||
alpha={0.5}
|
||||
alpha={0.6}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export default LandImageLayer;
|
@ -0,0 +1,51 @@
|
||||
import { useCallback, useState } from "react";
|
||||
import { Radio, Spin } from "antd";
|
||||
import { Loading3QuartersOutlined, LoadingOutlined } from "@ant-design/icons";
|
||||
|
||||
let dataList = [];
|
||||
|
||||
for (let index = 10; index < 20; index++) {
|
||||
const text = `${index * 100 + 1} ~ ${(index + 1) * 100}`;
|
||||
dataList.push(text);
|
||||
}
|
||||
|
||||
export default function ResultPanel({ setYearRange }) {
|
||||
const [loading, setLoading] = useState(true);
|
||||
|
||||
const changeHandler = useCallback((e) => {
|
||||
setYearRange(e.target.value.split(" ~ "));
|
||||
});
|
||||
|
||||
setTimeout(() => {
|
||||
setLoading(false);
|
||||
}, Math.random() + 2000);
|
||||
|
||||
return (
|
||||
<div className="result-panel">
|
||||
<div className="panel-title">选择年份范围</div>
|
||||
{loading ? (
|
||||
<div className="loading">
|
||||
<Spin size="large" />
|
||||
</div>
|
||||
) : (
|
||||
<Radio.Group
|
||||
className="result-panel-radio"
|
||||
buttonStyle="solid"
|
||||
size="large"
|
||||
>
|
||||
{dataList.map((data, index) => {
|
||||
return (
|
||||
<Radio.Button
|
||||
key={`result-panel-item-${index}`}
|
||||
value={data}
|
||||
onChange={changeHandler}
|
||||
>
|
||||
{data}
|
||||
</Radio.Button>
|
||||
);
|
||||
})}
|
||||
</Radio.Group>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
@ -1,17 +1,41 @@
|
||||
import { useState } from "react";
|
||||
import MapLayout from "@/components/map/Layout";
|
||||
import TextInfoPanel from "@/components/common/TextInfoPanel";
|
||||
import FormPanel from "./FormPanel";
|
||||
import styles from "./index.module.less";
|
||||
import Legend from "./Legend";
|
||||
import ResultPanel from "./ResultPanel";
|
||||
import ImageLayer from "./ImageLayer";
|
||||
import styles from "./index.module.less";
|
||||
|
||||
function ClimateReconDataAssim() {
|
||||
const [showResult, setShowResult] = useState(false);
|
||||
const [yearRange, setYearRange] = useState([]);
|
||||
|
||||
return (
|
||||
<div className={styles.climateReconDataAssim}>
|
||||
<MapLayout>
|
||||
<div className="title">过去千年气候重建数据同化</div>
|
||||
<div className="formPanel">
|
||||
<FormPanel />
|
||||
<FormPanel setShowResult={setShowResult} />
|
||||
</div>
|
||||
{showResult && (
|
||||
<div
|
||||
className="formPanel"
|
||||
style={{
|
||||
top: "50%",
|
||||
bottom: 14,
|
||||
}}
|
||||
>
|
||||
<ResultPanel setYearRange={setYearRange} />
|
||||
</div>
|
||||
)}
|
||||
<div className="text-info-panel">
|
||||
<TextInfoPanel
|
||||
content={`基于自主研发的古气候数据同化系统,对过去千年气候模拟结果和气候代用资料进行最优融合,以此对过去千年北半球温度和降水进行网格化重建。通过该同化系统重建的气候要素既符合气候系统变化物理学规律和动力学机制、又包含代用资料记录的气候变化信息,同时具备时-空连续的优势。重建结果支持了对过去千年三极地区温度和降水的时空变化特征研究和过去千年北极放大效应机制的研究,研究成果在国内外已经产生了广泛的影响。`}
|
||||
/>
|
||||
</div>
|
||||
<Legend />
|
||||
<ImageLayer yearRange={yearRange} />
|
||||
</MapLayout>
|
||||
</div>
|
||||
);
|
||||
|
@ -5,6 +5,7 @@
|
||||
right: 12px;
|
||||
width: 450px;
|
||||
background-color: #000000e7;
|
||||
border-radius: 8px;
|
||||
|
||||
.form-panel {
|
||||
width: 100%;
|
||||
@ -43,6 +44,56 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.result-panel {
|
||||
height: 100%;
|
||||
border: 1px solid #04fbfd;
|
||||
border-radius: 8px;
|
||||
|
||||
.panel-title {
|
||||
height: 72px;
|
||||
color: white;
|
||||
font-weight: bold;
|
||||
font-size: 22px;
|
||||
padding-left: 12px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.loading {
|
||||
height: calc(100% - 72px);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
background-color: #0000004f;
|
||||
}
|
||||
|
||||
.result-panel-radio {
|
||||
height: calc(100% - 72px);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
gap: 12px;
|
||||
|
||||
.ant-radio-button-wrapper {
|
||||
width: 200px;
|
||||
border-radius: 8px;
|
||||
|
||||
&::before {
|
||||
width: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.text-info-panel {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
bottom: 12px;
|
||||
left: 12px;
|
||||
width: 450px;
|
||||
}
|
||||
}
|
||||
|
||||
.legend :global {
|
||||
|
@ -20,12 +20,12 @@ function CustomToolbar() {
|
||||
{
|
||||
label: "数据集成和共享",
|
||||
title: "数据集成和共享",
|
||||
value: "/map/",
|
||||
value: "http://casearthpoles.tpdc.ac.cn/zh-hans/",
|
||||
icon: <MenuUnfoldOutlined />,
|
||||
onClick: () => {
|
||||
navigate("/", { replace: true });
|
||||
window.open("http://casearthpoles.tpdc.ac.cn/zh-hans/", "_blank");
|
||||
},
|
||||
// key: "/ ",
|
||||
key: "http://casearthpoles.tpdc.ac.cn/zh-hans/",
|
||||
},
|
||||
{
|
||||
label: "随机森林方法在线计算案例",
|
||||
|
@ -1,9 +1,12 @@
|
||||
import { useEffect } from "react";
|
||||
import { useSelector } from "react-redux";
|
||||
import { Cartesian3, EasingFunction, Math } from "cesium";
|
||||
import { useCesium } from "resium";
|
||||
|
||||
function CustomFlyTo() {
|
||||
const { viewer } = useCesium();
|
||||
const { camera } = viewer;
|
||||
const { replayVersion } = useSelector((state) => state.data);
|
||||
|
||||
function cameraFlyToLine() {
|
||||
const step1 = {
|
||||
@ -65,6 +68,12 @@ function CustomFlyTo() {
|
||||
}
|
||||
cameraFlyToLine();
|
||||
|
||||
useEffect(() => {
|
||||
viewer.clock.shouldAnimate = false;
|
||||
viewer.clock.currentTime = viewer.clock.startTime.clone();
|
||||
cameraFlyToLine();
|
||||
}, [replayVersion]);
|
||||
|
||||
return <></>;
|
||||
}
|
||||
|
||||
|
@ -1,89 +0,0 @@
|
||||
import {
|
||||
CorridorGraphics,
|
||||
Entity,
|
||||
LabelGraphics,
|
||||
PolylineGraphics,
|
||||
useCesium,
|
||||
} from "resium";
|
||||
import {
|
||||
CallbackProperty,
|
||||
Cartesian2,
|
||||
Cartesian3,
|
||||
Color,
|
||||
ColorBlendMode,
|
||||
CornerType,
|
||||
LabelStyle,
|
||||
Material,
|
||||
PolylineArrowMaterialProperty,
|
||||
} from "cesium";
|
||||
import { Fragment, useCallback, useState } from "react";
|
||||
import { useInterval } from "ahooks";
|
||||
|
||||
function Labels() {
|
||||
const { viewer } = useCesium();
|
||||
|
||||
const [showOne, setShowOne] = useState(false);
|
||||
const [showTwo, setShowTwo] = useState(false);
|
||||
const [showThree, setShowThree] = useState(false);
|
||||
|
||||
const showAnimate = useCallback(() => {
|
||||
const { currentTime, stopTime } = viewer.clock;
|
||||
const leftTime = Math.floor(
|
||||
stopTime.secondsOfDay - currentTime.secondsOfDay
|
||||
);
|
||||
|
||||
if (leftTime < 20) {
|
||||
setShowOne(true);
|
||||
} else if (showOne) setShowOne(false);
|
||||
|
||||
if (leftTime < 15) {
|
||||
setShowTwo(true);
|
||||
} else if (showTwo) setShowTwo(false);
|
||||
|
||||
if (leftTime < 5) {
|
||||
setShowThree(true);
|
||||
} else if (showThree) setShowThree(false);
|
||||
}, [showOne, showTwo, showThree, viewer]);
|
||||
|
||||
useInterval(showAnimate, 300);
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<Entity show={showOne} position={Cartesian3.fromDegrees(-20, 55, 0)}>
|
||||
<LabelGraphics
|
||||
text={"北大西洋大气环流异常"}
|
||||
font="24px Helvetica"
|
||||
fillColor={Color.fromCssColorString("#04fbfd")}
|
||||
outlineColor={Color.BLACK}
|
||||
outlineWidth={2}
|
||||
style={LabelStyle.FILL_AND_OUTLINE}
|
||||
eyeOffset={new Cartesian2(0, 200000)}
|
||||
/>
|
||||
</Entity>
|
||||
<Entity show={showTwo} position={Cartesian3.fromDegrees(13, 50, 0)}>
|
||||
<LabelGraphics
|
||||
text={"欧洲地区大气环流异常"}
|
||||
font="24px Helvetica"
|
||||
fillColor={Color.fromCssColorString("#04fbfd")}
|
||||
outlineColor={Color.BLACK}
|
||||
outlineWidth={2}
|
||||
style={LabelStyle.FILL_AND_OUTLINE}
|
||||
eyeOffset={new Cartesian2(0, 200000)}
|
||||
/>
|
||||
</Entity>
|
||||
<Entity show={showThree} position={Cartesian3.fromDegrees(90, 27, 0)}>
|
||||
<LabelGraphics
|
||||
text={"青藏高原夏季出现年代际增温"}
|
||||
font="24px Helvetica"
|
||||
fillColor={Color.fromCssColorString("#04fbfd")}
|
||||
outlineColor={Color.BLACK}
|
||||
outlineWidth={2}
|
||||
style={LabelStyle.FILL_AND_OUTLINE}
|
||||
eyeOffset={new Cartesian2(0, 200000)}
|
||||
/>
|
||||
</Entity>
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
|
||||
export default Labels;
|
58
src/components/domain/One/Labels/LabelEtity.jsx
Normal file
58
src/components/domain/One/Labels/LabelEtity.jsx
Normal file
@ -0,0 +1,58 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { useSelector } from "react-redux";
|
||||
import { Entity, LabelGraphics, useCesium } from "resium";
|
||||
import { useInterval, useToggle } from "ahooks";
|
||||
import { Cartesian2, Color, LabelStyle } from "cesium";
|
||||
|
||||
export default function LabelEntity({ showTime, text, position }) {
|
||||
const { viewer } = useCesium();
|
||||
const { replayVersion } = useSelector((state) => state.data);
|
||||
const [deley, setDeley] = useState(300);
|
||||
const [show, setShow] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
setDeley(300);
|
||||
setShow(false);
|
||||
}, [replayVersion]);
|
||||
|
||||
const [font, { toggle: fontToggle }] = useToggle(
|
||||
"24px Helvetica",
|
||||
"bold 32px Helvetica"
|
||||
);
|
||||
const [fillColor, { toggle: colorToggle }] = useToggle(
|
||||
Color.fromCssColorString("#04fbfd").withAlpha(0.9),
|
||||
Color.fromCssColorString("#04fbfd")
|
||||
);
|
||||
|
||||
useInterval(() => {
|
||||
const { startTime, currentTime } = viewer.clock;
|
||||
const passtime = currentTime.secondsOfDay - startTime.secondsOfDay;
|
||||
|
||||
if (passtime >= showTime) {
|
||||
setShow(true);
|
||||
let timer = setInterval(() => {
|
||||
fontToggle();
|
||||
colorToggle();
|
||||
}, 500);
|
||||
|
||||
setTimeout(() => {
|
||||
clearInterval(timer);
|
||||
}, 3000);
|
||||
setDeley(undefined);
|
||||
}
|
||||
}, deley);
|
||||
|
||||
return (
|
||||
<Entity position={position} show={show}>
|
||||
<LabelGraphics
|
||||
text={text}
|
||||
font={font}
|
||||
fillColor={fillColor}
|
||||
outlineColor={Color.BLACK}
|
||||
outlineWidth={2}
|
||||
style={LabelStyle.FILL_AND_OUTLINE}
|
||||
eyeOffset={new Cartesian2(0, 200000)}
|
||||
/>
|
||||
</Entity>
|
||||
);
|
||||
}
|
30
src/components/domain/One/Labels/index.jsx
Normal file
30
src/components/domain/One/Labels/index.jsx
Normal file
@ -0,0 +1,30 @@
|
||||
import { Fragment } from "react";
|
||||
import { Cartesian3 } from "cesium";
|
||||
import LabelEntity from "./LabelEtity";
|
||||
|
||||
export default function Labels() {
|
||||
return (
|
||||
<Fragment>
|
||||
<LabelEntity
|
||||
showTime={1}
|
||||
text={"拉布拉多海海温上升"}
|
||||
position={Cartesian3.fromDegrees(-59, 60, 0)}
|
||||
/>
|
||||
<LabelEntity
|
||||
showTime={9}
|
||||
text={"北大西洋大气环流异常"}
|
||||
position={Cartesian3.fromDegrees(-20, 55, 0)}
|
||||
/>
|
||||
<LabelEntity
|
||||
showTime={13.5}
|
||||
text={"欧洲地区大气环流异常"}
|
||||
position={Cartesian3.fromDegrees(13, 50, 0)}
|
||||
/>
|
||||
<LabelEntity
|
||||
showTime={25}
|
||||
text={"青藏高原夏季出现年代际增温"}
|
||||
position={Cartesian3.fromDegrees(90, 27, 0)}
|
||||
/>
|
||||
</Fragment>
|
||||
);
|
||||
}
|
20
src/components/domain/One/ReplayButton.jsx
Normal file
20
src/components/domain/One/ReplayButton.jsx
Normal file
@ -0,0 +1,20 @@
|
||||
import { useCallback } from "react";
|
||||
import { useDispatch } from "react-redux";
|
||||
import { Button } from "antd";
|
||||
import styles from "./index.module.less";
|
||||
|
||||
export default function ReplayButton() {
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const playHandler = useCallback(() => {
|
||||
dispatch.data.update({ replayVersion: Date.now() });
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className={styles.replayButton}>
|
||||
<Button type="primary" onClick={playHandler}>
|
||||
播放
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
}
|
@ -4,11 +4,7 @@ import WavePoint from "@/components/common/WavePoint";
|
||||
export default function WavePoints() {
|
||||
return (
|
||||
<Fragment>
|
||||
<WavePoint
|
||||
stationLon={-59}
|
||||
stationLat={60}
|
||||
labelText={"拉布拉多海海温上升"}
|
||||
/>
|
||||
<WavePoint stationLon={-59} stationLat={60} />
|
||||
<WavePoint stationLon={88} stationLat={32.5} />
|
||||
</Fragment>
|
||||
);
|
||||
|
@ -13,6 +13,7 @@ import JJAImageLayer from "./JJAImageLayer";
|
||||
import CustomChartPanel from "./CustomChartPanel";
|
||||
import EntityLegend from "./EntityLegend";
|
||||
import Labels from "./Labels";
|
||||
import ReplayButton from "./ReplayButton";
|
||||
// import WaterVaporPath from "./WaterVaporPath";
|
||||
|
||||
export default function DomainOne() {
|
||||
@ -40,6 +41,7 @@ export default function DomainOne() {
|
||||
<Labels />
|
||||
<Legend />
|
||||
<JJAImageLayer />
|
||||
<ReplayButton />
|
||||
</MapLayout>
|
||||
);
|
||||
}
|
||||
|
@ -0,0 +1,5 @@
|
||||
.replayButton :global {
|
||||
position: absolute;
|
||||
top: 12px;
|
||||
left: 12px;
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
import { useMemo } from "react";
|
||||
import { ImageryLayer } from "resium";
|
||||
import { WebMapServiceImageryProvider } from "cesium";
|
||||
|
||||
const url = "http://analysis.tpdc.ac.cn/gs/geoserver/phitrellis/wms";
|
||||
const name = "phitrellis:4_3_t2m_era_1024";
|
||||
|
||||
function LandImageLayer() {
|
||||
const tempProvider = useMemo(
|
||||
() =>
|
||||
new WebMapServiceImageryProvider({
|
||||
url: url,
|
||||
layers: name,
|
||||
parameters: {
|
||||
service: "WMS",
|
||||
format: "image/png",
|
||||
transparent: true,
|
||||
},
|
||||
}),
|
||||
[name, url]
|
||||
);
|
||||
return (
|
||||
<ImageryLayer
|
||||
key={`ImageryLayer-${name}`}
|
||||
imageryProvider={tempProvider}
|
||||
show={true}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export default LandImageLayer;
|
@ -1,59 +0,0 @@
|
||||
import styles from "./index.module.less";
|
||||
|
||||
const colorBar = [
|
||||
"#7F20F0",
|
||||
"#2A09FA",
|
||||
"#1C33F1",
|
||||
"#3B6CE3",
|
||||
"#2388F8",
|
||||
"#0EA5FE",
|
||||
"#23C0FB",
|
||||
"#85CAF1",
|
||||
"#B8E1F3",
|
||||
"#FEF995",
|
||||
"#FEDD30",
|
||||
"#FEB709",
|
||||
"#FF8B00",
|
||||
"#FF5D00",
|
||||
"#FF1001",
|
||||
"#E00000",
|
||||
"#D62A2A",
|
||||
"#FFB1B1",
|
||||
];
|
||||
|
||||
function Legend({ style }) {
|
||||
return (
|
||||
<div className={styles.legend} style={{ ...style }}>
|
||||
<div className="legend-title"></div>
|
||||
<div className="colorbar">
|
||||
{colorBar.map((color, index) => {
|
||||
return (
|
||||
<div
|
||||
key={`colorbar-item-${index}`}
|
||||
className="colorbar-item"
|
||||
style={{ backgroundColor: color }}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</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;
|
@ -1,32 +0,0 @@
|
||||
import { useMemo } from "react";
|
||||
import { ImageryLayer } from "resium";
|
||||
import { WebMapServiceImageryProvider } from "cesium";
|
||||
|
||||
const url = "http://analysis.tpdc.ac.cn/gs/geoserver/phitrellis/wms";
|
||||
const name = "phitrellis:4_3_hadisst_1822";
|
||||
|
||||
function OceanImageLayer() {
|
||||
const tempProvider = useMemo(
|
||||
() =>
|
||||
new WebMapServiceImageryProvider({
|
||||
url: url,
|
||||
layers: name,
|
||||
parameters: {
|
||||
service: "WMS",
|
||||
format: "image/png",
|
||||
transparent: true,
|
||||
},
|
||||
}),
|
||||
[name, url]
|
||||
);
|
||||
return (
|
||||
<ImageryLayer
|
||||
key={`ImageryLayer-${name}`}
|
||||
imageryProvider={tempProvider}
|
||||
show={true}
|
||||
opacity={0.5}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export default OceanImageLayer;
|
@ -1,187 +0,0 @@
|
||||
import ChartPanel from "@/components/common/ChartPanel";
|
||||
|
||||
const years = [];
|
||||
|
||||
for (let year = 1900; year <= 2000; year++) {
|
||||
years.push(year);
|
||||
}
|
||||
|
||||
// 北极
|
||||
const AntarcticaData = [
|
||||
0.101942611, 0.121527548, 0.139042908, 0.153372484, 0.163348844, 0.16781324,
|
||||
0.165740405, 0.156668394, 0.140792524, 0.118786901, 0.091903343, 0.062313072,
|
||||
0.032977812, 0.00716395, -0.012074836, -0.022308346, -0.021755523,
|
||||
-0.00911355, 0.016196573, 0.053416993, 0.100564819, 0.155328769, 0.215351821,
|
||||
0.278252395, 0.341745714, 0.40383823, 0.463006888, 0.518309403, 0.569408932,
|
||||
0.616333481, 0.65915749, 0.697835067, 0.732192543, 0.761939745, 0.78659761,
|
||||
0.805314271, 0.81708585, 0.820876623, 0.815679973, 0.800851314, 0.776409401,
|
||||
0.742721875, 0.700509783, 0.651004076, 0.595858743, 0.536937172, 0.476075479,
|
||||
0.414725656, 0.353864772, 0.294239451, 0.236327526, 0.18015056, 0.125260938,
|
||||
0.070978964, 0.016363941, -0.039809019, -0.09861786, -0.160770418,
|
||||
-0.226238681, -0.294159838, -0.363174145, -0.431703208, -0.497831469,
|
||||
-0.559188985, -0.613384987, -0.658281488, -0.692634725, -0.716904761,
|
||||
-0.73222222, -0.739942379, -0.741611283, -0.73898482, -0.733815531,
|
||||
-0.727389051, -0.720449369, -0.713466528, -0.706847385, -0.700922099,
|
||||
-0.695911133, -0.691920829, -0.688978939, -0.687022002, -0.685739611,
|
||||
-0.684476492, -0.682376879, -0.678508387, -0.672015068, -0.662330127,
|
||||
-0.649157058, -0.632405431, -0.612100964, -0.588400678, -0.56151658,
|
||||
-0.531629308, -0.498751783, -0.462720586, -0.423305188, -0.380187818,
|
||||
-0.332990445, -0.281392986, -0.225240753,
|
||||
];
|
||||
|
||||
// 南极
|
||||
const ArcticData = [
|
||||
0.280477536, 0.259957371, 0.238217659, 0.215366218, 0.191558571, 0.167050728,
|
||||
0.142221385, 0.117514405, 0.093353739, 0.070136018, 0.048165337, 0.027449274,
|
||||
0.007551689, -0.012191879, -0.032557296, -0.054358257, -0.078483167,
|
||||
-0.105781444, -0.137208672, -0.174049223, -0.217858518, -0.26986764,
|
||||
-0.329886107, -0.395653113, -0.463819615, -0.530529991, -0.591308473,
|
||||
-0.641252419, -0.675396192, -0.689099366, -0.679883827, -0.649742172,
|
||||
-0.602149752, -0.540699996, -0.469155442, -0.39235518, -0.317187358,
|
||||
-0.251641431, -0.203124483, -0.175400473, -0.167133512, -0.174805821,
|
||||
-0.194600911, -0.222664488, -0.254875954, -0.286753396, -0.31384639,
|
||||
-0.331733387, -0.335992097, -0.322259345, -0.28761534, -0.234372353,
|
||||
-0.167389335, -0.091870697, -0.013026713, 0.063931601, 0.133955753,
|
||||
0.193415777, 0.241940543, 0.280019233, 0.308168154, 0.326938643, 0.337234614,
|
||||
0.34096367, 0.340608802, 0.338547054, 0.336593745, 0.335321866, 0.334127457,
|
||||
0.331817533, 0.327341923, 0.320216724, 0.310432332, 0.298228465, 0.284102612,
|
||||
0.268784935, 0.253114795, 0.237954629, 0.224151962, 0.212536008, 0.203736355,
|
||||
0.198010458, 0.195233614, 0.194960735, 0.196490857, 0.19901247, 0.201666439,
|
||||
0.203617401, 0.204129573, 0.202630823, 0.19873752, 0.192336315, 0.183625216,
|
||||
0.173000981, 0.16106866, 0.148653001, 0.136669759, 0.12600632, 0.117368896,
|
||||
0.111065474, 0.107060448,
|
||||
];
|
||||
|
||||
// 青藏高原
|
||||
const TibetanData = [
|
||||
-0.054774324, -0.072074468, -0.088166217, -0.102150868, -0.113128752,
|
||||
-0.12021764, -0.122708696, -0.12041877, -0.113696453, -0.103130771,
|
||||
-0.089455408, -0.073531475, -0.056259257, -0.03854918, -0.021352917,
|
||||
-0.005665395, 0.007550856, 0.01747264, 0.023473197, 0.025172256, 0.022567986,
|
||||
0.01612004, 0.006575074, -0.005110343, -0.017780686, -0.030203073,
|
||||
-0.041154273, -0.04937311, -0.053563998, -0.052516092, -0.045257867,
|
||||
-0.031279225, -0.010592879, 0.016344502, 0.048680379, 0.085233754,
|
||||
0.124518788, 0.164767706, 0.204092074, 0.240587798, 0.272353213, 0.297512938,
|
||||
0.314395917, 0.321976324, 0.320031404, 0.309041322, 0.289958303, 0.26397781,
|
||||
0.232447596, 0.196815201, 0.15858192, 0.119195224, 0.079906512, 0.041729979,
|
||||
0.005377081, -0.028807517, -0.060676589, -0.09016857, -0.11718843,
|
||||
-0.141549386, -0.163019079, -0.181382947, -0.196521195, -0.208451503,
|
||||
-0.21726015, -0.223065102, -0.226003897, -0.226234158, -0.223991288,
|
||||
-0.219766729, -0.214261928, -0.208224121, -0.202386774, -0.197405298,
|
||||
-0.193729514, -0.191661726, -0.191394367, -0.192960556, -0.196177765,
|
||||
-0.20070803, -0.206145455, -0.212083352, -0.218149914, -0.223985256,
|
||||
-0.229195822, -0.233329665, -0.235927137, -0.236550243, -0.234784989,
|
||||
-0.230241493, -0.222529731, -0.211284994, -0.196192431, -0.177010405,
|
||||
-0.153629275, -0.126243447, -0.095383816, -0.061763417, -0.026131148,
|
||||
0.010750252, 0.048064799,
|
||||
];
|
||||
|
||||
function CustomChartPanel() {
|
||||
const option = {
|
||||
title: {
|
||||
// text: "Stacked Line",
|
||||
},
|
||||
tooltip: {
|
||||
trigger: "axis",
|
||||
},
|
||||
legend: {
|
||||
data: ["南极", "北极", "青藏高原"],
|
||||
textStyle: { color: "#04fbfd", cursor: "point", fontSize: 20 },
|
||||
},
|
||||
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: -1,
|
||||
max: 1,
|
||||
interval: 0.5,
|
||||
splitNumber: 5,
|
||||
splitLine: { show: false },
|
||||
axisLine: {
|
||||
onZero: false,
|
||||
show: true,
|
||||
symbol: ["none", "arrow"],
|
||||
symbolOffset: [0, 10],
|
||||
lineStyle: {
|
||||
color: "#04fbfd",
|
||||
},
|
||||
},
|
||||
axisLabel: {
|
||||
show: true,
|
||||
},
|
||||
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 <ChartPanel option={option} />;
|
||||
}
|
||||
|
||||
export default CustomChartPanel;
|
@ -1,55 +0,0 @@
|
||||
import styles from "./index.module.less";
|
||||
|
||||
const colorBar = [
|
||||
"#801FEF",
|
||||
"#050CFB",
|
||||
"#3B6EE6",
|
||||
"#159AFF",
|
||||
"#36C1F8",
|
||||
"#AADBF2",
|
||||
"#FFF479",
|
||||
"#FFC113",
|
||||
"#FF7E00",
|
||||
"#FF7E00",
|
||||
"#CD0000",
|
||||
"#FFB1B1",
|
||||
];
|
||||
|
||||
function Legend() {
|
||||
return (
|
||||
<div className={styles.legend}>
|
||||
<div className="legend-title">全球温度异常空间分布</div>
|
||||
<div className="colorbar">
|
||||
{colorBar.map((color, index) => {
|
||||
return (
|
||||
<div
|
||||
key={`colorbar-item-${index}`}
|
||||
className="colorbar-item"
|
||||
style={{ backgroundColor: color }}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
<div className="legend-text">
|
||||
{["", -1, -0.8, -0.6, -0.4, -0.2, 0, 0.2, 0.4, 0.6, 0.8, 1.0, ""].map(
|
||||
(item, index) => {
|
||||
return (
|
||||
<div
|
||||
key={`legend-text-item-${index}`}
|
||||
className="legend-text-item"
|
||||
style={{
|
||||
textAlign:
|
||||
index === 6 ? "center" : index < 6 ? "left" : "right",
|
||||
}}
|
||||
>
|
||||
{item}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default Legend;
|
@ -1,31 +0,0 @@
|
||||
import { CameraFlyTo } from "resium";
|
||||
import { Cartesian3 } from "cesium";
|
||||
import MapLayout from "@/components/map/Layout";
|
||||
import CustomToolbar from "@/components/common/CustomToolbar";
|
||||
import CustomClock from "@/components/common/CustomClock";
|
||||
import ViewerImageLayer from "./ViewerImageLayer";
|
||||
import WavePoint from "@/components/common/WavePoint";
|
||||
|
||||
function ViewerOne({ children }) {
|
||||
return (
|
||||
<div className="domain-viewer">
|
||||
<MapLayout>
|
||||
<div className="title" style={{ zIndex: 999 }}>
|
||||
两极协同—连接南极和北极的热带大西洋经向模的媒介作用
|
||||
</div>
|
||||
<CustomToolbar />
|
||||
<CustomClock />
|
||||
<CameraFlyTo
|
||||
duration={5}
|
||||
destination={Cartesian3.fromDegrees(80, -85, 10000000)}
|
||||
/>
|
||||
|
||||
<WavePoint stationLon={88} stationLat={-85} labelText={"南极"} />
|
||||
<ViewerImageLayer />
|
||||
{children}
|
||||
</MapLayout>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default ViewerOne;
|
@ -1,23 +0,0 @@
|
||||
import { CameraFlyTo } from "resium";
|
||||
import { Cartesian3 } from "cesium";
|
||||
import MapLayout from "@/components/map/Layout";
|
||||
import WavePoint from "@/components/common/WavePoint";
|
||||
import ViewerImageLayer from "./ViewerImageLayer";
|
||||
|
||||
function ViewerThree({ children }) {
|
||||
return (
|
||||
<div className="domain-viewer">
|
||||
<MapLayout>
|
||||
<CameraFlyTo
|
||||
duration={5}
|
||||
destination={Cartesian3.fromDegrees(100, 33, 10000000)}
|
||||
/>
|
||||
<WavePoint stationLon={88} stationLat={33} labelText={"青藏高原"} />
|
||||
{children}
|
||||
<ViewerImageLayer />
|
||||
</MapLayout>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default ViewerThree;
|
@ -1,28 +0,0 @@
|
||||
import { CameraFlyTo } from "resium";
|
||||
import { Cartesian3 } from "cesium";
|
||||
import MapLayout from "@/components/map/Layout";
|
||||
import ViewerImageLayer from "./ViewerImageLayer";
|
||||
import WavePoint from "@/components/common/WavePoint";
|
||||
|
||||
function ViewerTwo({ children }) {
|
||||
return (
|
||||
<div className="domain-viewer">
|
||||
<MapLayout>
|
||||
<ViewerImageLayer />
|
||||
<CameraFlyTo
|
||||
duration={5}
|
||||
destination={Cartesian3.fromDegrees(0, 88, 10000000)}
|
||||
/>
|
||||
<WavePoint
|
||||
color={"WHITE"}
|
||||
stationLon={0}
|
||||
stationLat={87}
|
||||
labelText={"北极"}
|
||||
/>
|
||||
{children}
|
||||
</MapLayout>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default ViewerTwo;
|
@ -1,30 +0,0 @@
|
||||
import TextInfoPanel from "@/components/common/TextInfoPanel";
|
||||
import CustomChartPanel from "./CustomChartPanel";
|
||||
import Legend from "./Legend";
|
||||
import ViewerOne from "./ViewerOne";
|
||||
import ViewerTwo from "./ViewerTwo";
|
||||
import ViewerThree from "./ViewerThree";
|
||||
import styles from "./index.module.less";
|
||||
|
||||
function SceneOne() {
|
||||
return (
|
||||
<div className={styles.sceneOne}>
|
||||
<div className="domain-viewers">
|
||||
<ViewerOne />
|
||||
<ViewerTwo />
|
||||
<ViewerThree />
|
||||
</div>
|
||||
<div className="domain-info">
|
||||
<div className="left-panel">
|
||||
<TextInfoPanel content="利用GISTEMP资料,通过EEMD分解方法提取两极温度多年代际变化序列,发现南北极温度变化的跷跷板现象与大西洋多年代际振荡AMO紧密相关。而AMO与热带大西洋经向模AMM在年代际尺度上显著相关。ERA5再分析资料显示AMM可以通过Rossby波影响西南极的气温与海冰偶极子。因此,AMM可能在联系南北极气候变化的中起到了重要的媒介作用。" />
|
||||
</div>
|
||||
<div className="right-panel">
|
||||
<CustomChartPanel />
|
||||
</div>
|
||||
</div>
|
||||
<Legend />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default SceneOne;
|
@ -1,142 +0,0 @@
|
||||
.sceneOne :global {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: darkslategray;
|
||||
|
||||
.domain-viewers {
|
||||
width: 100%;
|
||||
flex: 1;
|
||||
display: flex;
|
||||
|
||||
.domain-viewer {
|
||||
flex: 1;
|
||||
position: relative;
|
||||
|
||||
.title {
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.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%;
|
||||
}
|
||||
|
||||
.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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.legend :global {
|
||||
position: absolute;
|
||||
bottom: calc(50% + 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;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,15 +0,0 @@
|
||||
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;
|
@ -1,9 +1,6 @@
|
||||
import MapLayout from "@/components/map/Layout";
|
||||
import Legend from "./Legend";
|
||||
import ViewerOne from "../SceneOne/ViewerOne";
|
||||
import CustomFlyTo from "./CustomFlyTo";
|
||||
import SSTImageLayer from "./SSTImageLayer";
|
||||
import TSImageLayer from "./TSImageLayer";
|
||||
import HGTImageLayer from "./HGTImageLayer";
|
||||
import Point from "./Point";
|
||||
import Circles from "./Circles";
|
||||
@ -25,8 +22,6 @@ function SceneTwo() {
|
||||
<CustomFlyTo />
|
||||
<Legend />
|
||||
<HGTImageLayer />
|
||||
{/* <SSTImageLayer /> */}
|
||||
{/* <TSImageLayer /> */}
|
||||
<Point />
|
||||
</MapLayout>
|
||||
</div>
|
||||
|
@ -1,11 +0,0 @@
|
||||
import { Fragment } from "react";
|
||||
import WavePoint from "@/components/common/WavePoint";
|
||||
|
||||
export default function WavePoints() {
|
||||
return (
|
||||
<Fragment>
|
||||
<WavePoint stationLon={88} stationLat={-85} />
|
||||
<WavePoint stationLon={88} stationLat={32.5} />
|
||||
</Fragment>
|
||||
);
|
||||
}
|
@ -1,17 +1,10 @@
|
||||
import { useState } from "react";
|
||||
import styles from "./index.module.less";
|
||||
import SceneOne from "./SceneOne";
|
||||
import SceneTwo from "./SceneTwo";
|
||||
import SceneSwitch from "./SceneSwitch";
|
||||
|
||||
export default function DomainThree() {
|
||||
const [scene, setScene] = useState(1);
|
||||
|
||||
return (
|
||||
<div className={styles.domainThree}>
|
||||
{/* {scene === 1 ? <SceneOne /> : <SceneTwo />} */}
|
||||
<SceneTwo />
|
||||
{/* <SceneSwitch scene={scene} setScene={setScene} /> */}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -1,8 +1,11 @@
|
||||
import { Cartesian3, EasingFunction } from "cesium";
|
||||
import { useEffect } from "react";
|
||||
import { useSelector } from "react-redux";
|
||||
import { useCesium } from "resium";
|
||||
|
||||
function CustomFlyTo() {
|
||||
const { viewer, camera } = useCesium();
|
||||
const { replayVersion } = useSelector((state) => state.data);
|
||||
|
||||
function cameraFlyToLine() {
|
||||
const area1Options = {
|
||||
@ -80,12 +83,28 @@ function CustomFlyTo() {
|
||||
duration: 3,
|
||||
complete: function () {
|
||||
setTimeout(() => {
|
||||
camera.flyTo(QTPlateauOption);
|
||||
camera.flyTo(HadleyCellOptions);
|
||||
}, 3000);
|
||||
},
|
||||
easingFunction: EasingFunction.LINEAR_NONE,
|
||||
};
|
||||
|
||||
const HadleyCellOptions = {
|
||||
destination: Cartesian3.fromDegrees(94, 1, 5000000),
|
||||
duration: 2,
|
||||
orientation: {
|
||||
heading: 6,
|
||||
pitch: -1.2,
|
||||
roll: -6.28,
|
||||
},
|
||||
complete: function () {
|
||||
setTimeout(() => {
|
||||
camera.flyTo(QTPlateauOption);
|
||||
}, 1000);
|
||||
},
|
||||
easingFunction: EasingFunction.LINEAR_NONE,
|
||||
};
|
||||
|
||||
const QTPlateauOption = {
|
||||
destination: Cartesian3.fromDegrees(92, 8, 5000000),
|
||||
duration: 2,
|
||||
@ -100,6 +119,13 @@ function CustomFlyTo() {
|
||||
camera.flyTo(area1Options);
|
||||
}
|
||||
cameraFlyToLine();
|
||||
|
||||
useEffect(() => {
|
||||
viewer.clock.shouldAnimate = false;
|
||||
viewer.clock.currentTime = viewer.clock.startTime.clone();
|
||||
cameraFlyToLine();
|
||||
}, [replayVersion]);
|
||||
|
||||
return <></>;
|
||||
}
|
||||
|
||||
|
@ -33,7 +33,7 @@ export default function HadleyCell() {
|
||||
<Entity show={show}>
|
||||
<PolylineGraphics
|
||||
positions={Cartesian3.fromDegreesArrayHeights([
|
||||
82, 14, 1000000, 82, 14, 300000, 82.3, 14.7, 200000, 87.7, 27.3,
|
||||
76, 9, 1000000, 76, 9, 300000, 76.6, 9.85, 200000, 87.4, 27.15,
|
||||
200000,
|
||||
])}
|
||||
width={50}
|
||||
@ -48,7 +48,7 @@ export default function HadleyCell() {
|
||||
<Entity show={show}>
|
||||
<PolylineGraphics
|
||||
positions={Cartesian3.fromDegreesArrayHeights([
|
||||
88, 28, 200000, 88, 28, 900000, 87.7, 27.3, 1000000, 82.3, 14.7,
|
||||
88, 28, 200000, 88, 28, 900000, 87.4, 27.15, 1000000, 76.6, 9.85,
|
||||
1000000,
|
||||
])}
|
||||
width={50}
|
||||
|
@ -1,70 +0,0 @@
|
||||
import { useInterval } from "ahooks";
|
||||
import { Cartesian2, Cartesian3, Color, LabelStyle } from "cesium";
|
||||
import { Fragment, useCallback, useState } from "react";
|
||||
import { Entity, LabelGraphics, useCesium } from "resium";
|
||||
|
||||
function Labels() {
|
||||
const { viewer } = useCesium();
|
||||
const [showIO, setShowIO] = useState(false);
|
||||
const [showTB, setShowTB] = useState(false);
|
||||
|
||||
const showAnimate = useCallback(() => {
|
||||
const { currentTime, stopTime } = viewer.clock;
|
||||
const leftTime = Math.floor(
|
||||
stopTime.secondsOfDay - currentTime.secondsOfDay
|
||||
);
|
||||
|
||||
if (leftTime < 5) {
|
||||
setShowIO(true);
|
||||
} else if (showIO) {
|
||||
setShowIO(false);
|
||||
}
|
||||
if (leftTime < 3) {
|
||||
setShowTB(true);
|
||||
} else if (showIO) {
|
||||
setShowTB(false);
|
||||
}
|
||||
}, [showIO]);
|
||||
|
||||
useInterval(showAnimate, 100);
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<Entity position={Cartesian3.fromDegrees(-110, -60, 0)}>
|
||||
<LabelGraphics
|
||||
text={"5月南极涛动"}
|
||||
font="24px Helvetica"
|
||||
fillColor={Color.fromCssColorString("#04fbfd")}
|
||||
outlineColor={Color.BLACK}
|
||||
outlineWidth={2}
|
||||
style={LabelStyle.FILL_AND_OUTLINE}
|
||||
eyeOffset={new Cartesian2(0, 200000)}
|
||||
/>
|
||||
</Entity>
|
||||
<Entity show={showIO} position={Cartesian3.fromDegrees(73, -7, 0)}>
|
||||
<LabelGraphics
|
||||
text={"印度洋海温异常"}
|
||||
font="24px Helvetica"
|
||||
fillColor={Color.fromCssColorString("#04fbfd")}
|
||||
outlineColor={Color.BLACK}
|
||||
outlineWidth={2}
|
||||
style={LabelStyle.FILL_AND_OUTLINE}
|
||||
eyeOffset={new Cartesian2(0, 200000)}
|
||||
/>
|
||||
</Entity>
|
||||
<Entity show={showTB} position={Cartesian3.fromDegrees(95, 28, 0)}>
|
||||
<LabelGraphics
|
||||
text={"高原上空降水增加、感热通量降低"}
|
||||
font="24px Helvetica"
|
||||
fillColor={Color.fromCssColorString("#04fbfd")}
|
||||
outlineColor={Color.BLACK}
|
||||
outlineWidth={2}
|
||||
style={LabelStyle.FILL_AND_OUTLINE}
|
||||
eyeOffset={new Cartesian2(0, 0)}
|
||||
/>
|
||||
</Entity>
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
|
||||
export default Labels;
|
58
src/components/domain/Two/Labels/LabelEtity.jsx
Normal file
58
src/components/domain/Two/Labels/LabelEtity.jsx
Normal file
@ -0,0 +1,58 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { useSelector } from "react-redux";
|
||||
import { Entity, LabelGraphics, useCesium } from "resium";
|
||||
import { useInterval, useToggle } from "ahooks";
|
||||
import { Cartesian2, Color, LabelStyle } from "cesium";
|
||||
|
||||
export default function LabelEntity({ showTime, text, position }) {
|
||||
const { viewer } = useCesium();
|
||||
const { replayVersion } = useSelector((state) => state.data);
|
||||
const [deley, setDeley] = useState(300);
|
||||
const [show, setShow] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
setDeley(300);
|
||||
setShow(false);
|
||||
}, [replayVersion]);
|
||||
|
||||
const [font, { toggle: fontToggle }] = useToggle(
|
||||
"24px Helvetica",
|
||||
"bold 32px Helvetica"
|
||||
);
|
||||
const [fillColor, { toggle: colorToggle }] = useToggle(
|
||||
Color.fromCssColorString("#04fbfd").withAlpha(0.9),
|
||||
Color.fromCssColorString("#04fbfd")
|
||||
);
|
||||
|
||||
useInterval(() => {
|
||||
const { startTime, currentTime } = viewer.clock;
|
||||
const passtime = currentTime.secondsOfDay - startTime.secondsOfDay;
|
||||
|
||||
if (passtime >= showTime) {
|
||||
setShow(true);
|
||||
let timer = setInterval(() => {
|
||||
fontToggle();
|
||||
colorToggle();
|
||||
}, 500);
|
||||
|
||||
setTimeout(() => {
|
||||
clearInterval(timer);
|
||||
}, 3000);
|
||||
setDeley(undefined);
|
||||
}
|
||||
}, deley);
|
||||
|
||||
return (
|
||||
<Entity position={position} show={show}>
|
||||
<LabelGraphics
|
||||
text={text}
|
||||
font={font}
|
||||
fillColor={fillColor}
|
||||
outlineColor={Color.BLACK}
|
||||
outlineWidth={2}
|
||||
style={LabelStyle.FILL_AND_OUTLINE}
|
||||
eyeOffset={new Cartesian2(0, 200000)}
|
||||
/>
|
||||
</Entity>
|
||||
);
|
||||
}
|
35
src/components/domain/Two/Labels/index.jsx
Normal file
35
src/components/domain/Two/Labels/index.jsx
Normal file
@ -0,0 +1,35 @@
|
||||
import { Fragment } from "react";
|
||||
import { Cartesian3 } from "cesium";
|
||||
import LabelEntity from "./LabelEtity";
|
||||
|
||||
export default function Labels() {
|
||||
return (
|
||||
<Fragment>
|
||||
<LabelEntity
|
||||
showTime={1}
|
||||
text={"5月南极涛动"}
|
||||
position={Cartesian3.fromDegrees(-110, -60, 0)}
|
||||
/>
|
||||
<LabelEntity
|
||||
showTime={9}
|
||||
text={"源自阿蒙森海的纬向波列异常"}
|
||||
position={Cartesian3.fromDegrees(11, -65, 0)}
|
||||
/>
|
||||
<LabelEntity
|
||||
showTime={22}
|
||||
text={"印度洋海温降低"}
|
||||
position={Cartesian3.fromDegrees(73, -7, 0)}
|
||||
/>
|
||||
<LabelEntity
|
||||
showTime={27}
|
||||
text={"局地环流异常"}
|
||||
position={Cartesian3.fromDegrees(84, 15, 0)}
|
||||
/>
|
||||
<LabelEntity
|
||||
showTime={30}
|
||||
text={"高原上空降水增加、感热通量降低"}
|
||||
position={Cartesian3.fromDegrees(95, 28, 0)}
|
||||
/>
|
||||
</Fragment>
|
||||
);
|
||||
}
|
20
src/components/domain/Two/ReplayButton.jsx
Normal file
20
src/components/domain/Two/ReplayButton.jsx
Normal file
@ -0,0 +1,20 @@
|
||||
import { useCallback } from "react";
|
||||
import { useDispatch } from "react-redux";
|
||||
import { Button } from "antd";
|
||||
import styles from "./index.module.less";
|
||||
|
||||
export default function ReplayButton() {
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const playHandler = useCallback(() => {
|
||||
dispatch.data.update({ replayVersion: Date.now() });
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className={styles.replayButton}>
|
||||
<Button type="primary" onClick={playHandler}>
|
||||
播放
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
}
|
@ -16,6 +16,7 @@ import SiteLegend from "./SiteLegend";
|
||||
import Labels from "./Labels";
|
||||
import TimeLinePanel from "./TimeLinePanel";
|
||||
import HadleyCell from "./HadleyCell";
|
||||
import ReplayButton from "./ReplayButton";
|
||||
|
||||
export default function DomainTwo() {
|
||||
return (
|
||||
@ -37,8 +38,9 @@ export default function DomainTwo() {
|
||||
<TextInfoPanel content="利用ERA5再分析数据集和CESM气候系统模式,发现5月南极涛动正位相在阿蒙森海激发的Rossby波列将造成印度洋海温降低,导致的局地环流异常会引起高原上空降水增加和感热通量降低。该成果从大气桥,海洋通道和陆气耦合的角度深刻揭示了第三极和南极间的紧密联系。" />
|
||||
</div>
|
||||
<WavePoints />
|
||||
<TimeLinePanel />
|
||||
{/* <TimeLinePanel /> */}
|
||||
<HadleyCell />
|
||||
<ReplayButton />
|
||||
{/* <SurfaceAnomaly /> */}
|
||||
</MapLayout>
|
||||
);
|
||||
|
@ -54,3 +54,9 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.replayButton :global {
|
||||
position: absolute;
|
||||
top: 12px;
|
||||
left: 12px;
|
||||
}
|
||||
|
@ -29,7 +29,11 @@ const itemsThree = [
|
||||
{
|
||||
key: "1",
|
||||
label: (
|
||||
<a target="_blank" rel="noopener noreferrer" href="http://project.lasg.ac.cn/FGOALS_f2-S2S/index.php?Var=Arctic-sea-ice">
|
||||
<a
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
href="http://project.lasg.ac.cn/FGOALS_f2-S2S/index.php?Var=Arctic-sea-ice"
|
||||
>
|
||||
北极海冰预报
|
||||
</a>
|
||||
),
|
||||
@ -37,7 +41,11 @@ const itemsThree = [
|
||||
{
|
||||
key: "2",
|
||||
label: (
|
||||
<a target="_blank" rel="noopener noreferrer" href="http://arcticroute.tpdc.ac.cn/">
|
||||
<a
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
href="http://arcticroute.tpdc.ac.cn/"
|
||||
>
|
||||
北极航线智能规划
|
||||
</a>
|
||||
),
|
||||
@ -95,14 +103,16 @@ const itemsFour = [
|
||||
];
|
||||
|
||||
function NavBar() {
|
||||
const navigateHandler = (type) => window.open(`/map/${type}`, "_blank");
|
||||
const navigateHandler = (url) => window.open(url, "_blank");
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<div className="nav-bar-first">
|
||||
<NavBarButton
|
||||
text={"数据集成和共享"}
|
||||
onClick={() => navigateHandler("http://casearthpoles.tpdc.ac.cn/zh-hans/")}
|
||||
onClick={() =>
|
||||
navigateHandler("http://casearthpoles.tpdc.ac.cn/zh-hans/")
|
||||
}
|
||||
/>
|
||||
<Dropdown
|
||||
menu={{ items: itemsTwo }}
|
||||
|
@ -7,7 +7,7 @@ function HeadingPitchRoll() {
|
||||
const heading = camera.heading;
|
||||
const pitch = camera.pitch;
|
||||
const roll = camera.roll;
|
||||
console.log("heading,pitch,roll :>> ", heading, pitch, roll);
|
||||
// console.log("heading,pitch,roll :>> ", heading, pitch, roll);
|
||||
});
|
||||
|
||||
return <></>;
|
||||
|
@ -1,5 +1,7 @@
|
||||
export const data = {
|
||||
state: {},
|
||||
state: {
|
||||
replayVersion: Date.now(),
|
||||
},
|
||||
reducers: {
|
||||
update(state, payload) {
|
||||
return { ...state, ...payload };
|
||||
|
Loading…
x
Reference in New Issue
Block a user