diff --git a/src/components/map/ZoomPanWrapper.js b/src/components/map/ZoomPanWrapper.js
index b28b95b..2a5295e 100644
--- a/src/components/map/ZoomPanWrapper.js
+++ b/src/components/map/ZoomPanWrapper.js
@@ -3,7 +3,6 @@ import './ZoomPanWrapper.css';
import Constants from '../../helpers/constants';
import { useZoomPanSubscriber, viewBox$, clientRect$, camera$ } from '../../hooks/useZoomPubSub';
import {mapRotation$} from '../../services/mapRotationService';
-import ZoomPanContext from "../../contexts/ZoomPanContext";
import AngleHelper from "../../helpers/angleHelper";
export default function ZoomPanWrapper({children}) {
@@ -91,8 +90,19 @@ export default function ZoomPanWrapper({children}) {
scheduleCameraUpdate();
}, [scheduleCameraUpdate]);
- // Subscribe to any external "center" calls
- useZoomPanSubscriber(centerOn);
+ const alignView = (angleDeg) => {
+ // Find such relative rotation in the range [-45, 45] degrees that aligns the track
+ // with y rotation angleDeg to the X or Y screen axis.
+ const angleDifference = -angleDeg - cameraRef.current.rotation;
+ let deltaAngle = AngleHelper.normalizeDegAngle(angleDifference, 90);
+ if (deltaAngle > 45) deltaAngle -= 90;
+
+ cameraRef.current.rotation += deltaAngle;
+ scheduleCameraUpdate();
+ };
+
+ // Subscribe to any external `center` and `alignView` calls
+ useZoomPanSubscriber(centerOn, alignView);
const onWheel = (e) => {
const { left, top } = clientRectRef.current;
@@ -149,35 +159,21 @@ export default function ZoomPanWrapper({children}) {
isMouseDownRef.current = false;
};
- // `event` could be used in the future to perform the rotation around the click position
- const alignView = (angleDeg, _event) => {
- // Find such relative rotation in the range [-45, 45] degrees that aligns the track
- // with y rotation angleDeg to the X or Y screen axis.
- const angleDifference = -angleDeg - cameraRef.current.rotation;
- let deltaAngle = AngleHelper.normalizeDegAngle(angleDifference, 90);
- if (deltaAngle > 45) deltaAngle -= 90;
-
- cameraRef.current.rotation += deltaAngle;
- scheduleCameraUpdate();
- };
-
return (
-
-
-
-
-
+
+
+
);
}
diff --git a/src/components/map/object-renderers/TrackRenderer.js b/src/components/map/object-renderers/TrackRenderer.js
index 9c67e4a..6a7496b 100644
--- a/src/components/map/object-renderers/TrackRenderer.js
+++ b/src/components/map/object-renderers/TrackRenderer.js
@@ -3,18 +3,18 @@ import SettingsContext from "../../../contexts/SettingsContext";
import Constants from "../../../helpers/constants";
import {ElectrificationStatus} from "../../../model/electrification-status";
import {setHoveredTrack, unsetHoveredTrack} from "../../../services/trackHoverInfoService";
-import ZoomPanContext from "../../../contexts/ZoomPanContext";
import GradientsContext from "../../../contexts/GradientsContext";
import MiscHelper from "../../../helpers/miscHelper";
+import {useZoomPanEmitter} from "../../../hooks/useZoomPubSub";
export default function TrackRenderer(props) {
const {object} = props;
const {trackColorMode} = useContext(SettingsContext);
const {gradientDefs} = useContext(GradientsContext);
- const {alignView} = useContext(ZoomPanContext);
+ const { alignView } = useZoomPanEmitter();
- const onAlign = (event) => {
- alignView(object.rot.y, event);
+ const onAlign = () => {
+ alignView(object.rot.y);
};
return (
diff --git a/src/contexts/ZoomPanContext.js b/src/contexts/ZoomPanContext.js
deleted file mode 100644
index 98c8cfe..0000000
--- a/src/contexts/ZoomPanContext.js
+++ /dev/null
@@ -1,4 +0,0 @@
-import { createContext } from 'react';
-
-const ZoomPanContext = createContext();
-export default ZoomPanContext;
diff --git a/src/hooks/useZoomPubSub.js b/src/hooks/useZoomPubSub.js
index fa500be..acaf8c3 100644
--- a/src/hooks/useZoomPubSub.js
+++ b/src/hooks/useZoomPubSub.js
@@ -2,6 +2,7 @@ import { useEffect } from 'react';
import { Subject, BehaviorSubject } from 'rxjs';
const zoomCenter$ = new Subject();
+const viewAlign$ = new Subject();
// BehaviorSubjects to store current viewBox, clientRect and camera transform
export const viewBox$ = new BehaviorSubject(null);
@@ -32,17 +33,27 @@ export function getCurrentCamera() {
/**
* useZoomPanSubscriber
*
-* Registers a callback (onCenter) that will be invoked whenever
+* Registers an `onCenter` callback that will be invoked whenever
* someone calls `center(x, y)` via the emitter. You should pass
* a function that takes (x, y) and recenters your viewBox accordingly.
+ *
+ * Similarly, registers an `onAlign` callback that will be invoked
+ * when someone calls `alignView(angleDeg)`.
*/
-export function useZoomPanSubscriber(onCenter) {
+export function useZoomPanSubscriber(onCenter, onAlign) {
useEffect(() => {
const sub = zoomCenter$.subscribe(({ x, y }) => {
onCenter(x, y);
});
return () => sub.unsubscribe();
}, [onCenter]);
+
+ useEffect(() => {
+ const sub = viewAlign$.subscribe((angleDeg) => {
+ onAlign(angleDeg);
+ });
+ return () => sub.unsubscribe();
+ }, [onAlign]);
}
/**
@@ -57,5 +68,8 @@ export function useZoomPanEmitter() {
center: (x, y) => {
zoomCenter$.next({ x, y });
},
+ alignView: (angleDeg) => {
+ viewAlign$.next(angleDeg);
+ },
};
}