feat: Move route-preview
This commit is contained in:
148
src/pages/Route/route-preview/Station.tsx
Normal file
148
src/pages/Route/route-preview/Station.tsx
Normal file
@ -0,0 +1,148 @@
|
||||
import { FederatedMouseEvent, Graphics } from "pixi.js";
|
||||
import {
|
||||
BACKGROUND_COLOR,
|
||||
PATH_COLOR,
|
||||
STATION_RADIUS,
|
||||
STATION_OUTLINE_WIDTH,
|
||||
UP_SCALE,
|
||||
} from "./Constants";
|
||||
import { useTransform } from "./TransformContext";
|
||||
import { useCallback, useEffect, useRef, useState } from "react";
|
||||
import { StationData } from "./types";
|
||||
import { useMapData } from "./MapDataContext";
|
||||
import { coordinatesToLocal } from "./utils";
|
||||
import { observer } from "mobx-react-lite";
|
||||
import { languageStore } from "@shared";
|
||||
|
||||
interface StationProps {
|
||||
station: StationData;
|
||||
ruLabel: string | null;
|
||||
}
|
||||
|
||||
export const Station = observer(
|
||||
({ station, ruLabel }: Readonly<StationProps>) => {
|
||||
const draw = useCallback((g: Graphics) => {
|
||||
g.clear();
|
||||
const coordinates = coordinatesToLocal(
|
||||
station.latitude,
|
||||
station.longitude
|
||||
);
|
||||
g.circle(
|
||||
coordinates.x * UP_SCALE,
|
||||
coordinates.y * UP_SCALE,
|
||||
STATION_RADIUS
|
||||
);
|
||||
g.fill({ color: PATH_COLOR });
|
||||
g.stroke({ color: BACKGROUND_COLOR, width: STATION_OUTLINE_WIDTH });
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<pixiContainer>
|
||||
<pixiGraphics draw={draw} />
|
||||
<StationLabel station={station} ruLabel={ruLabel} />
|
||||
</pixiContainer>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
export const StationLabel = observer(
|
||||
({ station, ruLabel }: Readonly<StationProps>) => {
|
||||
const { language } = languageStore;
|
||||
const { rotation, scale } = useTransform();
|
||||
const { setStationOffset } = useMapData();
|
||||
|
||||
const [position, setPosition] = useState({
|
||||
x: station.offset_x,
|
||||
y: station.offset_y,
|
||||
});
|
||||
const [isDragging, setIsDragging] = useState(false);
|
||||
const [startPosition, setStartPosition] = useState({ x: 0, y: 0 });
|
||||
const [startMousePosition, setStartMousePosition] = useState({
|
||||
x: 0,
|
||||
y: 0,
|
||||
});
|
||||
|
||||
if (!station) {
|
||||
console.error("station is null");
|
||||
return null;
|
||||
}
|
||||
|
||||
const handlePointerDown = (e: FederatedMouseEvent) => {
|
||||
setIsDragging(true);
|
||||
setStartPosition({
|
||||
x: position.x,
|
||||
y: position.y,
|
||||
});
|
||||
setStartMousePosition({
|
||||
x: e.globalX,
|
||||
y: e.globalY,
|
||||
});
|
||||
|
||||
e.stopPropagation();
|
||||
};
|
||||
const handlePointerMove = (e: FederatedMouseEvent) => {
|
||||
if (!isDragging) return;
|
||||
const dx = e.globalX - startMousePosition.x;
|
||||
const dy = e.globalY - startMousePosition.y;
|
||||
const newPosition = {
|
||||
x: startPosition.x + dx,
|
||||
y: startPosition.y + dy,
|
||||
};
|
||||
setPosition(newPosition);
|
||||
setStationOffset(station.id, newPosition.x, newPosition.y);
|
||||
e.stopPropagation();
|
||||
};
|
||||
|
||||
const handlePointerUp = (e: FederatedMouseEvent) => {
|
||||
setIsDragging(false);
|
||||
e.stopPropagation();
|
||||
};
|
||||
const coordinates = coordinatesToLocal(station.latitude, station.longitude);
|
||||
|
||||
return (
|
||||
<pixiContainer
|
||||
eventMode="static"
|
||||
interactive
|
||||
onPointerDown={handlePointerDown}
|
||||
onGlobalPointerMove={handlePointerMove}
|
||||
onPointerUp={handlePointerUp}
|
||||
onPointerUpOutside={handlePointerUp}
|
||||
width={48}
|
||||
height={48}
|
||||
x={coordinates.x * UP_SCALE}
|
||||
y={coordinates.y * UP_SCALE}
|
||||
rotation={-rotation}
|
||||
>
|
||||
<pixiText
|
||||
anchor={{ x: 1, y: 0.5 }}
|
||||
text={station.name}
|
||||
position={{
|
||||
x: position.x / scale + 24,
|
||||
y: position.y / scale,
|
||||
}}
|
||||
style={{
|
||||
fontSize: 26,
|
||||
fontWeight: "bold",
|
||||
fill: "#ffffff",
|
||||
}}
|
||||
/>
|
||||
|
||||
{ruLabel && (
|
||||
<pixiText
|
||||
anchor={{ x: 1, y: -1 }}
|
||||
text={ruLabel}
|
||||
position={{
|
||||
x: position.x / scale + 24,
|
||||
y: position.y / scale,
|
||||
}}
|
||||
style={{
|
||||
fontSize: 16,
|
||||
fontWeight: "bold",
|
||||
fill: "#CCCCCC",
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</pixiContainer>
|
||||
);
|
||||
}
|
||||
);
|
Reference in New Issue
Block a user