]> git.localhorst.tv Git - alttp.git/blobdiff - resources/js/components/map/OpenSeadragon.js
improved underworld map navigation
[alttp.git] / resources / js / components / map / OpenSeadragon.js
index b6158a5aea79ca3a03f964deb4f5dc413cfa52c0..36ddec1ce4c0685ba471ce101b4913c04f503cf3 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;
 
@@ -59,9 +97,25 @@ export const Provider = React.forwardRef(({ children }, ref) => {
                                        maxLevel: 14,
                                        tilesUrl: '/media/alttp/map/uw_files/',
                                        fileFormat: 'png',
+                               }), new OpenSeadragon.DziTileSource({
+                                       width: 16384,
+                                       height: 3072,
+                                       tileSize: 256,
+                                       tileOverlap: 0,
+                                       minLevel: 8,
+                                       maxLevel: 14,
+                                       tilesUrl: '/media/alttp/map/uw2_files/',
+                                       fileFormat: 'png',
                                }),
                        ],
                });
+               v.addHandler('canvas-nonprimary-press', e => {
+                       if (e.button === 3) {
+                               navigate(-1);
+                       } else if (e.button === 4) {
+                               navigate(1);
+                       }
+               });
                setViewer(v);
                return () => {
                        v.destroy();
@@ -83,6 +137,9 @@ export const Provider = React.forwardRef(({ children }, ref) => {
                        case 'uw':
                                viewer.goToPage(3);
                                break;
+                       case 'uw2':
+                               viewer.goToPage(4);
+                               break;
                }
                const controller = new AbortController();
                axios.get(`/api/markers/${activeMap}`, {
@@ -99,7 +156,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>;
 });