UNPKG

photoswipe-deep-zoom-plugin

Version:

A plugin that adds tile-based zoom support to PhotoSwipe. Supports Deepzoom and Zoomify tile formats.

167 lines (139 loc) 3.94 kB
import { getTileKey } from "./util.js"; export const LOAD_STATE = { IDLE: 'idle', LOADING: 'loading', LOADED: 'loaded', ERROR: 'error', }; export const DECODING_STATE = { IDLE: 'idle', DECODING: 'decoding', DECODED: 'decoded' }; class TileImage { constructor(url, x, y, z) { this.x = x; this.y = y; this.z = z; this.key = getTileKey(x, y, z); this.url = url; this.hasParent = false; // the Image has an Tile that uses it this.loadState = LOAD_STATE.IDLE; this.decodingState = DECODING_STATE.IDLE; this.styles = undefined; this._createImage(); } isLoaded() { return this.loadState === LOAD_STATE.LOADED; } isDecoded() { return this.decodingState === DECODING_STATE.DECODED; } setStyles(styles) { if (styles) { this.styles = styles; for(let name in this.styles) { this.imageElement.style[name] = this.styles[name]; } } } tileDetached() { this.hasParent = false; if (this.decodingState !== DECODING_STATE.DECODING) { this.decodingState = DECODING_STATE.IDLE; } } tileAttached() { this.hasParent = true; } _createImage() { this.imageElement = new Image(); this.imageElement.setAttribute('role', 'presentation'); this.imageElement.setAttribute('alt', ''); this.setStyles(this.styles); } decode() { if (this.loadState === LOAD_STATE.LOADED) { // if image is loaded and decoded, just exit if (this.decodingState === DECODING_STATE.DECODED) { this._onDecoded(); return; } // if image is decoding, just wait for it if (this.decodingState === DECODING_STATE.DECODING) { return; } // start decoding if (this.decodingState === DECODING_STATE.IDLE) { this._startDecode(); } } else if (this.loadState === LOAD_STATE.LOADING) { if (this.decodingState === DECODING_STATE.DECODING) { // if image is decoding, just wait for it return; } } else { // this.loadState === LOAD_STATE.IDLE || this.loadState === LOAD_STATE.ERROR // Image is not loaded yet, or needs a reload this._startDecode(); } } _startDecode() { if (this.loadState === LOAD_STATE.ERROR) { this._createImage(); } if (!this.imageElement.src) { this.imageElement.src = this.url; } this.decodingState = DECODING_STATE.DECODING; if (this.loadState !== LOAD_STATE.LOADED) { this.loadState = LOAD_STATE.LOADING; } if ('decode' in this.imageElement) { this.imageElement.decode().then(() => { this._onDecoded(); }).catch((error) => { this._onDecodeError(); }); } else { if (this.loadState === LOAD_STATE.LOADED) { this._onDecoded(); } else { this.imageElement.onload = () => { this._onDecoded(); }; this.imageElement.onerror = (e) => { this._onDecodeError(); }; } } } _onDecoded() { // If image has no parent, it won't be added to dom, // thus it's not guaranteed that it's decoded this.decodingState = this.hasParent ? DECODING_STATE.DECODED : DECODING_STATE.IDLE; this.loadState = LOAD_STATE.LOADED; if (this.onDecoded) { this.onDecoded(this); } } _onDecodeError() { this.decodingState = DECODING_STATE.IDLE; this.loadState = LOAD_STATE.ERROR; if (this.onError) { this.onError(this); } } destroy() { if (this.imageElement) { this.imageElement.onload = null; this.imageElement.onerror = null; this.imageElement = null; } this.onError = null; this.onDecoded = null; } } export default TileImage;