]> git.localhorst.tv Git - alttp.git/blobdiff - resources/js/components/map/OpenSeadragon.js
store map position in history
[alttp.git] / resources / js / components / map / OpenSeadragon.js
index b6158a5aea79ca3a03f964deb4f5dc413cfa52c0..52c0506b13fc8ffa89214431562cde8158c29417 100644 (file)
@@ -2,16 +2,54 @@ import axios from 'axios';
 import OpenSeadragon from 'openseadragon';
 import PropTypes from 'prop-types';
 import React from 'react';
+import { useNavigate, useParams } from 'react-router';
+import { createSearchParams, useSearchParams } from 'react-router-dom';
 
 export const Context = React.createContext({});
 
 export const useOpenSeadragon = () => React.useContext(Context);
 
 export const Provider = React.forwardRef(({ children }, ref) => {
-       const [activeMap, setActiveMap] = React.useState('lw');
+       const { activeMap } = useParams();
+       const navigate = useNavigate();
+       const [searchParams, setSearchParams] = useSearchParams();
        const [pins, setPins] = React.useState([]);
        const [viewer, setViewer] = React.useState(null);
 
+       const storePosition = React.useCallback(() => {
+               if (!viewer || !viewer.viewport) return;
+               const center = viewer.viewport.getCenter();
+               const zoom = viewer.viewport.getZoom();
+               setSearchParams({ x: center.x, y: center.y, z: zoom }, { replace: true });
+       }, [setSearchParams, viewer]);
+
+       const setActiveMap = React.useCallback(map => {
+               if (viewer && viewer.viewport) {
+                       const center = viewer.viewport.getCenter();
+                       const zoom = viewer.viewport.getZoom();
+                       const params = { x: center.x, y: center.y, z: zoom };
+                       navigate(
+                               { pathname: `../${map}`, search: `?${createSearchParams(params)}` },
+                               { replace: true },
+                       );
+               } else {
+                       navigate(`../${map}`, { replace: true });
+               }
+       }, [navigate, viewer]);
+
+       React.useEffect(() => {
+               if (!viewer || !viewer.viewport) return;
+               if (searchParams.has('x') && searchParams.has('y')) {
+                       viewer.viewport.panTo(new OpenSeadragon.Point(
+                               parseFloat(searchParams.get('x')),
+                               parseFloat(searchParams.get('y')),
+                       ));
+               }
+               if (searchParams.has('z')) {
+                       viewer.viewport.zoomTo(parseFloat(searchParams.get('z')));
+               }
+       }, [searchParams, viewer]);
+
        React.useEffect(() => {
                if (!ref.current) return;
 
@@ -99,7 +137,7 @@ export const Provider = React.forwardRef(({ children }, ref) => {
                };
        }, [activeMap, viewer]);
 
-       return <Context.Provider value={{ activeMap, setActiveMap, pins, viewer }}>
+       return <Context.Provider value={{ activeMap, pins, setActiveMap, storePosition, viewer }}>
                {children}
        </Context.Provider>;
 });