1 import axios from 'axios';
2 import OpenSeadragon from 'openseadragon';
3 import PropTypes from 'prop-types';
4 import React from 'react';
5 import { useNavigate, useParams } from 'react-router';
6 import { createSearchParams, useSearchParams } from 'react-router-dom';
8 export const Context = React.createContext({});
10 export const useOpenSeadragon = () => React.useContext(Context);
12 export const Provider = React.forwardRef(({ children }, ref) => {
13 const { activeMap } = useParams();
14 const navigate = useNavigate();
15 const [searchParams, setSearchParams] = useSearchParams();
16 const [pins, setPins] = React.useState([]);
17 const [viewer, setViewer] = React.useState(null);
19 const storePosition = React.useCallback(() => {
20 if (!viewer || !viewer.viewport) return;
21 const center = viewer.viewport.getCenter();
22 const zoom = viewer.viewport.getZoom();
23 setSearchParams({ x: center.x, y: center.y, z: zoom }, { replace: true });
24 }, [setSearchParams, viewer]);
26 const setActiveMap = React.useCallback(map => {
27 if (viewer && viewer.viewport) {
28 const center = viewer.viewport.getCenter();
29 const zoom = viewer.viewport.getZoom();
30 const params = { x: center.x, y: center.y, z: zoom };
32 { pathname: `../${map}`, search: `?${createSearchParams(params)}` },
36 navigate(`../${map}`, { replace: true });
38 }, [navigate, viewer]);
40 React.useEffect(() => {
41 if (!viewer || !viewer.viewport) return;
42 if (searchParams.has('x') && searchParams.has('y')) {
43 viewer.viewport.panTo(new OpenSeadragon.Point(
44 parseFloat(searchParams.get('x')),
45 parseFloat(searchParams.get('y')),
48 if (searchParams.has('z')) {
49 viewer.viewport.zoomTo(parseFloat(searchParams.get('z')));
51 }, [searchParams, viewer]);
53 React.useEffect(() => {
54 if (!ref.current) return;
56 const v = OpenSeadragon({
58 preserveViewport: true,
61 showNavigationControl: false,
62 showSequenceControl: false,
64 new OpenSeadragon.DziTileSource({
71 tilesUrl: '/media/alttp/map/lw_files/',
73 }), new OpenSeadragon.DziTileSource({
80 tilesUrl: '/media/alttp/map/dw_files/',
82 }), new OpenSeadragon.DziTileSource({
89 tilesUrl: '/media/alttp/map/sp_files/',
91 }), new OpenSeadragon.DziTileSource({
98 tilesUrl: '/media/alttp/map/uw_files/',
100 }), new OpenSeadragon.DziTileSource({
107 tilesUrl: '/media/alttp/map/uw2_files/',
112 v.addHandler('canvas-nonprimary-press', e => {
113 if (e.button === 3) {
115 } else if (e.button === 4) {
125 React.useEffect(() => {
144 const controller = new AbortController();
145 axios.get(`/api/markers/${activeMap}`, {
146 signal: controller.signal,
147 }).then(response => {
148 setPins(response.data || []);
150 if (!axios.isCancel(e)) {
157 }, [activeMap, viewer]);
159 return <Context.Provider value={{ activeMap, pins, setActiveMap, storePosition, viewer }}>
164 Provider.displayName = 'OpenSeadragonProvider';
166 Provider.propTypes = {
167 children: PropTypes.node,
170 export default Provider;