fix fix fix fix
This commit is contained in:
parent
4b20c94b70
commit
7c920eb81e
13212
package-lock.json
generated
13212
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -6,7 +6,6 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@emotion/react": "^11.8.2",
|
"@emotion/react": "^11.8.2",
|
||||||
"@emotion/styled": "^11.8.1",
|
"@emotion/styled": "^11.8.1",
|
||||||
"@esbuild/win32-x64": "^0.25.3",
|
|
||||||
"@hello-pangea/dnd": "^18.0.1",
|
"@hello-pangea/dnd": "^18.0.1",
|
||||||
"@mui/icons-material": "^6.1.6",
|
"@mui/icons-material": "^6.1.6",
|
||||||
"@mui/lab": "^6.0.0-beta.14",
|
"@mui/lab": "^6.0.0-beta.14",
|
||||||
|
@ -3,6 +3,7 @@ import { Component, ReactNode, useEffect, useState } from "react";
|
|||||||
import { useTransform } from "./TransformContext";
|
import { useTransform } from "./TransformContext";
|
||||||
import { useMapData } from "./MapDataContext";
|
import { useMapData } from "./MapDataContext";
|
||||||
import { SCALE_FACTOR } from "./Constants";
|
import { SCALE_FACTOR } from "./Constants";
|
||||||
|
import { useApplication } from "@pixi/react";
|
||||||
|
|
||||||
class ErrorBoundary extends Component<{ children: ReactNode }, { hasError: boolean }> {
|
class ErrorBoundary extends Component<{ children: ReactNode }, { hasError: boolean }> {
|
||||||
state = { hasError: false };
|
state = { hasError: false };
|
||||||
@ -22,14 +23,27 @@ class ErrorBoundary extends Component<{ children: ReactNode }, { hasError: boole
|
|||||||
|
|
||||||
|
|
||||||
export function InfiniteCanvas({children} : Readonly<{children?: ReactNode}>) {
|
export function InfiniteCanvas({children} : Readonly<{children?: ReactNode}>) {
|
||||||
const { position, setPosition, scale, setScale, rotation, setRotation, applicationRef, getCenter } = useTransform();
|
const { position, setPosition, scale, setScale, rotation, setRotation, setScreenCenter, screenCenter } = useTransform();
|
||||||
const { routeData, originalRouteData } = useMapData();
|
const { routeData, originalRouteData } = useMapData();
|
||||||
|
|
||||||
|
const applicationRef = useApplication();
|
||||||
|
|
||||||
const [isDragging, setIsDragging] = useState(false);
|
const [isDragging, setIsDragging] = useState(false);
|
||||||
const [startMousePosition, setStartMousePosition] = useState({ x: 0, y: 0 });
|
const [startMousePosition, setStartMousePosition] = useState({ x: 0, y: 0 });
|
||||||
const [startRotation, setStartRotation] = useState(0);
|
const [startRotation, setStartRotation] = useState(0);
|
||||||
const [startPosition, setStartPosition] = useState({ x: 0, y: 0 });
|
const [startPosition, setStartPosition] = useState({ x: 0, y: 0 });
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const canvas = applicationRef?.app.canvas;
|
||||||
|
if (!canvas) return;
|
||||||
|
const canvasRect = canvas.getBoundingClientRect();
|
||||||
|
const canvasLeft = canvasRect?.left ?? 0;
|
||||||
|
const canvasTop = canvasRect?.top ?? 0;
|
||||||
|
const centerX = window.innerWidth / 2 - canvasLeft;
|
||||||
|
const centerY = window.innerHeight / 2 - canvasTop;
|
||||||
|
setScreenCenter({x: centerX, y: centerY});
|
||||||
|
}, [applicationRef?.app.canvas, window.innerWidth, window.innerHeight]);
|
||||||
|
|
||||||
const handlePointerDown = (e: FederatedMouseEvent) => {
|
const handlePointerDown = (e: FederatedMouseEvent) => {
|
||||||
setIsDragging(true);
|
setIsDragging(true);
|
||||||
setStartPosition({
|
setStartPosition({
|
||||||
@ -53,7 +67,7 @@ export function InfiniteCanvas({children} : Readonly<{children?: ReactNode}>) {
|
|||||||
if (!isDragging) return;
|
if (!isDragging) return;
|
||||||
|
|
||||||
if (e.shiftKey) {
|
if (e.shiftKey) {
|
||||||
const center = getCenter();
|
const center = screenCenter ?? {x: 0, y: 0};
|
||||||
const startAngle = Math.atan2(startMousePosition.y - center.y, startMousePosition.x - center.x);
|
const startAngle = Math.atan2(startMousePosition.y - center.y, startMousePosition.x - center.x);
|
||||||
const currentAngle = Math.atan2(e.globalY - center.y, e.globalX - center.x);
|
const currentAngle = Math.atan2(e.globalY - center.y, e.globalX - center.x);
|
||||||
|
|
||||||
@ -117,17 +131,17 @@ export function InfiniteCanvas({children} : Readonly<{children?: ReactNode}>) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
applicationRef?.current?.getApplication()?.render();
|
applicationRef?.app.render();
|
||||||
console.log(position, scale, rotation);
|
console.log(position, scale, rotation);
|
||||||
}, [position, scale, rotation]);
|
}, [position, scale, rotation]);
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ErrorBoundary>
|
<ErrorBoundary>
|
||||||
{applicationRef?.current && (
|
{applicationRef?.app && (
|
||||||
<pixiGraphics
|
<pixiGraphics
|
||||||
draw={(g) => {
|
draw={(g) => {
|
||||||
const canvas = applicationRef.current!.getCanvas();
|
const canvas = applicationRef.app.canvas;
|
||||||
g.clear();
|
g.clear();
|
||||||
g.rect(0, 0, canvas?.width ?? 0, canvas?.height ?? 0);
|
g.rect(0, 0, canvas?.width ?? 0, canvas?.height ?? 0);
|
||||||
g.fill("#111");
|
g.fill("#111");
|
||||||
@ -154,7 +168,7 @@ export function InfiniteCanvas({children} : Readonly<{children?: ReactNode}>) {
|
|||||||
|
|
||||||
draw={(g) => {
|
draw={(g) => {
|
||||||
g.clear();
|
g.clear();
|
||||||
const center = getCenter();
|
const center = screenCenter ?? {x: 0, y: 0};
|
||||||
g.circle(center.x, center.y, 1);
|
g.circle(center.x, center.y, 1);
|
||||||
g.fill("#fff");
|
g.fill("#fff");
|
||||||
}}
|
}}
|
||||||
|
@ -6,7 +6,7 @@ import { coordinatesToLocal, localToCoordinates } from "./utils";
|
|||||||
|
|
||||||
export function RightSidebar() {
|
export function RightSidebar() {
|
||||||
const { routeData, setScaleRange, saveChanges, originalRouteData, setMapRotation, setMapCenter } = useMapData();
|
const { routeData, setScaleRange, saveChanges, originalRouteData, setMapRotation, setMapCenter } = useMapData();
|
||||||
const { rotation, position, screenToLocal, getCenter, rotateToAngle, setTransform } = useTransform();
|
const { rotation, position, screenToLocal, screenCenter, rotateToAngle, setTransform } = useTransform();
|
||||||
const [minScale, setMinScale] = useState<number>(1);
|
const [minScale, setMinScale] = useState<number>(1);
|
||||||
const [maxScale, setMaxScale] = useState<number>(10);
|
const [maxScale, setMaxScale] = useState<number>(10);
|
||||||
const [localCenter, setLocalCenter] = useState<{x: number, y: number}>({x: 0, y: 0});
|
const [localCenter, setLocalCenter] = useState<{x: number, y: number}>({x: 0, y: 0});
|
||||||
@ -36,7 +36,7 @@ export function RightSidebar() {
|
|||||||
}, [rotationDegrees]);
|
}, [rotationDegrees]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const center = getCenter();
|
const center = screenCenter ?? {x: 0, y: 0};
|
||||||
const localCenter = screenToLocal(center.x, center.y);
|
const localCenter = screenToLocal(center.x, center.y);
|
||||||
const coordinates = localToCoordinates(localCenter.x, localCenter.y);
|
const coordinates = localToCoordinates(localCenter.x, localCenter.y);
|
||||||
setLocalCenter({x: coordinates.latitude, y: coordinates.longitude});
|
setLocalCenter({x: coordinates.latitude, y: coordinates.longitude});
|
||||||
|
@ -1,7 +1,4 @@
|
|||||||
import { createContext, ReactNode, RefObject, useContext, useMemo, useRef, useState } from "react";
|
import { createContext, ReactNode, useContext, useMemo, useState } from "react";
|
||||||
import {
|
|
||||||
ApplicationRef
|
|
||||||
} from '@pixi/react';
|
|
||||||
import { SCALE_FACTOR, UP_SCALE } from "./Constants";
|
import { SCALE_FACTOR, UP_SCALE } from "./Constants";
|
||||||
|
|
||||||
|
|
||||||
@ -9,30 +6,29 @@ const TransformContext = createContext<{
|
|||||||
position: { x: number, y: number },
|
position: { x: number, y: number },
|
||||||
scale: number,
|
scale: number,
|
||||||
rotation: number,
|
rotation: number,
|
||||||
applicationRef: RefObject<ApplicationRef> | null,
|
screenCenter?: { x: number, y: number },
|
||||||
|
|
||||||
setPosition: React.Dispatch<React.SetStateAction<{ x: number, y: number }>>,
|
setPosition: React.Dispatch<React.SetStateAction<{ x: number, y: number }>>,
|
||||||
setScale: React.Dispatch<React.SetStateAction<number>>,
|
setScale: React.Dispatch<React.SetStateAction<number>>,
|
||||||
setRotation: React.Dispatch<React.SetStateAction<number>>,
|
setRotation: React.Dispatch<React.SetStateAction<number>>,
|
||||||
screenToLocal: (x: number, y: number) => { x: number, y: number },
|
screenToLocal: (x: number, y: number) => { x: number, y: number },
|
||||||
localToScreen: (x: number, y: number) => { x: number, y: number },
|
localToScreen: (x: number, y: number) => { x: number, y: number },
|
||||||
getCenter: () => { x: number, y: number },
|
|
||||||
rotateToAngle: (to: number, fromPosition?: {x: number, y: number}) => void,
|
rotateToAngle: (to: number, fromPosition?: {x: number, y: number}) => void,
|
||||||
setTransform: (latitude: number, longitude: number, rotationDegrees?: number, scale?: number) => void
|
setTransform: (latitude: number, longitude: number, rotationDegrees?: number, scale?: number) => void,
|
||||||
|
setScreenCenter: React.Dispatch<React.SetStateAction<{ x: number, y: number } | undefined>>
|
||||||
}>({
|
}>({
|
||||||
position: { x: 0, y: 0 },
|
position: { x: 0, y: 0 },
|
||||||
scale: 1,
|
scale: 1,
|
||||||
rotation: 0,
|
rotation: 0,
|
||||||
applicationRef: null,
|
screenCenter: undefined,
|
||||||
|
|
||||||
setPosition: () => {},
|
setPosition: () => {},
|
||||||
setScale: () => {},
|
setScale: () => {},
|
||||||
setRotation: () => {},
|
setRotation: () => {},
|
||||||
screenToLocal: () => ({ x: 0, y: 0 }),
|
screenToLocal: () => ({ x: 0, y: 0 }),
|
||||||
localToScreen: () => ({ x: 0, y: 0 }),
|
localToScreen: () => ({ x: 0, y: 0 }),
|
||||||
getCenter: () => ({ x: 0, y: 0 }),
|
|
||||||
rotateToAngle: () => {},
|
rotateToAngle: () => {},
|
||||||
setTransform: () => {}
|
setTransform: () => {},
|
||||||
|
setScreenCenter: () => {}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Provider component
|
// Provider component
|
||||||
@ -40,7 +36,7 @@ export const TransformProvider = ({ children }: { children: ReactNode }) => {
|
|||||||
const [position, setPosition] = useState({ x: 0, y: 0 });
|
const [position, setPosition] = useState({ x: 0, y: 0 });
|
||||||
const [scale, setScale] = useState(1);
|
const [scale, setScale] = useState(1);
|
||||||
const [rotation, setRotation] = useState(0);
|
const [rotation, setRotation] = useState(0);
|
||||||
const applicationRef = useRef<ApplicationRef>(null);
|
const [screenCenter, setScreenCenter] = useState<{x: number, y: number}>();
|
||||||
|
|
||||||
function screenToLocal(screenX: number, screenY: number) {
|
function screenToLocal(screenX: number, screenY: number) {
|
||||||
// Translate point relative to current pan position
|
// Translate point relative to current pan position
|
||||||
@ -79,21 +75,13 @@ export const TransformProvider = ({ children }: { children: ReactNode }) => {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function getCenter() {
|
|
||||||
const canvas = applicationRef?.current?.getCanvas();
|
|
||||||
const canvasRect = canvas?.getBoundingClientRect();
|
|
||||||
const canvasLeft = canvasRect?.left ?? 0;
|
|
||||||
const canvasTop = canvasRect?.top ?? 0;
|
|
||||||
const centerX = window.innerWidth / 2 - canvasLeft;
|
|
||||||
const centerY = window.innerHeight / 2 - canvasTop;
|
|
||||||
return {x: centerX, y: centerY};
|
|
||||||
}
|
|
||||||
|
|
||||||
function rotateToAngle(to: number, fromPosition?: {x: number, y: number}) {
|
function rotateToAngle(to: number, fromPosition?: {x: number, y: number}) {
|
||||||
setRotation(to);
|
setRotation(to);
|
||||||
const rotationDiff = to - rotation;
|
const rotationDiff = to - rotation;
|
||||||
|
|
||||||
const center = getCenter();
|
const center = screenCenter ?? {x: 0, y: 0};
|
||||||
const cosDelta = Math.cos(rotationDiff);
|
const cosDelta = Math.cos(rotationDiff);
|
||||||
const sinDelta = Math.sin(rotationDiff);
|
const sinDelta = Math.sin(rotationDiff);
|
||||||
|
|
||||||
@ -108,7 +96,7 @@ export const TransformProvider = ({ children }: { children: ReactNode }) => {
|
|||||||
function setTransform(latitude: number, longitude: number, rotationDegrees?: number, useScale ?: number) {
|
function setTransform(latitude: number, longitude: number, rotationDegrees?: number, useScale ?: number) {
|
||||||
const selectedRotation = rotationDegrees ? (rotationDegrees * Math.PI / 180) : rotation;
|
const selectedRotation = rotationDegrees ? (rotationDegrees * Math.PI / 180) : rotation;
|
||||||
const selectedScale = useScale ? useScale/SCALE_FACTOR : scale;
|
const selectedScale = useScale ? useScale/SCALE_FACTOR : scale;
|
||||||
const center = getCenter();
|
const center = screenCenter ?? {x: 0, y: 0};
|
||||||
console.log("center", center.x, center.y);
|
console.log("center", center.x, center.y);
|
||||||
const newPosition = {
|
const newPosition = {
|
||||||
x: -latitude * UP_SCALE * selectedScale,
|
x: -latitude * UP_SCALE * selectedScale,
|
||||||
@ -134,16 +122,16 @@ export const TransformProvider = ({ children }: { children: ReactNode }) => {
|
|||||||
position,
|
position,
|
||||||
scale,
|
scale,
|
||||||
rotation,
|
rotation,
|
||||||
applicationRef,
|
screenCenter,
|
||||||
getCenter,
|
|
||||||
setPosition,
|
setPosition,
|
||||||
setScale,
|
setScale,
|
||||||
setRotation,
|
setRotation,
|
||||||
rotateToAngle,
|
rotateToAngle,
|
||||||
screenToLocal,
|
screenToLocal,
|
||||||
localToScreen,
|
localToScreen,
|
||||||
setTransform
|
setTransform,
|
||||||
}), [position, scale, rotation, applicationRef]);
|
setScreenCenter
|
||||||
|
}), [position, scale, rotation, screenCenter]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TransformContext.Provider value={value}>
|
<TransformContext.Provider value={value}>
|
||||||
|
@ -2,6 +2,7 @@ import { useRef, useEffect, useState } from "react";
|
|||||||
|
|
||||||
import {
|
import {
|
||||||
Application,
|
Application,
|
||||||
|
ApplicationRef,
|
||||||
extend
|
extend
|
||||||
} from '@pixi/react';
|
} from '@pixi/react';
|
||||||
import {
|
import {
|
||||||
@ -54,7 +55,7 @@ export const RoutePreview = () => {
|
|||||||
|
|
||||||
|
|
||||||
export function RouteMap() {
|
export function RouteMap() {
|
||||||
const { applicationRef, setPosition, screenToLocal, setTransform } = useTransform();
|
const { setPosition, screenToLocal, setTransform, screenCenter } = useTransform();
|
||||||
const {
|
const {
|
||||||
routeData, stationData, sightData, originalRouteData
|
routeData, stationData, sightData, originalRouteData
|
||||||
} = useMapData();
|
} = useMapData();
|
||||||
@ -72,10 +73,12 @@ export function RouteMap() {
|
|||||||
}, [originalRouteData]);
|
}, [originalRouteData]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if(!applicationRef?.current?.getCanvas() || isSetup) {
|
if(isSetup || !screenCenter) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log("Use effect fired")
|
||||||
|
|
||||||
if (
|
if (
|
||||||
originalRouteData?.center_latitude === originalRouteData?.center_longitude &&
|
originalRouteData?.center_latitude === originalRouteData?.center_longitude &&
|
||||||
originalRouteData?.center_latitude === 0
|
originalRouteData?.center_latitude === 0
|
||||||
@ -96,6 +99,7 @@ export function RouteMap() {
|
|||||||
y: -(boundingBox.from.y + boundingBox.to.y) / 2
|
y: -(boundingBox.from.y + boundingBox.to.y) / 2
|
||||||
};
|
};
|
||||||
setPosition(newCenter);
|
setPosition(newCenter);
|
||||||
|
console.log("Taking easy way out", originalRouteData)
|
||||||
setIsSetup(true);
|
setIsSetup(true);
|
||||||
}
|
}
|
||||||
} else if (
|
} else if (
|
||||||
@ -103,15 +107,18 @@ export function RouteMap() {
|
|||||||
originalRouteData?.center_longitude
|
originalRouteData?.center_longitude
|
||||||
) {
|
) {
|
||||||
const coordinates = coordinatesToLocal(originalRouteData?.center_latitude, originalRouteData?.center_longitude);
|
const coordinates = coordinatesToLocal(originalRouteData?.center_latitude, originalRouteData?.center_longitude);
|
||||||
|
|
||||||
setTransform(
|
setTransform(
|
||||||
coordinates.x,
|
coordinates.x,
|
||||||
coordinates.y,
|
coordinates.y,
|
||||||
originalRouteData?.rotate,
|
originalRouteData?.rotate,
|
||||||
originalRouteData?.scale_min
|
originalRouteData?.scale_min
|
||||||
);
|
);
|
||||||
|
console.log("Setup complete")
|
||||||
setIsSetup(true);
|
setIsSetup(true);
|
||||||
}
|
}
|
||||||
}, [points, originalRouteData?.center_latitude, originalRouteData?.center_longitude, originalRouteData?.rotate, applicationRef?.current?.getCanvas(), isSetup]);
|
}, [points, originalRouteData?.center_latitude, originalRouteData?.center_longitude, originalRouteData?.rotate, isSetup, screenCenter]);
|
||||||
|
|
||||||
|
|
||||||
if (!routeData || !stationData || !sightData) {
|
if (!routeData || !stationData || !sightData) {
|
||||||
console.error("routeData, stationData or sightData is null");
|
console.error("routeData, stationData or sightData is null");
|
||||||
@ -122,7 +129,6 @@ export function RouteMap() {
|
|||||||
return (
|
return (
|
||||||
<div style={{width: "100%", height:"100%"}} ref={parentRef}>
|
<div style={{width: "100%", height:"100%"}} ref={parentRef}>
|
||||||
<Application
|
<Application
|
||||||
ref={applicationRef}
|
|
||||||
resizeTo={parentRef}
|
resizeTo={parentRef}
|
||||||
background="#fff"
|
background="#fff"
|
||||||
>
|
>
|
||||||
|
Loading…
Reference in New Issue
Block a user