consolidate drawer creation into viewer api. add drawer-error event

This commit is contained in:
Tom 2024-02-21 16:01:18 -05:00
parent 02898cfc17
commit 99c35aa3cb
4 changed files with 51 additions and 18 deletions

View File

@ -280,6 +280,37 @@ OpenSeadragon.DrawerBase = class DrawerBase{
}); });
} }
/**
* Called by implementations to fire the drawer-error event
* @private
*/
_raiseDrawerErrorEvent(tiledImage, errorMessage){
if(!this.viewer) {
return;
}
/**
* Raised when a tiled image is drawn to the canvas. Used internally for testing.
* The update-viewport event is preferred if you want to know when a frame has been drawn.
*
* @event drawer-error
* @memberof OpenSeadragon.Viewer
* @type {object}
* @property {OpenSeadragon.Viewer} eventSource - A reference to the Viewer which raised the event.
* @property {OpenSeadragon.TiledImage} tiledImage - Which TiledImage is being drawn.
* @property {OpenSeadragon.DrawerBase} drawer - The drawer that raised the error.
* @property {String} error - A message describing the error.
* @property {?Object} userData - Arbitrary subscriber-defined object.
* @private
*/
this.viewer.raiseEvent( 'drawer-error', {
tiledImage: tiledImage,
drawer: this,
error: errorMessage,
});
}
}; };
}( OpenSeadragon )); }( OpenSeadragon ));

View File

@ -456,7 +456,7 @@ $.Viewer = function( options ) {
this.drawer = null; this.drawer = null;
for (const drawerCandidate of drawerCandidates){ for (const drawerCandidate of drawerCandidates){
let success = this.setDrawer(drawerCandidate, false); let success = this.requestDrawer(drawerCandidate, true, false);
if(success){ if(success){
break; break;
} }
@ -929,19 +929,20 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype,
}, },
/** /**
* Set the drawer for this viewer, as a supported string or drawer constructor. * Request a drawer for this viewer, as a supported string or drawer constructor.
* @param {String | OpenSeadragon.DrawerBase} drawerCandidate The type of drawer to try to construct * @param {String | OpenSeadragon.DrawerBase} drawerCandidate The type of drawer to try to construct.
* @param { Boolean } [redrawImmediately] Whether to immediately draw a new frame. Default = true. * @param { Boolean } [mainDrawer] Whether to use this as the viewer's main drawer. Default = true.
* @param { Boolean } [redrawImmediately] Whether to immediately draw a new frame. Only used if mainDrawer = true. Default = true.
* @param { Object } [drawerOptions] Options for this drawer. If falsey, defaults to viewer.drawerOptions * @param { Object } [drawerOptions] Options for this drawer. If falsey, defaults to viewer.drawerOptions
* for this viewer type. See {@link OpenSeadragon.Options}. * for this viewer type. See {@link OpenSeadragon.Options}.
* @returns {Boolean} whether the drawer was created successfully * @returns {Object | Boolean} The drawer that was created, or false if the requestd drawer is not supported
*/ */
setDrawer(drawerCandidate, redrawImmediately = true, drawerOptions = null){ requestDrawer(drawerCandidate, mainDrawer = true, redrawImmediately = true, drawerOptions = null){
const oldDrawer = this.drawer; const oldDrawer = this.drawer;
let Drawer = null; let Drawer = null;
//if inherits from a drawer base, use it //if the candidate inherits from a drawer base, use it
if (drawerCandidate && drawerCandidate.prototype instanceof $.DrawerBase) { if (drawerCandidate && drawerCandidate.prototype instanceof $.DrawerBase) {
Drawer = drawerCandidate; Drawer = drawerCandidate;
drawerCandidate = 'custom'; drawerCandidate = 'custom';
@ -957,12 +958,12 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype,
if (Drawer && Drawer.isSupported()) { if (Drawer && Drawer.isSupported()) {
// first destroy the previous drawer // first destroy the previous drawer
if(oldDrawer){ if(oldDrawer && mainDrawer){
oldDrawer.destroy(); oldDrawer.destroy();
} }
// create the new drawer // create the new drawer
this.drawer = new Drawer({ const newDrawer = new Drawer({
viewer: this, viewer: this,
viewport: this.viewport, viewport: this.viewport,
element: this.canvas, element: this.canvas,
@ -970,10 +971,14 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype,
options: drawerOptions || this.drawerOptions[drawerCandidate], options: drawerOptions || this.drawerOptions[drawerCandidate],
}); });
if(redrawImmediately){ if(mainDrawer){
this.forceRedraw(); this.drawer = newDrawer;
if(redrawImmediately){
this.forceRedraw();
}
} }
return true;
return newDrawer;
} }
return false; return false;

View File

@ -231,11 +231,7 @@
*/ */
_getBackupCanvasDrawer(){ _getBackupCanvasDrawer(){
if(!this._backupCanvasDrawer){ if(!this._backupCanvasDrawer){
this._backupCanvasDrawer = new $.CanvasDrawer({ this._backupCanvasDrawer = this.viewer.requestDrawer('canvas', false);
viewer: this.viewer,
viewport: this.viewport,
element: this.container,
});
this._backupCanvasDrawer.canvas.style.setProperty('visibility', 'hidden'); this._backupCanvasDrawer.canvas.style.setProperty('visibility', 'hidden');
} }
@ -882,6 +878,7 @@
if(!wasTainted){ if(!wasTainted){
tiledImage.setTainted(true); tiledImage.setTainted(true);
$.console.warn('WebGL cannot be used to draw this TiledImage because it has tainted data. Does crossOriginPolicy need to be set?'); $.console.warn('WebGL cannot be used to draw this TiledImage because it has tainted data. Does crossOriginPolicy need to be set?');
this._raiseDrawerErrorEvent(tiledImage, 'Tainted data cannot be used by the WebGLDrawer. Falling back to CanvasDrawer for this TiledImage.');
} }
return; return;
} }

View File

@ -49,7 +49,7 @@ let viewer2 = window.viewer2 = OpenSeadragon({
minZoomImageRatio:0.01, minZoomImageRatio:0.01,
maxZoomPixelRatio:100, maxZoomPixelRatio:100,
smoothTileEdgesMinZoom:1.1, smoothTileEdgesMinZoom:1.1,
crossOriginPolicy: 'Anonymous', // crossOriginPolicy: 'Anonymous',
ajaxWithCredentials: false, ajaxWithCredentials: false,
// maxImageCacheCount: 30, // maxImageCacheCount: 30,
drawer:drawer2, drawer:drawer2,