197 lines
5.5 KiB
TypeScript
197 lines
5.5 KiB
TypeScript
import { useRef, useEffect, useState } from "react";
|
|
import { Widgets } from "./Widgets";
|
|
import { extend } from "@pixi/react";
|
|
import {
|
|
Container,
|
|
Graphics,
|
|
Sprite,
|
|
Texture,
|
|
TilingSprite,
|
|
Text,
|
|
} from "pixi.js";
|
|
import { Box, Stack } from "@mui/material";
|
|
import { MapDataProvider, useMapData } from "./MapDataContext";
|
|
import { TransformProvider, useTransform } from "./TransformContext";
|
|
|
|
import { LeftSidebar } from "./LeftSidebar";
|
|
import { RightSidebar } from "./RightSidebar";
|
|
|
|
import { coordinatesToLocal } from "./utils";
|
|
import { observer } from "mobx-react-lite";
|
|
import { UP_SCALE } from "./Constants";
|
|
import { WebGLRouteMapPrototype } from "./webgl-prototype/WebGLRouteMapPrototype";
|
|
import { CircularProgress } from "@mui/material";
|
|
|
|
extend({
|
|
Container,
|
|
Graphics,
|
|
Sprite,
|
|
Texture,
|
|
TilingSprite,
|
|
Text,
|
|
});
|
|
|
|
const Loading = () => {
|
|
const { isRouteLoading, isStationLoading, isSightLoading } = useMapData();
|
|
|
|
if (isRouteLoading || isStationLoading || isSightLoading) {
|
|
return (
|
|
<div className="fixed flex z-1000000000 items-center justify-center h-screen w-screen bg-[#111]">
|
|
<CircularProgress />
|
|
</div>
|
|
);
|
|
}
|
|
|
|
return null;
|
|
};
|
|
export const RoutePreview = () => {
|
|
const [isLeftSidebarOpen, setIsLeftSidebarOpen] = useState(true);
|
|
return (
|
|
<MapDataProvider>
|
|
<TransformProvider>
|
|
<Stack direction="row" height="100vh" width="100vw" overflow="hidden">
|
|
<Loading />
|
|
<Box
|
|
sx={{
|
|
position: "relative",
|
|
width: isLeftSidebarOpen ? 300 : 0,
|
|
transition: "width 0.3s ease",
|
|
overflow: "visible",
|
|
height: "100%",
|
|
bgcolor: "primary.main",
|
|
borderRight: isLeftSidebarOpen
|
|
? "1px solid rgba(255,255,255,0.08)"
|
|
: "none",
|
|
display: "flex",
|
|
justifyContent: "flex-start",
|
|
flexShrink: 0,
|
|
}}
|
|
>
|
|
<LeftSidebar
|
|
open={isLeftSidebarOpen}
|
|
onToggle={() => setIsLeftSidebarOpen((prev) => !prev)}
|
|
/>
|
|
</Box>
|
|
<Stack direction="row" flex={1} position="relative" height="100%">
|
|
<RouteMap />
|
|
<Widgets />
|
|
<RightSidebar />
|
|
</Stack>
|
|
</Stack>
|
|
</TransformProvider>
|
|
</MapDataProvider>
|
|
);
|
|
};
|
|
|
|
export const RouteMap = observer(() => {
|
|
const { setPosition, setTransform, screenCenter } = useTransform();
|
|
const { routeData, stationData, sightData, originalRouteData } = useMapData();
|
|
|
|
const [points, setPoints] = useState<{ x: number; y: number }[]>([]);
|
|
const [isSetup, setIsSetup] = useState(false);
|
|
|
|
const parentRef = useRef<HTMLDivElement>(null);
|
|
|
|
useEffect(() => {
|
|
document.body.style.overflow = "hidden";
|
|
return () => {
|
|
document.body.style.overflow = "auto";
|
|
};
|
|
}, []);
|
|
|
|
useEffect(() => {
|
|
if (originalRouteData) {
|
|
const path = originalRouteData?.path;
|
|
const points =
|
|
path?.map(([x, y]: [number, number]) => ({
|
|
x: x * UP_SCALE,
|
|
y: y * UP_SCALE,
|
|
})) ?? [];
|
|
setPoints(points);
|
|
}
|
|
}, [originalRouteData]);
|
|
|
|
useEffect(() => {
|
|
if (isSetup || !screenCenter) {
|
|
return;
|
|
}
|
|
|
|
if (
|
|
originalRouteData?.center_latitude ===
|
|
originalRouteData?.center_longitude &&
|
|
originalRouteData?.center_latitude === 0
|
|
) {
|
|
if (points.length > 0) {
|
|
let boundingBox = {
|
|
from: { x: Infinity, y: Infinity },
|
|
to: { x: -Infinity, y: -Infinity },
|
|
};
|
|
for (const point of points) {
|
|
boundingBox.from.x = Math.min(boundingBox.from.x, point.x);
|
|
boundingBox.from.y = Math.min(boundingBox.from.y, point.y);
|
|
boundingBox.to.x = Math.max(boundingBox.to.x, point.x);
|
|
boundingBox.to.y = Math.max(boundingBox.to.y, point.y);
|
|
}
|
|
const newCenter = {
|
|
x: -(boundingBox.from.x + boundingBox.to.x) / 2,
|
|
y: -(boundingBox.from.y + boundingBox.to.y) / 2,
|
|
};
|
|
setPosition(newCenter);
|
|
setIsSetup(true);
|
|
}
|
|
} else if (
|
|
originalRouteData?.center_latitude &&
|
|
originalRouteData?.center_longitude
|
|
) {
|
|
const coordinates = coordinatesToLocal(
|
|
originalRouteData?.center_latitude,
|
|
originalRouteData?.center_longitude
|
|
);
|
|
|
|
setTransform(
|
|
coordinates.x,
|
|
coordinates.y,
|
|
originalRouteData?.rotate,
|
|
originalRouteData?.scale_min
|
|
);
|
|
setIsSetup(true);
|
|
}
|
|
}, [
|
|
points,
|
|
originalRouteData?.center_latitude,
|
|
originalRouteData?.center_longitude,
|
|
originalRouteData?.rotate,
|
|
isSetup,
|
|
screenCenter,
|
|
]);
|
|
|
|
if (!routeData || !stationData || !sightData) {
|
|
return null;
|
|
}
|
|
|
|
return (
|
|
<div style={{ width: "100%", height: "100%" }} ref={parentRef}>
|
|
{/* <Application resizeTo={parentRef} background="#000" preference="webgl">
|
|
<InfiniteCanvas>
|
|
<TravelPath points={points} />
|
|
{stationData[language].map((obj, index) => (
|
|
<Station
|
|
station={obj}
|
|
key={obj.id}
|
|
ruLabel={
|
|
language === "ru"
|
|
? stationData.ru[index].name
|
|
: stationData.ru[index].name
|
|
}
|
|
/>
|
|
))}
|
|
{originalSightData?.map((sight: SightData, index: number) => {
|
|
return <Sight sight={sight} id={index} key={sight.id} />;
|
|
})}
|
|
</InfiniteCanvas>
|
|
</Application> */}
|
|
<WebGLRouteMapPrototype />
|
|
</div>
|
|
);
|
|
});
|