UNPKG

mirador

Version:

An open-source, web-based 'multi-up' viewer that supports zoom-pan-rotate functionality, ability to display/compare simple images, and images with annotations.

106 lines (87 loc) 3.11 kB
import Openseadragon from 'openseadragon'; import PropTypes from 'prop-types'; import { useContext, useEffect, useRef } from 'react'; import OpenSeadragonViewerContext from '../contexts/OpenSeadragonViewerContext'; import FailedImageContext from '../contexts/FailedImageContext'; /** OSD tile source shim that adds + updates its tile source data */ export default function OpenSeadragonTileSource({ index = undefined, opacity = undefined, fitBounds = undefined, tileSource = {}, url = undefined, }) { const viewer = useContext(OpenSeadragonViewerContext); const { notifyFailure, fallbackImage } = useContext(FailedImageContext); const tiledImage = useRef(undefined); useEffect(() => { if (opacity == null) return; tiledImage.current?.setOpacity(opacity); }, [opacity]); useEffect(() => { if (!fitBounds) return; tiledImage.current?.fitBounds(new Openseadragon.Rect(...fitBounds)); }, [fitBounds]); useEffect(() => { if (!tiledImage.current || !viewer?.current || index == null) return; viewer.current.world.setItemIndex(tiledImage.current, index); }, [index, viewer]); useEffect(() => { if (!viewer?.current) return undefined; const loadFallback = () => { if (!fallbackImage) { return; } viewer.current.addTiledImage({ tileSource: { type: 'image', url: fallbackImage }, index, opacity, fitBounds: fitBounds ? new Openseadragon.Rect(...fitBounds) : undefined, success: (ev) => { tiledImage.current = ev.item; }, }); }; const promise = new Promise((resolve, reject) => { const localTileSource = (url && { type: 'image', url }) || ((typeof tileSource === 'string' || tileSource instanceof String) && tileSource) || // OSD mutates this object, so we give it a shallow copy { ...tileSource }; viewer.current?.addTiledImage({ tileSource: localTileSource, index, opacity, fitBounds: fitBounds ? new Openseadragon.Rect(...fitBounds) : undefined, success: (event) => resolve(event), error: (event) => { const imageUrl = url || (typeof tileSource === 'string' ? tileSource : tileSource?.['@id']); if (imageUrl) notifyFailure(imageUrl); loadFallback(); reject(event); }, }); }) .then((event) => { tiledImage.current = event.item; }) .catch((err) => { console.warn('[Mirador: OSD tile image load failed]', err); }); const osd = viewer.current; return () => promise.finally(() => { if (osd && tiledImage.current) { osd.world.removeItem(tiledImage.current); } }); // eslint-disable-next-line react-hooks/exhaustive-deps }, [viewer?.current, url]); return null; } OpenSeadragonTileSource.propTypes = { fitBounds: PropTypes.arrayOf(PropTypes.number), index: PropTypes.number, opacity: PropTypes.number, tileSource: PropTypes.oneOfType([PropTypes.string, PropTypes.object]), url: PropTypes.string, };