-
Notifications
You must be signed in to change notification settings - Fork 264
Expand file tree
/
Copy pathOpenSeadragonTileSource.jsx
More file actions
96 lines (78 loc) · 2.98 KB
/
OpenSeadragonTileSource.jsx
File metadata and controls
96 lines (78 loc) · 2.98 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
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);
}
})
);
}, [viewer?.current, url]); // eslint-disable-line react-hooks/exhaustive-deps
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,
};