This commit is contained in:
Aifeilong 2023-09-26 18:35:08 +08:00
parent c356384360
commit bd77497225
34 changed files with 1147 additions and 334 deletions

View File

@ -1,8 +1,11 @@
import { Clock, useCesium } from "resium";
import { Clock } from "resium";
function CustomClock({ start, stop }) {
const { viewer } = useCesium();
//
const start = Cesium.JulianDate.fromDate(new Date());
//
const stop = Cesium.JulianDate.addSeconds(start, 60, new Cesium.JulianDate());
function CustomClock() {
return (
<Clock
multiplier={1}
@ -11,15 +14,13 @@ function CustomClock({ start, stop }) {
stopTime={stop.clone()}
currentTime={start.clone()}
clockRange={Cesium.ClockRange.LOOP_STOP}
onStop={() => {
// const move = viewer.entities.values.filter(
// (entity) => entity.id === "move"
// )[0];
// viewer.trackedEntity = move;
// viewer.camera.flyTo({
// destination: Cesium.Cartesian3.fromDegrees(88, -89, 20000000),
// });
}}
// onTick={(clock) => {
// if (!clock.shouldAnimate) return;
// }}
// onStop={() => {
// if (toolbar.showPanel === undefined)
// dispatch.data.updateToolbar({ showPanel: true });
// }}
/>
);
}

View File

@ -1,60 +0,0 @@
import { Camera, useCesium } from "resium";
function CustomFlyTo() {
const { viewer } = useCesium();
const { camera } = viewer;
function cameraFlyToLine(adjustPitch) {
//
const antarcticalOptions = {
destination: Cesium.Cartesian3.fromDegrees(88, -89, 1600000),
orientation: {
heading: Cesium.Math.toRadians(15.0),
pitch: Cesium.Math.toRadians(-60),
roll: 0.0,
},
duration: 10,
complete: function () {
setTimeout(() => {
camera.flyTo(plateauOptions);
}, 1000);
},
};
//
const plateauOptions = {
destination: Cesium.Cartesian3.fromDegrees(90, 20, 1600000),
duration: 10,
orientation: {
heading: Cesium.Math.toRadians(-15.0),
pitch: -Cesium.Math.PI_OVER_FOUR,
roll: 0.0,
},
complete: function () {
setTimeout(function () {
camera.flyTo(sideViewOptions);
}, 1000);
},
};
//
const sideViewOptions = {
destination: Cesium.Cartesian3.fromDegrees(130, -10.5, 20000000),
duration: 5,
complete: () => {
viewer.clock.shouldAnimate = true;
},
};
if (adjustPitch) {
antarcticalOptions.pitchAdjustHeight = 1000;
plateauOptions.pitchAdjustHeight = 1000;
sideViewOptions.pitchAdjustHeight = 1000;
}
camera.flyTo(antarcticalOptions);
}
cameraFlyToLine();
return <Camera />;
}
export default CustomFlyTo;

View File

@ -0,0 +1,106 @@
import { useCesium } from "resium";
function AntarcticaFlytoQTP() {
const { viewer } = useCesium();
const { camera } = viewer;
function cameraFlyToLine(adjustPitch) {
//
const antarcticalOptions = {
destination: Cesium.Cartesian3.fromDegrees(88, -89, 1600000),
orientation: {
heading: Cesium.Math.toRadians(15.0),
pitch: Cesium.Math.toRadians(-60),
roll: 0.0,
},
duration: 10,
complete: function () {
setTimeout(() => {
camera.flyTo(area1Options);
}, 1000);
},
};
const area1Options = {
destination: Cesium.Cartesian3.fromDegrees(-110, -60, 6000000),
duration: 5,
complete: function () {
setTimeout(function () {
camera.flyTo(area2Options);
}, 1000);
},
};
const area2Options = {
destination: Cesium.Cartesian3.fromDegrees(-30, -55, 6000000),
duration: 5,
complete: function () {
setTimeout(function () {
camera.flyTo(area3Options);
}, 1000);
},
};
const area3Options = {
destination: Cesium.Cartesian3.fromDegrees(30, -40, 6000000),
duration: 5,
complete: function () {
setTimeout(function () {
camera.flyTo(area4Options);
}, 1000);
},
};
const area4Options = {
destination: Cesium.Cartesian3.fromDegrees(65, -35, 6000000),
duration: 5,
complete: function () {
setTimeout(function () {
camera.flyTo(sideViewOptions);
}, 1000);
},
};
//
const plateauOptions = {
destination: Cesium.Cartesian3.fromDegrees(95, -30, 6000000),
duration: 10,
orientation: {
heading: Cesium.Math.toRadians(-15.0),
pitch: -Cesium.Math.PI_OVER_FOUR,
roll: 0.0,
},
complete: function () {
setTimeout(function () {
camera.flyTo(sideViewOptions);
}, 1000);
},
};
//
const sideViewOptions = {
destination: Cesium.Cartesian3.fromDegrees(70, -60, 14000000),
// destination: Cesium.Cartesian3.fromDegrees(130, -10.5, 20000000),
duration: 5,
orientation: {
heading: Cesium.Math.toRadians(-10.0),
pitch: Cesium.Math.toRadians(-90),
roll: 6.0,
},
complete: () => {
viewer.clock.shouldAnimate = true;
},
};
if (adjustPitch) {
antarcticalOptions.pitchAdjustHeight = 1000;
plateauOptions.pitchAdjustHeight = 1000;
sideViewOptions.pitchAdjustHeight = 1000;
}
camera.flyTo(antarcticalOptions);
}
cameraFlyToLine();
return <></>;
}
export default AntarcticaFlytoQTP;

View File

@ -1,10 +1,40 @@
import { useDispatch } from "react-redux";
import { Camera, useCesium } from "resium";
function CustomFlyTo() {
function LabFlytoQTP() {
const { viewer } = useCesium();
const { camera } = viewer;
const dispatch = useDispatch();
function cameraFlyToLine(adjustPitch) {
// barotorpic
const barotorpic = {
destination: Cesium.Cartesian3.fromDegrees(42, 46, 15000000),
duration: 30,
complete: () => {},
};
//
const sideViewOptions = {
destination: Cesium.Cartesian3.fromDegrees(-50, 46, 2000000),
duration: 5,
orientation: {
heading: Cesium.Math.toRadians(-15.0),
pitch: -Cesium.Math.PI_OVER_FOUR,
roll: 0.0,
},
complete: () => {
viewer.clock.shouldAnimate = true;
setTimeout(function () {
camera.flyTo(barotorpic);
}, 1000);
dispatch.data.updateImageLayer({
labrador: true,
});
dispatch.data.updateToolbar({ showPanel: true });
},
};
//
const plateauOptions = {
destination: Cesium.Cartesian3.fromDegrees(90, 20, 1600000),
@ -16,7 +46,7 @@ function CustomFlyTo() {
},
complete: function () {
setTimeout(function () {
camera.flyTo(step1);
camera.flyTo(sideViewOptions);
}, 1000);
},
};
@ -37,43 +67,6 @@ function CustomFlyTo() {
},
};
// barotorpic
const barotorpic = {
destination: Cesium.Cartesian3.fromDegrees(42, 46, 15000000),
duration: 30,
complete: function () {},
};
// //
// const sideViewOptions = {
// destination: Cesium.Cartesian3.fromDegrees(-2.5, 32.5, 20000000),
// duration: 5,
// complete: () => {
// const entity = viewer.entities.getById("point");
// viewer.clock.shouldAnimate = true;
// setTimeout(function () {
// camera.flyTo(step1);
// }, 1000);
// },
// };
//
const step1 = {
destination: Cesium.Cartesian3.fromDegrees(-50, 46, 2000000),
duration: 5,
orientation: {
heading: Cesium.Math.toRadians(-15.0),
pitch: -Cesium.Math.PI_OVER_FOUR,
roll: 0.0,
},
complete: () => {
viewer.clock.shouldAnimate = true;
setTimeout(function () {
camera.flyTo(barotorpic);
}, 1000);
},
};
if (adjustPitch) {
plateauOptions.pitchAdjustHeight = 1000;
sideViewOptions.pitchAdjustHeight = 1000;
@ -81,7 +74,8 @@ function CustomFlyTo() {
camera.flyTo(labrador);
}
cameraFlyToLine();
return <Camera />;
return <></>;
}
export default CustomFlyTo;
export default LabFlytoQTP;

View File

@ -0,0 +1,17 @@
import { useParams } from "react-router-dom";
import LabFlytoQTP from "./LabFlytoQTP";
import AntarcticaFlytoQTP from "./AntarcticaFlytoQTP";
function CustomFlyTo({}) {
const { type } = useParams();
return type === "1" ? (
<LabFlytoQTP />
) : type === "2" ? (
<AntarcticaFlytoQTP />
) : (
<></>
);
}
export default CustomFlyTo;

View File

@ -99,7 +99,7 @@ function CustomToolbar() {
/> */}
<Select
onChange={showPanelHandler}
value={toolbar.showPanel}
value={!!toolbar.showPanel}
getPopupContainer={(node) => node}
options={[
{

View File

@ -0,0 +1,36 @@
import { useEffect, useMemo, useState } from "react";
import { ImageryLayer, useCesium } from "resium";
import { WebMapServiceImageryProvider } from "cesium";
import { useInterval } from "ahooks";
import { useSelector } from "react-redux";
const url = "http://analysis.tpdc.ac.cn/gs/geoserver/phitrellis/wms";
function LayerAntarcticaToQTP() {
const { imageLayer } = useSelector((state) => state.data);
console.log("imageLayer :>> ", imageLayer);
const tempProvider = useMemo(
() =>
new WebMapServiceImageryProvider({
url: url,
layers: "phitrellis:india_ocean_sst",
parameters: {
service: "WMS",
format: "image/png",
transparent: true,
},
}),
[url]
);
return (
<ImageryLayer
key={`ImageryLayer-india-ocean`}
imageryProvider={tempProvider}
show={!!imageLayer.indianOcean}
/>
);
}
export default LayerAntarcticaToQTP;

View File

@ -0,0 +1,65 @@
import { useEffect, useMemo, useState } from "react";
import { ImageryLayer, useCesium } from "resium";
import { WebMapServiceImageryProvider } from "cesium";
import { useInterval } from "ahooks";
import { useSelector } from "react-redux";
const url = "http://analysis.tpdc.ac.cn/gs/geoserver/phitrellis/wms";
const nameList = [
1980, 1981, 1982, 1983, 1984, 1985, 1986, 1987, 1988, 1989, 1990, 1991, 1992,
1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017,
].map((item) => "phitrellis:4_1_la_" + item);
function LayerLabToQTP() {
const { viewer } = useCesium();
const { imageLayer } = useSelector((state) => state.data);
const [delay, setDelay] = useState(undefined);
const [index, setIndex] = useState(0);
//viewer.clock?.shouldAnimate
useEffect(() => {
const { labrador } = imageLayer;
if (!!labrador) {
setDelay(1000);
setIndex(0);
}
}, [imageLayer]);
const layers = nameList.map((name, index) => {
const tempProvider = useMemo(
() =>
new WebMapServiceImageryProvider({
url: url,
layers: name,
parameters: {
service: "WMS",
format: "image/png",
transparent: true,
},
}),
[name, url]
);
return (
<ImageryLayer
key={`ImageryLayer-${index}`}
imageryProvider={tempProvider}
show={true}
/>
);
});
useInterval(() => {
setIndex((index) => index + 1);
if (!viewer.clock?.shouldAnimate) {
setDelay(undefined);
}
if (index >= nameList.length) setDelay(undefined);
}, delay);
return <></>;
// return layers[index];
}
export default LayerLabToQTP;

View File

@ -0,0 +1,13 @@
import { useParams } from "react-router-dom";
import LayerLabToQTP from "./LayerLabToQTP";
import LayerAntarcticaToQTP from "./LayerAntarcticaToQTP";
const DynamicImageryLayer = () => {
const { type } = useParams();
if (type === "1") return <LayerLabToQTP />;
else if (type === "2") return <LayerAntarcticaToQTP />;
else return <></>;
};
export default DynamicImageryLayer;

View File

@ -1,20 +0,0 @@
import WavePoint from "./WavePoint";
function AntarcticaPolygon() {
return (
// <Entity>
// <PolygonGraphics
// hierarchy={Cesium.Cartesian3.fromDegreesArray([
// 20, -85, -20, -85, -20, -88, 20, -88,
// ])}
// material={Cesium.Color.PINK}
// outline={true}
// outlineColor={Cesium.Color.RED}
// outlineWidth={20}
// />
// </Entity>
<WavePoint stationLat={-85} stationLon={88} />
);
}
export default AntarcticaPolygon;

View File

@ -7,28 +7,12 @@ import {
CylinderGraphics,
} from "resium";
import { Color, Cartesian3, LabelStyle } from "cesium";
import { useParams } from "react-router-dom";
import { useInterval } from "ahooks";
// const material = Cesium.Material.fromType("Custom", {
// fabric: Cesium.Color.RED.withAlpha(0.5),
// shader: `
// czm_material input;
// czm_material output;
// void main() {
// output = input;
// output.alpha = sin(input.st) * 0.5 + 0.5; //
// }`,
// uniforms: {
// input: function (czm, frameNumber, time, context) {
// var u = Cesium.getUniform(context, "u");
// return Cesium.Color.fromAlpha(czm.color, u);
// },
// },
// });
function Barotropic() {
const { viewer } = useCesium();
const { type } = useParams();
const [show, setShow] = useState(false);
@ -45,11 +29,13 @@ function Barotropic() {
useInterval(showAnimate, 1000);
if (type !== "1") return <></>;
return (
<Entity
show={show}
name="EllipseGraphics"
description="EllipseGraphics!!"
name="Barotropic"
// description="Barotropic"
position={Cartesian3.fromDegrees(88, 60, 0)}
>
<EllipseGraphics

View File

@ -0,0 +1,157 @@
import { Fragment, useCallback, useState } from "react";
import { Entity, EllipsoidGraphics, useCesium, PolylineGraphics } from "resium";
import { useParams } from "react-router-dom";
import { useInterval, useThrottleFn } from "ahooks";
import { useDispatch } from "react-redux";
const lowCircle = (
<EllipsoidGraphics
radii={new Cesium.Cartesian3(460000.0, 460000.0, 460000.0)}
innerRadii={new Cesium.Cartesian3(415000.0, 415000.0, 415000.0)}
minimumCone={Cesium.Math.toRadians(89.8)}
maximumCone={Cesium.Math.toRadians(90.2)}
material={new Cesium.Color(0.29, 0.46, 0.77, 1)}
/>
);
const highCircle = (
<EllipsoidGraphics
radii={new Cesium.Cartesian3(460000.0, 460000.0, 460000.0)}
innerRadii={new Cesium.Cartesian3(415000.0, 415000.0, 415000.0)}
minimumCone={Cesium.Math.toRadians(89.8)}
maximumCone={Cesium.Math.toRadians(90.2)}
material={new Cesium.Color(0.99, 0.23, 0.23, 1)}
/>
);
function Circles() {
const { viewer } = useCesium();
const { type } = useParams();
const dispatch = useDispatch();
if (type !== "2") return <></>;
const { run: showInfo } = useThrottleFn(
() => {
dispatch.data.updateImageLayer({ indianOcean: true });
dispatch.data.update({ showSite: true });
},
{
wait: 1000,
}
);
const { run: closeInfo } = useThrottleFn(
() => {
dispatch.data.updateImageLayer({ indianOcean: false });
dispatch.data.update({ showSite: false });
},
{
wait: 1000,
}
);
const Circle = ({ id, lon, lat, isLow, showTime }) => {
const circle = isLow ? lowCircle : highCircle;
const [show, setShow] = useState(false);
useInterval(() => {
const { startTime, currentTime, shouldAnimate } = viewer.clock;
const _time = Math.floor(
currentTime.secondsOfDay - startTime.secondsOfDay
);
if (!shouldAnimate) return;
if (_time === 40) {
showInfo();
} else if (_time === 0) {
closeInfo();
}
if (_time >= showTime) {
setShow(true);
} else {
if (!show) return;
setShow(false);
}
}, 300);
if (!show) return <></>;
return (
<Fragment>
<Entity
id={`${id}-up`}
position={Cesium.Cartesian3.fromDegrees(lon, lat, 1000000)}
>
{circle}
</Entity>
{show && (
<Entity id={`${id}-connection-line`}>
<PolylineGraphics
positions={Cesium.Cartesian3.fromDegreesArrayHeights([
lon,
lat,
1000000,
lon,
lat,
0,
])}
width={2}
material={
new Cesium.PolylineDashMaterialProperty({
color: Cesium.Color.WHITE,
dashLength: 4,
})
}
/>
</Entity>
)}
<Entity
id={`${id}-down`}
position={Cesium.Cartesian3.fromDegrees(lon, lat, 0)}
>
{circle}
</Entity>
</Fragment>
);
};
return (
<Fragment>
<Circle
isLow={true}
id={`low-circle-1`}
showTime={10}
lon={-110}
lat={-60}
/>
<Circle
isLow={false}
id={`height-circle-1`}
showTime={20}
lon={-30}
lat={-55}
/>
<Circle
isLow={true}
id={`low-circle-2`}
showTime={30}
lon={30}
lat={-40}
/>
<Circle
isLow={false}
id={`height-circle-2`}
showTime={40}
lon={65}
lat={-35}
/>
<Circle
isLow={true}
id={`low-circle-3`}
showTime={50}
lon={95}
lat={-30}
/>
</Fragment>
);
}
export default Circles;

View File

@ -0,0 +1,146 @@
function Cloud() {
const viewer = new Cesium.Viewer("cesiumContainer");
const scene = viewer.scene;
const position = Cesium.Cartesian3.fromDegrees(-123.0744619, 44.0503706, 50);
function getColor(colorName) {
return Cesium.Color[colorName.toUpperCase()];
}
// These noise parameters are set to default, but can be changed
// to produce different cloud results. However, the noise is precomputed,
// so this cannot be changed dynamically.
const clouds = scene.primitives.add(
new Cesium.CloudCollection({
noiseDetail: 16.0,
noiseOffset: Cesium.Cartesian3.ZERO,
})
);
const cloudParameters = {
scaleWithMaximumSize: true,
scaleX: 25,
scaleY: 12,
maximumSizeX: 25,
maximumSizeY: 12,
maximumSizeZ: 15,
renderSlice: true, // if false, renders the entire surface of the ellipsoid
slice: 0.36,
brightness: 1.0,
color: "White",
colors: ["White", "Red", "Green", "Blue", "Yellow", "Gray"],
};
const cloud = clouds.add({
position: position,
scale: new Cesium.Cartesian2(
cloudParameters.scaleX,
cloudParameters.scaleY
),
maximumSize: new Cesium.Cartesian3(
cloudParameters.maximumSizeX,
cloudParameters.maximumSizeY,
cloudParameters.maximumSizeZ
),
color: getColor(cloudParameters.color),
slice: cloudParameters.renderSlice ? cloudParameters.slice : -1.0,
brightness: cloudParameters.brightness,
});
Cesium.knockout.track(cloudParameters);
const toolbar = document.getElementById("toolbar");
Cesium.knockout.applyBindings(cloudParameters, toolbar);
Cesium.knockout
.getObservable(cloudParameters, "scaleWithMaximumSize")
.subscribe(function (newValue) {
if (Boolean(newValue)) {
cloudParameters.scaleX = cloudParameters.maximumSizeX;
cloudParameters.scaleY = cloudParameters.maximumSizeY;
}
});
Cesium.knockout
.getObservable(cloudParameters, "scaleX")
.subscribe(function (newValue) {
const value = Number(newValue);
cloud.scale = new Cesium.Cartesian2(value, cloud.scale.y);
});
Cesium.knockout
.getObservable(cloudParameters, "scaleY")
.subscribe(function (newValue) {
const value = Number(newValue);
cloud.scale = new Cesium.Cartesian2(cloud.scale.x, value);
});
Cesium.knockout
.getObservable(cloudParameters, "maximumSizeX")
.subscribe(function (newValue) {
const value = Number(newValue);
cloud.maximumSize = new Cesium.Cartesian3(
value,
cloud.maximumSize.y,
cloud.maximumSize.z
);
if (cloudParameters.scaleWithMaximumSize) {
cloud.scale = new Cesium.Cartesian2(value, cloud.scale.y);
}
});
Cesium.knockout
.getObservable(cloudParameters, "maximumSizeY")
.subscribe(function (newValue) {
const value = Number(newValue);
cloud.maximumSize = new Cesium.Cartesian3(
cloud.maximumSize.x,
value,
cloud.maximumSize.z
);
if (cloudParameters.scaleWithMaximumSize) {
cloud.scale = new Cesium.Cartesian2(cloud.scale.x, value);
}
});
Cesium.knockout
.getObservable(cloudParameters, "maximumSizeZ")
.subscribe(function (newValue) {
const value = Number(newValue);
cloud.maximumSize = new Cesium.Cartesian3(
cloud.maximumSize.x,
cloud.maximumSize.y,
value
);
});
Cesium.knockout
.getObservable(cloudParameters, "renderSlice")
.subscribe(function (newValue) {
if (Boolean(newValue)) {
cloud.slice = Number(cloudParameters.slice);
} else {
cloud.slice = -1.0;
}
});
Cesium.knockout
.getObservable(cloudParameters, "slice")
.subscribe(function (newValue) {
cloud.slice = Number(newValue);
});
Cesium.knockout
.getObservable(cloudParameters, "color")
.subscribe(function (newValue) {
cloud.color = getColor(newValue);
});
Cesium.knockout
.getObservable(cloudParameters, "brightness")
.subscribe(function (newValue) {
cloud.brightness = Number(newValue);
});
viewer.camera.lookAt(position, new Cesium.Cartesian3(30, 30, -10));
}
export default Cloud;

View File

@ -1,6 +1,6 @@
import { Fragment, useCallback, useRef, useState } from "react";
import { Fragment, useCallback } from "react";
import { Entity, ModelGraphics, useCesium } from "resium";
import { useInterval } from "ahooks";
import { useParams } from "react-router-dom";
import arrowRound from "@/assets/arrow_round.glb";
let totalSeconds = 60;
@ -9,12 +9,9 @@ let wheelAngle = 0;
function Cyclone() {
const { viewer } = useCesium();
const { type } = useParams();
const [show1, setShow1] = useState(false);
const [show2, setShow2] = useState(false);
const [show3, setShow3] = useState(false);
const [show4, setShow4] = useState(false);
const [show5, setShow5] = useState(false);
if (type !== "1") return <></>;
// const position = new Cesium.SampledPositionProperty();
@ -44,49 +41,23 @@ function Cyclone() {
// );
// }, false);
const animate = useCallback(() => {
const { startTime, currentTime, shouldAnimate } = viewer.clock;
if (!shouldAnimate) return;
const time = Math.floor(currentTime.secondsOfDay - startTime.secondsOfDay);
if (time < 10) {
if (time === 0) {
setShow1(false);
setShow2(false);
setShow3(false);
setShow4(false);
setShow5(false);
}
} else if (10 <= time < 50) {
if (time === 10) {
setShow1(true);
}
if (time === 20) {
setShow2(true);
}
if (time === 30) {
setShow3(true);
}
if (time === 40) {
setShow4(true);
}
if (time === 50) {
setShow5(true);
}
} else if (50 <= time < 60) {
if (time === 50) {
setShow5(true);
}
}
const getPassTime = useCallback(() => {
const { startTime, currentTime } = viewer.clock;
const _time = Math.floor(currentTime.secondsOfDay - startTime.secondsOfDay);
return _time;
}, [viewer]);
useInterval(animate, 1000);
return (
<Fragment>
<Entity
id={"Anticyclone-1"}
show={show1}
position={Cesium.Cartesian3.fromDegrees(-55, 58, 1000000)}
position={
new Cesium.CallbackProperty(function (time, result) {
const passTime = getPassTime();
if (passTime < 10) return;
return Cesium.Cartesian3.fromDegrees(-55, 58, 1000000);
}, true)
}
>
<ModelGraphics
uri={arrowRound}
@ -100,36 +71,61 @@ function Cyclone() {
</Entity>
<Entity
id={"Cyclone-1"}
show={show2}
position={Cesium.Cartesian3.fromDegrees(-32, 72.2, 1000000)}
position={
new Cesium.CallbackProperty(function (time, result) {
const passTime = getPassTime();
if (passTime < 20) return;
return Cesium.Cartesian3.fromDegrees(-32, 72.2, 1000000);
}, true)
}
>
<ModelGraphics uri={arrowRound} minimumPixelSize={64} />
</Entity>
<Entity
id={"Anticyclone-2"}
show={show3}
position={Cesium.Cartesian3.fromDegrees(20, 77, 1000000)}
position={
new Cesium.CallbackProperty(function (time, result) {
const passTime = getPassTime();
if (passTime < 30) return;
return Cesium.Cartesian3.fromDegrees(20, 77, 1000000);
}, true)
}
>
<ModelGraphics uri={arrowRound} minimumPixelSize={64} />
</Entity>
<Entity
id={"Cyclone-2"}
show={show4}
position={Cesium.Cartesian3.fromDegrees(63, 69.9, 1000000)}
position={
new Cesium.CallbackProperty(function (time, result) {
const passTime = getPassTime();
if (passTime < 40) return;
return Cesium.Cartesian3.fromDegrees(63, 69.9, 1000000);
}, true)
}
>
<ModelGraphics uri={arrowRound} minimumPixelSize={64} />
</Entity>
<Entity
id={"Anticyclone-3"}
show={show5}
position={Cesium.Cartesian3.fromDegrees(88, 60, 1000000)}
position={
new Cesium.CallbackProperty(function (time, result) {
const passTime = getPassTime();
if (passTime < 50) return;
return Cesium.Cartesian3.fromDegrees(88, 60, 1000000);
}, true)
}
>
<ModelGraphics uri={arrowRound} minimumPixelSize={64} />
</Entity>
<Entity
id={"Anticyclone-4"}
show={show5}
position={Cesium.Cartesian3.fromDegrees(88, 60, 0)}
position={
new Cesium.CallbackProperty(function (time, result) {
const passTime = getPassTime();
if (passTime < 50) return;
return Cesium.Cartesian3.fromDegrees(88, 60, 0);
}, true)
}
>
<ModelGraphics uri={arrowRound} minimumPixelSize={64} />
</Entity>

View File

@ -5,16 +5,13 @@ import WavePoint from "./WavePoint";
function PlateauPolygon() {
return (
<Fragment>
<WavePoint stationLat={32.5} stationLon={88} />
{/* <WavePoint stationLat={32.5} stationLon={88} /> */}
<Entity id="plateau">
<PolygonGraphics
hierarchy={Cesium.Cartesian3.fromDegreesArray([
85, 30, 91, 30, 91, 35, 85, 35,
])}
// height={1}
material={new Cesium.Color(1, 0, 0, 0.1)}
// outline={true}
// outlineColor={Cesium.Color.LIGHTBLUE}
/>
</Entity>
</Fragment>

View File

@ -0,0 +1,92 @@
import { useEffect } from "react";
import { Entity, PointGraphics, useCesium } from "resium";
//
const dataAntarcticaToQTP = [
{ longitude: -110, latitude: -60, height: 0, time: 0 },
{ longitude: -110, latitude: -60, height: 1000000, time: 10 },
{ longitude: -30, latitude: -55, height: 1000000, time: 20 },
{ longitude: 30, latitude: -40, height: 1000000, time: 30 },
{ longitude: 65, latitude: -35, height: 1000000, time: 40 },
{ longitude: 95, latitude: -30, height: 1000000, time: 50 },
{ longitude: 95, latitude: -30, height: 0, time: 60 },
];
let property;
function PathAntarcticaToQTP() {
const { viewer } = useCesium();
const start = viewer.clock.startTime;
const stop = viewer.clock.stopTime;
const currentTime = viewer.clock.currentTime;
const pathMaterial = new Cesium.Color(4 / 255, 251 / 255, 253 / 255);
/**
* 计算飞行路径
* 数据坐标
* {SampledPositionProperty|*}
*/
function createProperty(source) {
let property = new Cesium.SampledPositionProperty();
for (let i = 0; i < source.length; i++) {
let time = Cesium.JulianDate.addSeconds(
start,
source[i].time,
new Cesium.JulianDate()
);
let position = Cesium.Cartesian3.fromDegrees(
source[i].longitude,
source[i].latitude,
source[i].height
);
//
property.addSample(time, position);
}
property.setInterpolationOptions({
interpolationDegree: 1,
interpolationAlgorithm: Cesium.LinearApproximation,
});
return property;
}
useEffect(() => {
property = createProperty(dataAntarcticaToQTP);
console.log("property 2:>> ", start, stop, currentTime, property);
}, []);
return (
<Entity
id={"point"}
position={property}
availability={
new Cesium.TimeIntervalCollection([
new Cesium.TimeInterval({
start: start,
stop: stop,
}),
])
}
orientation={new Cesium.VelocityOrientationProperty(property)}
path={{
resolution: 1,
material: pathMaterial,
// leadTimetrailTime path
leadTime: 0, // 0 path
// trailTime: 0, // 0 path
width: 2,
}}
>
<PointGraphics
show={true}
color={Cesium.Color.SKYBLUE}
pixelSize={10}
outlineColor={Cesium.Color.YELLOW}
outlineWidth={3}
/>
</Entity>
);
}
export default PathAntarcticaToQTP;

View File

@ -0,0 +1,90 @@
import { Entity, PointGraphics, useCesium } from "resium";
//
const dataLabToQTP = [
{ longitude: -55, latitude: 58, height: 1000000, time: 10 },
{ longitude: -32, latitude: 72.2, height: 1000000, time: 20 },
{ longitude: 20, latitude: 77, height: 1000000, time: 30 },
{ longitude: 63, latitude: 69.9, height: 1000000, time: 40 },
{ longitude: 88, latitude: 60, height: 1000000, time: 50 },
];
function PathLabToQTP() {
const { viewer } = useCesium();
const start = viewer.clock.startTime;
const stop = viewer.clock.stopTime;
const pathMaterial = new Cesium.PolylineDashMaterialProperty({
dashLength: 20,
color: new Cesium.Color(4 / 255, 251 / 255, 253 / 255),
});
/**
* 计算飞行路径
* 数据坐标
* {SampledPositionProperty|*}
*/
function createProperty(source) {
let property = new Cesium.SampledPositionProperty();
for (let i = 0; i < source.length; i++) {
const start = viewer.clock.startTime;
const stop = viewer.clock.stopTime;
let time = Cesium.JulianDate.addSeconds(
start,
source[i].time,
new Cesium.JulianDate()
);
let position = Cesium.Cartesian3.fromDegrees(
source[i].longitude,
source[i].latitude,
source[i].height
);
//
property.addSample(time, position);
console.log("property for:>> ", property, start, stop, viewer);
}
property.setInterpolationOptions({
interpolationDegree: 10,
interpolationAlgorithm: Cesium.LagrangePolynomialApproximation,
});
return property;
}
const property = createProperty(dataLabToQTP);
return (
<Entity
id={"point"}
position={property}
availability={
new Cesium.TimeIntervalCollection([
new Cesium.TimeInterval({
start: start,
stop: stop,
}),
])
}
orientation={new Cesium.VelocityOrientationProperty(property)}
path={{
resolution: 1,
material: pathMaterial,
// leadTimetrailTime path
leadTime: 0, // 0 path
// trailTime: 0, // 0 path
width: 2,
}}
>
<PointGraphics
show={true}
color={Cesium.Color.SKYBLUE}
pixelSize={10}
outlineColor={Cesium.Color.YELLOW}
outlineWidth={3}
/>
</Entity>
);
}
export default PathLabToQTP;

View File

@ -1,26 +1,21 @@
import { Entity, PointGraphics, useCesium } from "resium";
import { flatten } from "lodash-es";
const height = 9000 * 100;
//
const step1 = [
// { longitude: -55, latitude: 58, height: 0, time: 0 },
{ longitude: -55, latitude: 58, height: 1000000, time: 10 },
];
//
const step2 = [
{ longitude: -32, latitude: 72.2, height, time: 20 },
{ longitude: 20, latitude: 77, height, time: 30 },
{ longitude: 63, latitude: 69.9, height, time: 40 },
];
//
const step3 = [
{ longitude: 88, latitude: 60, height: 1000000, time: 50 },
// { longitude: 80, latitude: 60, height: 0, time: 60 },
];
const data = flatten([step1, step2, step3]);
function Point({ data, isCurves, pathColor, pathType = "default" }) {
const { viewer } = useCesium();
const start = viewer.clock.startTime;
const stop = viewer.clock.stopTime;
const pathMaterial =
pathType === "dash"
? new Cesium.PolylineDashMaterialProperty({
dashLength: 20,
color: pathColor || new Cesium.Color(4 / 255, 251 / 255, 253 / 255),
})
: pathColor || new Cesium.Color(4 / 255, 251 / 255, 253 / 255);
console.log("pathMaterial :>> ", pathMaterial);
function Point({ start, stop }) {
/**
* 计算飞行路径
* 数据坐标
@ -48,8 +43,10 @@ function Point({ start, stop }) {
const property = createProperty(data);
property.setInterpolationOptions({
interpolationDegree: 10,
interpolationAlgorithm: Cesium.LagrangePolynomialApproximation,
interpolationDegree: isCurves ? 10 : 1,
interpolationAlgorithm: isCurves
? Cesium.LagrangePolynomialApproximation
: Cesium.LinearApproximation,
});
// property.setInterpolationOptions({
// interpolationDegree: 1,
@ -58,7 +55,7 @@ function Point({ start, stop }) {
return (
<Entity
id={"point"}
id={"point-4-2"}
position={property}
availability={
new Cesium.TimeIntervalCollection([
@ -71,10 +68,7 @@ function Point({ start, stop }) {
orientation={new Cesium.VelocityOrientationProperty(property)}
path={{
resolution: 1,
material: new Cesium.PolylineDashMaterialProperty({
dashLength: 20,
color: new Cesium.Color(4 / 255, 251 / 255, 253 / 255),
}),
material: pathMaterial,
// leadTimetrailTime path
leadTime: 0, // 0 path
// trailTime: 0, // 0 path

View File

@ -0,0 +1,17 @@
import { useParams } from "react-router-dom";
import PathLabToQTP from "./PathLabToQTP";
import PathAntarcticaToQTP from "./PathAntarcticaToQTP";
function PointLayout() {
const { type } = useParams();
return type === "1" ? (
<PathLabToQTP />
) : type === "2" ? (
<PathAntarcticaToQTP />
) : (
<></>
);
}
export default PointLayout;

View File

@ -0,0 +1,23 @@
const xx = [
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,
];
//
function HeatFlux() {
return "heatFlux";
}
export default HeatFlux;

View File

@ -0,0 +1,23 @@
const xx = [
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,
];
//
function Rain() {
return "xx";
}
export default Rain;

View File

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

View File

@ -0,0 +1,5 @@
function Site() {
return "";
}
export default Site;

View File

@ -1,10 +1,13 @@
import { Entity, PolylineGraphics, useCesium } from "resium";
import { Cartesian3 } from "cesium";
import { useParams } from "react-router-dom";
import { min } from "lodash-es";
function Updraft() {
const { viewer } = useCesium();
// const { startTime, shouldAnimate } = viewer.clock;
const { type } = useParams();
if (type !== "1") return <></>;
return (
<Entity
id={"Updraft"}
@ -13,31 +16,17 @@ function Updraft() {
<PolylineGraphics
positions={
new Cesium.CallbackProperty(function (time, result) {
const { currentTime, startTime, shouldAnimate } = viewer.clock;
if (!shouldAnimate)
return Cesium.Cartesian3.fromDegreesArrayHeights(
[-55, 58, 0, -55, 58, 0],
Cesium.Ellipsoid.WGS84,
result
);
const { currentTime, startTime } = viewer.clock;
const passTime = currentTime.secondsOfDay - startTime.secondsOfDay;
const height = 100000 * passTime;
if (passTime <= 10) {
return Cesium.Cartesian3.fromDegreesArrayHeights(
[-55, 58, 0, -55, 58, height],
Cesium.Ellipsoid.WGS84,
result
);
} else if (passTime > 10) {
return Cesium.Cartesian3.fromDegreesArrayHeights(
[-55, 58, 0, -55, 58, 1000000],
Cesium.Ellipsoid.WGS84,
result
);
}
return Cesium.Cartesian3.fromDegreesArrayHeights(
[-55, 58, 0, -55, 58, min([height, 1000000])],
Cesium.Ellipsoid.WGS84,
result
);
}, false)
}
width={20}
width={30}
material={new Cesium.PolylineArrowMaterialProperty(Cesium.Color.RED)}
/>
</Entity>

View File

@ -11,11 +11,11 @@ function WavePoint({
maxR = 3600 * 100,
}) {
const data = {
stationLon, //
stationLat, //
value, //
deviationR, //
eachInterval, //
stationLon, //
stationLat, //
value, //
deviationR, //
eachInterval, //
imageUrl: wave,
maxR,
};

View File

@ -0,0 +1,27 @@
import { Fragment } from "react";
import { useParams } from "react-router-dom";
import Wavepoint from "./Wavepoint";
function WavePoint() {
const { type } = useParams();
//
if (type === "1")
return (
<Fragment>
<Wavepoint stationLon={-55} stationLat={58} />
<Wavepoint stationLon={88} stationLat={32.5} />
</Fragment>
);
//
else if (type === "2")
return (
<Fragment>
<Wavepoint stationLon={88} stationLat={-85} />
<Wavepoint stationLon={88} stationLat={32.5} />
</Fragment>
);
else return <></>;
}
export default WavePoint;

View File

@ -38,7 +38,7 @@ function SstAnnomary() {
data: ["ERSST_lancozs", "JRA55_lancozs"],
textStyle: { color: "#04fbfd", cursor: "point" },
},
animationDuration: 3000,
animationDuration: years.length * 1000,
animationEasing: "cubicInOut",
grid: {
left: "3%",

View File

@ -35,9 +35,10 @@ const colorBar = [
"#ee2529",
];
function legend() {
function LegendLab() {
return (
<div className={styles.legend}>
<div className="legend-title">拉布拉多海海表温度夏季年代际异常值</div>
<div className="colorbar">
{colorBar.map((color, index) => {
return (
@ -45,12 +46,16 @@ function legend() {
key={`colorbar-item-${index}`}
className="colorbar-item"
style={{ backgroundColor: color }}
title={`${(-3.2 + index * 0.2).toFixed(1)}~${(
-3.2 +
(index + 1) * 0.2
).toFixed(1)}`}
/>
);
})}
</div>
<div className="legend-text">
{[2.4, -1.6, -0.8, 0, 0.8, 1.6, 2.4].map((item, index) => {
{[-2.4, -1.6, -0.8, 0, 0.8, 1.6, 2.4, ""].map((item, index) => {
return (
<div key={`legend-text-item-${index}`} className="legend-text-item">
{item}
@ -62,4 +67,4 @@ function legend() {
);
}
export default legend;
export default LegendLab;

View File

@ -0,0 +1,64 @@
import styles from "./index.module.less";
// 4.5
const colorBar45 = [
"#7272ff",
"#8585ff",
"#fff",
"#ffafaf",
"#ff9c9c",
"#ff8787",
"#ff7474",
"#ff6060",
"#ff4b4b",
"#ff3838",
"#ff2323",
];
const legendText45 = [
-0.02,
-0.01,
0.01,
0.02,
0.03,
0.05,
0.1,
0.15,
0.2,
0.25,
"",
];
function Legend45() {
return (
<div className={styles.legend}>
<div className="legend-title">三极联动影响东亚夏季风</div>
<div className="colorbar">
{colorBar45.map((color, index) => {
return (
<div
key={`colorbar-item-${index}`}
className="colorbar-item"
style={{ backgroundColor: color }}
title={`${(-3.2 + index * 0.2).toFixed(1)}~${(
-3.2 +
(index + 1) * 0.2
).toFixed(1)}`}
/>
);
})}
</div>
<div className="legend-text">
{legendText45.map((item, index) => {
return (
<div key={`legend-text-item-${index}`} className="legend-text-item">
{item}
</div>
);
})}
</div>
</div>
);
}
export default Legend45;

View File

@ -0,0 +1,13 @@
import { useParams } from "react-router-dom";
import Legend41 from "./Legend41";
import Legend45 from "./Legend45";
function Legends() {
const { type } = useParams();
if (type === "1") return <Legend41 />;
else if (type === "5") return <Legend45 />;
else return <></>;
}
export default Legends;

View File

@ -0,0 +1,54 @@
.legend :global {
position: absolute;
bottom: 40px;
width: 50%;
left: 25%;
// height: 40px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
background-color: #1f485690;
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-radius: 8px;
border: 1px black solid;
&:not(:nth-child(1)) {
border-left: none;
}
}
}
.legend-text {
display: flex;
justify-content: space-evenly;
width: 100%;
height: 20px;
margin-left: 8px;
.legend-text-item {
flex: 1;
text-align: right;
font-weight: 600;
color: white;
-webkit-text-stroke: #04fbfd 1px;
}
}
}

View File

@ -1,11 +1,10 @@
import { Viewer } from "resium";
import { Viewer, Scene } from "resium";
import CustomClock from "./CustomClock";
import CustomFlyTo from "./CustomFlyTo";
import CustomToolbar from "./CustomToolbar";
import InfoLayout from "./InfoLayout";
import Picker from "./Picker";
import Legend from "./Legend";
import AntarcticaPolygon from "./Entities/AntarcticaPolygon";
import Legend from "./Legends";
import Barotropic from "./Entities/Barotorpic";
import Cyclone from "./Entities/Cyclone";
import Point from "./Entities/Point";
@ -13,44 +12,42 @@ import PlateauPolygon from "./Entities/PlateauPolygon";
import Updraft from "./Entities/Udraft";
import Watervapor from "./Entities/Watervapor";
import WavePoint from "./Entities/WavePoint";
import DynamicImageryLayer from "./DynamicImageryLayer";
import Circles from "./Entities/Circles";
import Site from "./Entities/Site";
import styles from "./index.module.less";
//
let start = Cesium.JulianDate.fromDate(new Date());
//
let stop = Cesium.JulianDate.addSeconds(start, 60, new Cesium.JulianDate());
const token = "41222ba4e90e51b5c90d08c329a55faa";
function MapLayout() {
return (
<Viewer
className={styles.cesiumContainer}
full
// infoBox={false}
// baseLayerPicker={false}
// timeline={true}
homeButton={false}
// fullscreenButton={false}
sceneModePicker={false}
// navigationInstructionsInitiallyVisible={false}
navigationHelpButton={false}
// animation={false}
shouldAnimate={true}
// infoBox={false}
timeline={false}
fullscreenButton={false}
geocoder={false}
baseLayerPicker={false}
>
<CustomClock start={start} stop={stop} />
{/* <CustomFlyTo /> */}
<CustomClock />
<CustomFlyTo />
<CustomToolbar />
<Point start={start} stop={stop} />
<Point />
<PlateauPolygon />
<AntarcticaPolygon />
<WavePoint stationLon={-55} stationLat={58} />
<InfoLayout />
<Cyclone />
<Barotropic />
{/* <Watervapor /> */}
<WavePoint />
<Updraft />
<Picker />
{/* <Legend /> */}
<Legend />
<DynamicImageryLayer />
<Circles />
<Site />
</Viewer>
);
}

View File

@ -78,45 +78,3 @@
}
}
}
.legend :global {
position: absolute;
bottom: 100px;
width: 100%;
height: 40px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
.colorbar {
width: 50%;
height: 40px;
display: flex;
.colorbar-item {
flex: 1;
height: 100%;
// border-radius: 8px;
border: 1px black solid;
&:not(:nth-child(1)) {
border-left: none;
}
}
}
.legend-text {
display: flex;
justify-content: space-evenly;
width: 50%;
height: 20px;
.legend-text-item {
flex: 1;
text-align: center;
color: white;
}
}
}

View File

@ -1,7 +1,12 @@
export const data = {
state: {
showSite: false,
toolbar: {
showPanel: true,
showPanel: undefined,
},
imageLayer: {
labrador: undefined,
indianOcean: undefined,
},
},
reducers: {
@ -12,6 +17,10 @@ export const data = {
const { toolbar } = state;
return { ...state, toolbar: { ...toolbar, ...payload } };
},
updateImageLayer(state, payload) {
const { imageLayer } = state;
return { ...state, imageLayer: { ...imageLayer, ...payload } };
},
},
effects: (dispatch) => ({}),
};