This commit is contained in:
Aifeilong 2023-10-25 18:48:54 +08:00
parent d307f3cad4
commit b0b7083817
25 changed files with 204 additions and 89 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

BIN
src/assets/cyclone.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

View File

@ -7,7 +7,7 @@ export default function ChartPanel({ option, className }) {
<div className={classNames(styles.chartPanel, { className })}>
<ReactECharts
option={option}
lazyUpdate={true}
// lazyUpdate={true}
style={{
height: "100%",
width: "100%",

View File

@ -14,10 +14,7 @@ function CustomClock() {
startTime={start.clone()}
stopTime={stop.clone()}
currentTime={start.clone()}
clockRange={ClockRange.LOOP_STOP}
// onTick={(clock) => {
// if (!clock.shouldAnimate) return;
// }}
clockRange={ClockRange.CLAMPED}
/>
);
}

View File

@ -134,7 +134,7 @@ function WavePoint({
outlineWidth={2}
style={LabelStyle.FILL_AND_OUTLINE}
eyeOffset={new Cartesian2(0, 200000)}
/>{" "}
/>
</Entity>
)}
</Fragment>

View File

@ -25,7 +25,8 @@ function Barotropic() {
<Entity
show={show}
name="Barotropic"
position={Cartesian3.fromDegrees(98, 48, 0)}
position={Cartesian3.fromDegrees(95, 36, 0)}
// position={Cartesian3.fromDegrees(98, 48, 0)}
>
<EllipseGraphics
material={new Color(0.73, 0.94, 0.95, 0.4)}

View File

@ -1,3 +1,4 @@
import { useState } from "react";
import ChartPanel from "@/components/common/ChartPanel";
const years = [];
@ -27,6 +28,8 @@ const laBrudata = [
];
function CustomChartPanel() {
const [plateauColor, setPlateauColor] = useState("#00a1ff");
const option = {
title: {
// text: "Stacked Line",
@ -38,8 +41,6 @@ function CustomChartPanel() {
data: ["拉布拉多海夏季海温(异常值)", "高原夏季气温(异常值)"],
textStyle: { color: "#04fbfd", cursor: "point", fontSize: 20 },
},
// animationDuration: years.length * 1000,
// animationEasing: "cubicInOut",
grid: {
left: "3%",
right: "4%",
@ -109,10 +110,9 @@ function CustomChartPanel() {
// stack: "Total",
data: plateauData,
smooth: false,
color: "#00a1ff",
symbol: "none",
itemStyle: {
color: "#00a1ff",
color: plateauColor,
},
lineStyle: {
type: "dashed",

View File

@ -39,13 +39,20 @@ function CustomFlyTo() {
//
const sideViewOptions = {
destination: Cartesian3.fromDegrees(-50, 46, 2200000),
destination: Cartesian3.fromDegrees(-50, 42, 2200000),
duration: 5,
orientation: {
heading: Math.toRadians(-15.0),
pitch: -Math.PI_OVER_FOUR,
roll: 0.0,
},
// destination: Cartesian3.fromDegrees(-50, 46, 2200000),
// duration: 5,
// orientation: {
// heading: Math.toRadians(-15.0),
// pitch: -Math.PI_OVER_FOUR,
// roll: 0.0,
// },
complete: () => {
viewer.clock.shouldAnimate = true;
setTimeout(function () {

View File

@ -1,6 +1,7 @@
import { useCallback } from "react";
import { Entity, ModelGraphics, useCesium } from "resium";
import arrowRound from "@/assets/arrow_round.glb";
import arrowRoundReverse from "@/assets/arrow_round_reverse.glb";
import { CallbackProperty, Cartesian3, Color, ColorBlendMode } from "cesium";
let totalSeconds = 60;
@ -50,28 +51,28 @@ function Cyclone() {
}, [viewer]);
const anticycloneColor = Color.fromCssColorString("#f70000");
const cycloneColor = Color.fromCssColorString("#00AC4D");
const cycloneColor = Color.fromCssColorString("#0000ff");
const cycloneList = [
{
type: "anticyclone",
showTime: 5,
position: Cartesian3.fromDegrees(-62, 69, height),
position: Cartesian3.fromDegrees(-59, 60, height),
},
{
type: "cyclone",
showTime: 7.5,
position: Cartesian3.fromDegrees(-45, 59, height),
position: Cartesian3.fromDegrees(-38, 55, height),
},
{
type: "anticyclone",
showTime: 10,
position: Cartesian3.fromDegrees(-20, 55, height),
position: Cartesian3.fromDegrees(-20, 50, height),
},
{
type: "cyclone",
showTime: 12.5,
position: Cartesian3.fromDegrees(5, 53, height),
position: Cartesian3.fromDegrees(5.5, 49, height),
},
{
type: "anticyclone",
@ -81,7 +82,7 @@ function Cyclone() {
{
type: "cyclone",
showTime: 17.5,
position: Cartesian3.fromDegrees(46, 46, height),
position: Cartesian3.fromDegrees(46, 47, height),
},
{
type: "anticyclone",
@ -91,22 +92,26 @@ function Cyclone() {
{
type: "cyclone",
showTime: 22.5,
position: Cartesian3.fromDegrees(81, 46.5, height),
position: Cartesian3.fromDegrees(77.5, 42.5, height),
},
{
type: "anticyclone",
showTime: 25,
position: Cartesian3.fromDegrees(98, 48, height),
position: Cartesian3.fromDegrees(95, 36, height),
},
{
type: "anticyclone",
showTime: 25,
position: Cartesian3.fromDegrees(98, 48, 0),
position: Cartesian3.fromDegrees(95, 36, 0),
},
];
return cycloneList.map((cyclone, index) => {
const { type, showTime, position } = cyclone;
const arrow = type === "anticyclone" ? arrowRound : arrowRoundReverse;
const color = type === "anticyclone" ? anticycloneColor : cycloneColor;
const minimumPixelSize = type === "anticyclone" ? 128 : 98;
return (
<Entity
key={`${type}-${index}`}
@ -120,9 +125,9 @@ function Cyclone() {
}
>
<ModelGraphics
uri={arrowRound}
minimumPixelSize={128}
color={type === "anticyclone" ? anticycloneColor : cycloneColor}
uri={arrow}
minimumPixelSize={minimumPixelSize}
color={color}
colorBlendMode={ColorBlendMode.REPLACE}
/>
</Entity>

View File

@ -1,6 +1,6 @@
import cyclone from "@/assets/cyclone.png";
import cyclone from "@/assets/cyclone.jpg";
import anticyclone from "@/assets/anticyclone.png";
import updraft from "@/assets/updraft.png";
import updraft from "@/assets/Heatflux.png";
import waterwapor from "@/assets/waterwapor.png";
function EntityLegend() {
@ -11,13 +11,13 @@ function EntityLegend() {
<div className="entity-legend-item-name">Rossby wave path</div>
</div>
<div className="entity-legend-item">
<div>
<div style={{ transform: "rotate(120deg)" }}>
<img src={anticyclone} width={32} />
</div>
<div className="entity-legend-item-name">anticyclone</div>
</div>
<div className="entity-legend-item">
<div>
<div style={{ transform: "rotate(180deg)" }}>
<img src={updraft} width={32} height={32} />
</div>
<div className="entity-legend-item-name">updraft</div>
@ -29,7 +29,7 @@ function EntityLegend() {
<div className="entity-legend-item-name">barotroptic structure</div>
</div>
<div className="entity-legend-item">
<div>
<div style={{ transform: "rotate(45deg)" }}>
<img src={cyclone} width={32} />
</div>
<div className="entity-legend-item-name">cyclone</div>

View File

@ -1,5 +1,21 @@
import { Entity, LabelGraphics, useCesium } from "resium";
import { Cartesian2, Cartesian3, Color, LabelStyle } from "cesium";
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";
@ -33,17 +49,6 @@ function Labels() {
return (
<Fragment>
<Entity position={Cartesian3.fromDegrees(-60, 65, 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={showOne} position={Cartesian3.fromDegrees(-20, 55, 0)}>
<LabelGraphics
text={"北大西洋大气环流异常"}
@ -55,7 +60,7 @@ function Labels() {
eyeOffset={new Cartesian2(0, 200000)}
/>
</Entity>
<Entity show={showTwo} position={Cartesian3.fromDegrees(31, 48, 0)}>
<Entity show={showTwo} position={Cartesian3.fromDegrees(13, 50, 0)}>
<LabelGraphics
text={"欧洲地区大气环流异常"}
font="24px Helvetica"

View File

@ -15,11 +15,19 @@ import {
//
const dataLabToQTP = [
{ longitude: -62, latitude: 69, height: 1000000, time: 5 },
{ longitude: -20, latitude: 55, height: 1000000, time: 10 },
// { longitude: -59, latitude: 60, height: 1000000, time: 5 },
// { longitude: -25, latitude: 46, height: 1000000, time: 10 },
// { longitude: 0, latitude: 42, height: 1000000, time: 15 },
// // { longitude: 30, latitude: 45, height: 1000000, time: 17 },
// { longitude: 47, latitude: 38, height: 1000000, time: 20 },
// { longitude: 95, latitude: 36, height: 1000000, time: 25 },
{ longitude: -59, latitude: 60, height: 1000000, time: 5 },
{ longitude: -38, latitude: 55, height: 1000000, time: 7.5 },
{ longitude: -20, latitude: 50, height: 1000000, time: 10 },
{ longitude: 29, latitude: 49, height: 1000000, time: 15 },
{ longitude: 62, latitude: 45, height: 1000000, time: 20 },
{ longitude: 98, latitude: 48, height: 1000000, time: 25 },
{ longitude: 77.5, latitude: 42.5, height: 1000000, time: 22.5 },
{ longitude: 95, latitude: 36, height: 1000000, time: 25 },
];
function Point() {
@ -56,7 +64,7 @@ function Point() {
property.addSample(time, position);
}
property.setInterpolationOptions({
interpolationDegree: 10,
interpolationDegree: 2,
interpolationAlgorithm: LagrangePolynomialApproximation,
});

View File

@ -12,10 +12,7 @@ function Updraft() {
const { viewer } = useCesium();
return (
<Entity
id={"Updraft"}
position={Cartesian3.fromDegrees(-34.0707383, 60.7117244, 100)}
>
<Entity id={"Updraft"} position={Cartesian3.fromDegrees(-59, 60, 100)}>
<PolylineGraphics
positions={
new CallbackProperty(function (time, result) {
@ -23,7 +20,7 @@ function Updraft() {
const passTime = currentTime.secondsOfDay - startTime.secondsOfDay;
const height = 200000 * passTime;
return Cartesian3.fromDegreesArrayHeights(
[-62, 69, 0, -62, 69, min([height, 1000000])],
[-59, 60, 0, -59, 60, min([height, 1000000])],
Ellipsoid.WGS84,
result
);

View File

@ -4,7 +4,11 @@ import WavePoint from "@/components/common/WavePoint";
export default function WavePoints() {
return (
<Fragment>
<WavePoint stationLon={-62} stationLat={69} />
<WavePoint
stationLon={-59}
stationLat={60}
labelText={"拉布拉多海海温上升"}
/>
<WavePoint stationLon={88} stationLat={32.5} />
</Fragment>
);

View File

@ -1,10 +1,10 @@
import { Fragment, useState } from "react";
import {
Entity,
EllipsoidGraphics,
useCesium,
PolylineGraphics,
LabelGraphics,
ModelGraphics,
} from "resium";
import { useInterval } from "ahooks";
import {
@ -14,43 +14,36 @@ import {
LabelStyle,
PolylineDashMaterialProperty,
Cartesian2,
ColorBlendMode,
} from "cesium";
import arrowRound from "@/assets/arrow_round.glb";
import arrowRoundReverse from "@/assets/arrow_round_reverse.glb";
const lowCircle = (
<EllipsoidGraphics
radii={new Cartesian3(460000.0, 460000.0, 460000.0)}
innerRadii={new Cartesian3(415000.0, 415000.0, 415000.0)}
minimumCone={CesiumMath.toRadians(89.8)}
maximumCone={CesiumMath.toRadians(90.2)}
material={new Color(0, 0, 1, 1)}
/>
);
const highCircle = (
<EllipsoidGraphics
radii={new Cartesian3(460000.0, 460000.0, 460000.0)}
innerRadii={new Cartesian3(415000.0, 415000.0, 415000.0)}
minimumCone={CesiumMath.toRadians(89.8)}
maximumCone={CesiumMath.toRadians(90.2)}
material={new Color(1, 0, 0, 1)}
/>
);
// const labelText={
// '5','Rossby' , '', '680'
// }
const anticycloneColor = Color.fromCssColorString("#f70000");
const cycloneColor = Color.fromCssColorString("#0000ff");
function Circles() {
const { viewer } = useCesium();
const Circle = ({ id, lon, lat, isLow, showTime }) => {
const circle = isLow ? lowCircle : highCircle;
const [show, setShow] = useState(false);
const arrow = !isLow ? arrowRound : arrowRoundReverse;
const color = !isLow ? anticycloneColor : cycloneColor;
const minimumPixelSize = !isLow ? 128 : 98;
const circle = (
<ModelGraphics
uri={arrow}
minimumPixelSize={minimumPixelSize}
color={color}
colorBlendMode={ColorBlendMode.REPLACE}
/>
);
useInterval(() => {
const { startTime, currentTime, shouldAnimate } = viewer.clock;
const _time = Math.floor(
currentTime.secondsOfDay - startTime.secondsOfDay
const _time = (currentTime.secondsOfDay - startTime.secondsOfDay).toFixed(
1
);
if (!shouldAnimate) return;
if (_time >= showTime) {
@ -123,27 +116,55 @@ function Circles() {
<Circle
isLow={false}
id={`height-circle-1`}
showTime={4.5}
lon={-70}
lat={-64}
/>
<Circle
isLow={true}
id={`low-circle-2`}
showTime={7}
lon={-30}
lat={-55}
/>
<Circle
isLow={false}
id={`height-circle-2`}
showTime={9.5}
lon={0}
lat={-52.5}
/>
<Circle
isLow={true}
id={`low-circle-2`}
id={`low-circle-3`}
showTime={12}
lon={30}
lat={-40}
/>
<Circle
isLow={false}
id={`height-circle-2`}
id={`height-circle-3`}
showTime={14}
lon={45.5}
lat={-39}
/>
<Circle
isLow={true}
id={`low-circle-4`}
showTime={16}
lon={65}
lat={-35}
/>
<Circle
isLow={false}
id={`height-circle-4`}
showTime={18}
lon={80}
lat={-33.5}
/>
<Circle
isLow={true}
id={`low-circle-3`}
id={`low-circle-5`}
showTime={20}
lon={95}
lat={-30}

View File

@ -1,6 +1,6 @@
import antiHadleyCell from "@/assets/anti-Hadleycell.png";
import low from "@/assets/Low.png";
import high from "@/assets/High.png";
import low from "@/assets/cyclone.jpg";
import high from "@/assets/anticyclone.png";
import cloud from "@/assets/cloud.png";
import moisture from "@/assets/moisture.png";
@ -8,7 +8,7 @@ function EntityLegend() {
return (
<div className="entity-legend" style={{ bottom: 116 }}>
<div className="entity-legend-item">
<div>
<div style={{ transform: "rotate(45deg)" }}>
<img src={low} alt="low" width={32} />
</div>
<div className="entity-legend-item-name">Low</div>
@ -26,7 +26,7 @@ function EntityLegend() {
<div className="entity-legend-item-name">anti-Hadley cell</div>
</div>
<div className="entity-legend-item">
<div>
<div style={{ transform: "rotate(120deg)" }}>
<img src={high} alt="high" width={32} />
</div>
<div className="entity-legend-item-name">High</div>

View File

@ -0,0 +1,56 @@
import { Cartesian3, Color, PolylineArrowMaterialProperty } from "cesium";
import { Fragment } from "react";
import { Entity, PolylineGraphics } from "resium";
export default function HadleyCell() {
return (
<Fragment>
{/* 右下部分 */}
{/* <Entity>
<PolylineGraphics
positions={Cartesian3.fromDegreesArrayHeights([
68, 24, 200000, 68, 24, 1000000,
])}
width={10}
material={Color.WHITE}
/>
</Entity>
<Entity>
<PolylineGraphics
positions={Cartesian3.fromDegreesArrayHeights([
68, 24, 200000, 80, 30, 200000,
])}
width={30}
material={new PolylineArrowMaterialProperty(Color.BLUE)}
/>
</Entity> */}
<Entity>
<PolylineGraphics
positions={Cartesian3.fromDegreesArrayHeights([
68, 24, 1000000, 68, 24, 300000, 70, 25, 200000, 79, 29.5, 200000,
])}
width={50}
material={
new PolylineArrowMaterialProperty(
Color.fromCssColorString("#04fbfd")
)
}
/>
</Entity>
{/* 左上部分 */}
<Entity>
<PolylineGraphics
positions={Cartesian3.fromDegreesArrayHeights([
80, 30, 200000, 80, 30, 900000, 78, 29, 1000000, 69, 24.5, 1000000,
])}
width={50}
material={
new PolylineArrowMaterialProperty(
Color.fromCssColorString("#04fbfd")
)
}
/>
</Entity>
</Fragment>
);
}

View File

@ -16,9 +16,13 @@ import {
const dataAntarcticaToQTP = [
{ longitude: -110, latitude: -60, height: 0, time: 0 },
{ longitude: -110, latitude: -60, height: 1000000, time: 2 },
{ longitude: -70, latitude: -64, height: 1000000, time: 4.5 },
{ longitude: -30, latitude: -55, height: 1000000, time: 7 },
{ longitude: 0, latitude: -52.5, height: 1000000, time: 9.5 },
{ longitude: 30, latitude: -40, height: 1000000, time: 12 },
{ longitude: 45.5, latitude: -39, height: 1000000, time: 14 },
{ longitude: 65, latitude: -35, height: 1000000, time: 16 },
{ longitude: 80, latitude: -33.5, height: 1000000, time: 18 },
{ longitude: 95, latitude: -30, height: 1000000, time: 20 },
{ longitude: 95, latitude: -30, height: 0, time: 25 },
];

View File

@ -31,13 +31,20 @@ function SiteLegend() {
style={{ transform: "rotate(180deg)" }}
/>
</div>
<div className="site-legend-item-name">感热通量异常增加</div>
<div className="site-legend-item-name">
感热通量
<br />
异常增加
</div>
</div>
<div className="site-legend-item">
<div>
<img src={heatflux} alt="heatflux-decrease" width={32} />
</div>
<div className="site-legend-item-name">感热通量异常降低</div>
<div className="site-legend-item-name">
感热通量 <br />
异常降低
</div>
</div>
</div>
);

View File

@ -15,6 +15,7 @@ import Sites from "./Site";
import SiteLegend from "./SiteLegend";
import Labels from "./Labels";
import TimeLinePanel from "./TimeLinePanel";
import HadleyCell from "./HadleyCell";
export default function DomainTwo() {
return (
@ -37,6 +38,7 @@ export default function DomainTwo() {
</div>
<WavePoints />
<TimeLinePanel />
<HadleyCell />
{/* <SurfaceAnomaly /> */}
</MapLayout>
);

View File

@ -18,6 +18,7 @@
gap: 8px;
.site-legend-item-name {
font-size: 20px;
font-weight: 700;
}
}