feat: Move route-preview
This commit is contained in:
119
src/pages/Route/route-preview/Sight.tsx
Normal file
119
src/pages/Route/route-preview/Sight.tsx
Normal file
@ -0,0 +1,119 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { useTransform } from "./TransformContext";
|
||||
import { SightData } from "./types";
|
||||
import { Assets, FederatedMouseEvent, Graphics, Texture } from "pixi.js";
|
||||
import { COLORS } from "../../contexts/color-mode/theme";
|
||||
import { SIGHT_SIZE, UP_SCALE } from "./Constants";
|
||||
import { coordinatesToLocal, localToCoordinates } from "./utils";
|
||||
import { useMapData } from "./MapDataContext";
|
||||
|
||||
interface SightProps {
|
||||
sight: SightData;
|
||||
id: number;
|
||||
}
|
||||
|
||||
export function Sight({
|
||||
sight, id
|
||||
}: Readonly<SightProps>) {
|
||||
const { rotation, scale } = useTransform();
|
||||
const { setSightCoordinates } = useMapData();
|
||||
|
||||
const [position, setPosition] = useState(coordinatesToLocal(sight.latitude, sight.longitude));
|
||||
const [isDragging, setIsDragging] = useState(false);
|
||||
const [startPosition, setStartPosition] = useState({ x: 0, y: 0 });
|
||||
const [startMousePosition, setStartMousePosition] = useState({ x: 0, y: 0 });
|
||||
|
||||
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) / scale / UP_SCALE;
|
||||
const dy = (e.globalY - startMousePosition.y) / scale / UP_SCALE;
|
||||
const cos = Math.cos(rotation);
|
||||
const sin = Math.sin(rotation);
|
||||
const newPosition = {
|
||||
x: startPosition.x + dx * cos + dy * sin,
|
||||
y: startPosition.y - dx * sin + dy * cos
|
||||
};
|
||||
setPosition(newPosition);
|
||||
const coordinates = localToCoordinates(newPosition.x, newPosition.y);
|
||||
setSightCoordinates(sight.id, coordinates.latitude, coordinates.longitude);
|
||||
e.stopPropagation();
|
||||
};
|
||||
|
||||
const handlePointerUp = (e: FederatedMouseEvent) => {
|
||||
setIsDragging(false);
|
||||
e.stopPropagation();
|
||||
};
|
||||
|
||||
const [texture, setTexture] = useState(Texture.EMPTY);
|
||||
useEffect(() => {
|
||||
if (texture === Texture.EMPTY) {
|
||||
Assets
|
||||
.load('/SightIcon.png')
|
||||
.then((result) => {
|
||||
setTexture(result)
|
||||
});
|
||||
}
|
||||
}, [texture]);
|
||||
|
||||
function draw(g: Graphics) {
|
||||
g.clear();
|
||||
g.circle(0, 0, 20);
|
||||
g.fill({color: COLORS.primary}); // Fill circle with primary color
|
||||
}
|
||||
|
||||
if(!sight) {
|
||||
console.error("sight is null");
|
||||
return null;
|
||||
}
|
||||
|
||||
const coordinates = coordinatesToLocal(sight.latitude, sight.longitude);
|
||||
|
||||
return (
|
||||
<pixiContainer rotation={-rotation}
|
||||
eventMode='static'
|
||||
interactive
|
||||
onPointerDown={handlePointerDown}
|
||||
onGlobalPointerMove={handlePointerMove}
|
||||
onPointerUp={handlePointerUp}
|
||||
onPointerUpOutside={handlePointerUp}
|
||||
x={position.x * UP_SCALE - SIGHT_SIZE/2} // Offset by half width to center
|
||||
y={position.y * UP_SCALE - SIGHT_SIZE/2} // Offset by half height to center
|
||||
>
|
||||
<pixiSprite
|
||||
texture={texture}
|
||||
width={SIGHT_SIZE}
|
||||
height={SIGHT_SIZE}
|
||||
/>
|
||||
<pixiGraphics
|
||||
draw={draw}
|
||||
x={SIGHT_SIZE}
|
||||
y={0}
|
||||
/>
|
||||
<pixiText
|
||||
text={`${id+1}`}
|
||||
x={SIGHT_SIZE+1}
|
||||
y={0}
|
||||
anchor={0.5}
|
||||
|
||||
style={{
|
||||
fontSize: 24,
|
||||
fontWeight: 'bold',
|
||||
fill: "#ffffff",
|
||||
}}
|
||||
/>
|
||||
</pixiContainer>
|
||||
);
|
||||
}
|
Reference in New Issue
Block a user