From 354590a17a8a5667a4a40c381d2b8ac5c56aea69 Mon Sep 17 00:00:00 2001 From: Tom Date: Wed, 7 Jun 2023 12:42:16 -0700 Subject: [PATCH] convert DrawerBase and drawer implementations to classes; add html drawer to the demo page --- src/canvasdrawer.js | 324 ++++++++----------------------- src/drawerbase.js | 449 ++++++++++++++++++++++++++++++++----------- src/htmldrawer.js | 202 ++++++------------- test/demo/webgl.html | 27 +++ test/demo/webgl.js | 13 ++ 5 files changed, 507 insertions(+), 508 deletions(-) diff --git a/src/canvasdrawer.js b/src/canvasdrawer.js index cae12a56..37b0c8a0 100644 --- a/src/canvasdrawer.js +++ b/src/canvasdrawer.js @@ -44,40 +44,39 @@ * @param {Element} options.element - Parent element. * @param {Number} [options.debugGridColor] - See debugGridColor in {@link OpenSeadragon.Options} for details. */ -$.CanvasDrawer = function(options) { - $.DrawerBase.call(this, options); +class CanvasDrawer extends $.DrawerBase{ + constructor(options){ + super(options); - /** - * 2d drawing context for {@link OpenSeadragon.Drawer#canvas} if it's a <canvas> element, otherwise null. - * @member {Object} context - * @memberof OpenSeadragon.Drawer# - */ - this.context = this.canvas.getContext( '2d' ); + /** + * 2d drawing context for {@link OpenSeadragon.Drawer#canvas} if it's a <canvas> element, otherwise null. + * @member {Object} context + * @memberof OpenSeadragon.Drawer# + */ + this.context = this.canvas.getContext( '2d' ); - /** - * Sketch canvas used to temporarily draw tiles which cannot be drawn directly - * to the main canvas due to opacity. Lazily initialized. - */ - this.sketchCanvas = null; - this.sketchContext = null; + /** + * Sketch canvas used to temporarily draw tiles which cannot be drawn directly + * to the main canvas due to opacity. Lazily initialized. + */ + this.sketchCanvas = null; + this.sketchContext = null; - // We force our container to ltr because our drawing math doesn't work in rtl. - // This issue only affects our canvas renderer, but we do it always for consistency. - // Note that this means overlays you want to be rtl need to be explicitly set to rtl. - this.container.dir = 'ltr'; + // We force our container to ltr because our drawing math doesn't work in rtl. + // This issue only affects our canvas renderer, but we do it always for consistency. + // Note that this means overlays you want to be rtl need to be explicitly set to rtl. + this.container.dir = 'ltr'; - // Image smoothing for canvas rendering (only if canvas is used). - // Canvas default is "true", so this will only be changed if user specified "false". - this._imageSmoothingEnabled = true; -}; - -$.extend( $.CanvasDrawer.prototype, $.DrawerBase.prototype, /** @lends OpenSeadragon.Drawer.prototype */ { + // Image smoothing for canvas rendering (only if canvas is used). + // Canvas default is "true", so this will only be changed if user specified "false". + this._imageSmoothingEnabled = true; + } /** * Draws the TiledImages */ - draw: function(tiledImages) { + draw(tiledImages) { var _this = this; this._prepareNewFrame(); // prepare to draw a new frame tiledImages.forEach(function(tiledImage){ @@ -89,26 +88,25 @@ $.extend( $.CanvasDrawer.prototype, $.DrawerBase.prototype, /** @lends OpenSeadr tiledImage._needsDraw = false; } }); - - }, + } /** * @returns {Boolean} True - rotation is supported. */ - canRotate: function() { + canRotate() { return true; - }, + } /** * Destroy the drawer (unload current loaded tiles) */ - destroy: function() { + destroy() { //force unloading of current canvas (1x1 will be gc later, trick not necessarily needed) this.canvas.width = 1; this.canvas.height = 1; this.sketchCanvas = null; this.sketchContext = null; - }, + } /** * Turns image smoothing on or off for this viewer. Note: Ignored in some (especially older) browsers that do not support this property. @@ -118,17 +116,17 @@ $.extend( $.CanvasDrawer.prototype, $.DrawerBase.prototype, /** @lends OpenSeadr * drawn smoothly on the canvas; see imageSmoothingEnabled in * {@link OpenSeadragon.Options} for more explanation. */ - setImageSmoothingEnabled: function(imageSmoothingEnabled){ + setImageSmoothingEnabled(imageSmoothingEnabled){ this._imageSmoothingEnabled = imageSmoothingEnabled; this._updateImageSmoothingEnabled(this.context); this.viewer.forceRedraw(); - }, + } /** * Draw a rectangle onto the canvas * @param {OpenSeadragon.Rect} rect */ - drawDebuggingRect: function(rect) { + drawDebuggingRect(rect) { var context = this.context; context.save(); context.lineWidth = 2 * $.pixelDensityRatio; @@ -143,8 +141,7 @@ $.extend( $.CanvasDrawer.prototype, $.DrawerBase.prototype, /** @lends OpenSeadr ); context.restore(); - - }, + } /** * @private @@ -152,7 +149,7 @@ $.extend( $.CanvasDrawer.prototype, $.DrawerBase.prototype, /** @lends OpenSeadr * Clears the Drawer so it's ready to draw another frame. * */ - _prepareNewFrame: function() { + _prepareNewFrame() { var viewportSize = this._calculateCanvasSize(); if( this.canvas.width !== viewportSize.x || this.canvas.height !== viewportSize.y ) { @@ -167,8 +164,7 @@ $.extend( $.CanvasDrawer.prototype, $.DrawerBase.prototype, /** @lends OpenSeadr } } this._clear(); - - }, + } /** * @private @@ -176,7 +172,7 @@ $.extend( $.CanvasDrawer.prototype, $.DrawerBase.prototype, /** @lends OpenSeadr * @param {Boolean} useSketch Whether to clear sketch canvas or main canvas * @param {OpenSeadragon.Rect} [bounds] The rectangle to clear */ - _clear: function(useSketch, bounds){ + _clear(useSketch, bounds){ var context = this._getContext(useSketch); if (bounds) { context.clearRect(bounds.x, bounds.y, bounds.width, bounds.height); @@ -184,106 +180,7 @@ $.extend( $.CanvasDrawer.prototype, $.DrawerBase.prototype, /** @lends OpenSeadr var canvas = context.canvas; context.clearRect(0, 0, canvas.width, canvas.height); } - }, - - /* Methods from TiledImage */ - - // /** - // * @private - // * @inner - // * Handles drawing a single TiledImage to the canvas - // * - // */ - // _updateViewportWithTiledImage: function(tiledImage) { - // var _this = this; - // tiledImage._needsDraw = false; - // tiledImage._tilesLoading = 0; - // tiledImage.loadingCoverage = {}; - - // // Reset tile's internal drawn state - // while (tiledImage.lastDrawn.length > 0) { - // var tile = tiledImage.lastDrawn.pop(); - // tile.beingDrawn = false; - // } - - - // var drawArea = tiledImage.getDrawArea(); - // if(!drawArea){ - // return; - // } - - // function updateTile(info){ - // var tile = info.tile; - // if(tile && tile.loaded){ - // var needsDraw = _this._blendTile( - // tiledImage, - // tile, - // tile.x, - // tile.y, - // info.level, - // info.levelOpacity, - // info.currentTime - // ); - // if(needsDraw){ - // tiledImage._needsDraw = true; - // } - // } - // } - - // var infoArray = tiledImage.getTileInfoForDrawing(); - // infoArray.forEach(updateTile); - - // this._drawTiles(tiledImage); - - // }, - - - - // /** - // * @private - // * @inner - // * Updates the opacity of a tile according to the time it has been on screen - // * to perform a fade-in. - // * Updates coverage once a tile is fully opaque. - // * Returns whether the fade-in has completed. - // * - // * @param {OpenSeadragon.Tile} tile - // * @param {Number} x - // * @param {Number} y - // * @param {Number} level - // * @param {Number} levelOpacity - // * @param {Number} currentTime - // * @returns {Boolean} - // */ - // _blendTile: function( tiledImage, tile, x, y, level, levelOpacity, currentTime ){ - // var blendTimeMillis = 1000 * tiledImage.blendTime, - // deltaTime, - // opacity; - - // if ( !tile.blendStart ) { - // tile.blendStart = currentTime; - // } - - // deltaTime = currentTime - tile.blendStart; - // opacity = blendTimeMillis ? Math.min( 1, deltaTime / ( blendTimeMillis ) ) : 1; - - // if ( tiledImage.alwaysBlend ) { - // opacity *= levelOpacity; - // } - - // tile.opacity = opacity; - - // tiledImage.lastDrawn.push( tile ); - - // if ( opacity === 1 ) { - // tiledImage._setCoverage( tiledImage.coverage, level, x, y, true ); - // tiledImage._hasOpaqueTile = true; - // } else if ( deltaTime < blendTimeMillis ) { - // return true; - // } - - // return false; - // }, + } /** * @private @@ -291,7 +188,7 @@ $.extend( $.CanvasDrawer.prototype, $.DrawerBase.prototype, /** @lends OpenSeadr * Draws a TiledImage. * */ - _drawTiles: function( tiledImage ) { + _drawTiles( tiledImage ) { var lastDrawn = tiledImage.lastDrawn; if (tiledImage.opacity === 0 || (lastDrawn.length === 0 && !tiledImage.placeholderFillStyle)) { return; @@ -532,7 +429,7 @@ $.extend( $.CanvasDrawer.prototype, $.DrawerBase.prototype, /** @lends OpenSeadr } this._drawDebugInfo( tiledImage, lastDrawn ); - }, + } /** * @private @@ -540,7 +437,7 @@ $.extend( $.CanvasDrawer.prototype, $.DrawerBase.prototype, /** @lends OpenSeadr * Draws special debug information for a TiledImage if in debug mode. * @param {OpenSeadragon.Tile[]} lastDrawn - An unordered list of Tiles drawn last frame. */ - _drawDebugInfo: function( tiledImage, lastDrawn ) { + _drawDebugInfo( tiledImage, lastDrawn ) { if( tiledImage.debugMode ) { for ( var i = lastDrawn.length - 1; i >= 0; i-- ) { var tile = lastDrawn[ i ]; @@ -551,7 +448,7 @@ $.extend( $.CanvasDrawer.prototype, $.DrawerBase.prototype, /** @lends OpenSeadr } } } - }, + } /* Methods from Tile */ @@ -563,7 +460,7 @@ $.extend( $.CanvasDrawer.prototype, $.DrawerBase.prototype, /** @lends OpenSeadr * @param {OpenSeadragon.Point[][]} polygons - an array of polygons. A polygon is an array of OpenSeadragon.Point * @param {Boolean} useSketch - Whether to use the sketch canvas or not. */ - _clipWithPolygons: function (polygons, useSketch) { + _clipWithPolygons (polygons, useSketch) { var context = this._getContext(useSketch); context.beginPath(); polygons.forEach(function (polygon) { @@ -572,7 +469,7 @@ $.extend( $.CanvasDrawer.prototype, $.DrawerBase.prototype, /** @lends OpenSeadr }); }); context.clip(); - }, + } /** * @private @@ -590,7 +487,7 @@ $.extend( $.CanvasDrawer.prototype, $.DrawerBase.prototype, /** @lends OpenSeadr * context. * @param {OpenSeadragon.TileSource} source - The source specification of the tile. */ - _drawTile: function( tile, drawingHandler, useSketch, scale, translate, shouldRoundPositionAndSize, source) { + _drawTile( tile, drawingHandler, useSketch, scale, translate, shouldRoundPositionAndSize, source) { $.console.assert(tile, '[Drawer._drawTile] tile is required'); $.console.assert(drawingHandler, '[Drawer._drawTile] drawingHandler is required'); @@ -598,7 +495,7 @@ $.extend( $.CanvasDrawer.prototype, $.DrawerBase.prototype, /** @lends OpenSeadr scale = scale || 1; this._drawTileToCanvas(tile, context, drawingHandler, scale, translate, shouldRoundPositionAndSize, source); - }, + } /** * @private @@ -617,7 +514,7 @@ $.extend( $.CanvasDrawer.prototype, $.DrawerBase.prototype, /** @lends OpenSeadr * context. * @param {OpenSeadragon.TileSource} source - The source specification of the tile. */ - _drawTileToCanvas: function( tile, context, drawingHandler, scale, translate, shouldRoundPositionAndSize, source) { + _drawTileToCanvas( tile, context, drawingHandler, scale, translate, shouldRoundPositionAndSize, source) { var position = tile.position.times($.pixelDensityRatio), size = tile.size.times($.pixelDensityRatio), @@ -708,68 +605,7 @@ $.extend( $.CanvasDrawer.prototype, $.DrawerBase.prototype, /** @lends OpenSeadr ); context.restore(); - }, - - /** - * @private - * @inner - * Renders the tile in an html container. - * @function - * @param {OpenSeadragon.Tile} tile - * @param {Element} container - */ - _drawTileToHTML: function( tile, container ) { - if (!tile.cacheImageRecord) { - $.console.warn( - '[Drawer._drawTileToHTML] attempting to draw tile %s when it\'s not cached', - tile.toString()); - return; - } - - if ( !tile.loaded ) { - $.console.warn( - "Attempting to draw tile %s when it's not yet loaded.", - tile.toString() - ); - return; - } - - //EXPERIMENTAL - trying to figure out how to scale the container - // content during animation of the container size. - - if ( !tile.element ) { - var image = tile.getImage(); - if (!image) { - return; - } - - tile.element = $.makeNeutralElement( "div" ); - tile.imgElement = image.cloneNode(); - tile.imgElement.style.msInterpolationMode = "nearest-neighbor"; - tile.imgElement.style.width = "100%"; - tile.imgElement.style.height = "100%"; - - tile.style = tile.element.style; - tile.style.position = "absolute"; - } - if ( tile.element.parentNode !== container ) { - container.appendChild( tile.element ); - } - if ( tile.imgElement.parentNode !== tile.element ) { - tile.element.appendChild( tile.imgElement ); - } - - tile.style.top = tile.position.y + "px"; - tile.style.left = tile.position.x + "px"; - tile.style.height = tile.size.y + "px"; - tile.style.width = tile.size.x + "px"; - - if (tile.flipped) { - tile.style.transform = "scaleX(-1)"; - } - - $.setElementOpacity( tile.element, tile.opacity ); - }, + } /** * @private @@ -778,7 +614,7 @@ $.extend( $.CanvasDrawer.prototype, $.DrawerBase.prototype, /** @lends OpenSeadr * @param {Boolean} useSketch * @returns */ - _getContext: function( useSketch ) { + _getContext( useSketch ) { var context = this.context; if ( useSketch ) { if (this.sketchCanvas === null) { @@ -808,7 +644,7 @@ $.extend( $.CanvasDrawer.prototype, $.DrawerBase.prototype, /** @lends OpenSeadr context = this.sketchContext; } return context; - }, + } /** * @private @@ -817,9 +653,9 @@ $.extend( $.CanvasDrawer.prototype, $.DrawerBase.prototype, /** @lends OpenSeadr * @param {Boolean} useSketch * @returns */ - _saveContext: function( useSketch ) { + _saveContext( useSketch ) { this._getContext( useSketch ).save(); - }, + } /** * @private @@ -828,26 +664,26 @@ $.extend( $.CanvasDrawer.prototype, $.DrawerBase.prototype, /** @lends OpenSeadr * @param {Boolean} useSketch * @returns */ - _restoreContext: function( useSketch ) { + _restoreContext( useSketch ) { this._getContext( useSketch ).restore(); - }, + } // private - _setClip: function(rect, useSketch) { + _setClip(rect, useSketch) { var context = this._getContext( useSketch ); context.beginPath(); context.rect(rect.x, rect.y, rect.width, rect.height); context.clip(); - }, + } // private - _drawRectangle: function(rect, fillStyle, useSketch) { + _drawRectangle(rect, fillStyle, useSketch) { var context = this._getContext( useSketch ); context.save(); context.fillStyle = fillStyle; context.fillRect(rect.x, rect.y, rect.width, rect.height); context.restore(); - }, + } /** * Blends the sketch canvas in the main canvas. @@ -865,7 +701,7 @@ $.extend( $.CanvasDrawer.prototype, $.DrawerBase.prototype, /** @lends OpenSeadr * canvas to blend in the main canvas. If specified, options.scale and * options.translate get ignored. */ - blendSketch: function(opacity, scale, translate, compositeOperation) { + blendSketch(opacity, scale, translate, compositeOperation) { var options = opacity; if (!$.isPlainObject(options)) { options = { @@ -942,10 +778,10 @@ $.extend( $.CanvasDrawer.prototype, $.DrawerBase.prototype, /** @lends OpenSeadr ); } this.context.restore(); - }, + } // private - drawDebugInfo: function(tile, count, i, tiledImage) { + drawDebugInfo(tile, count, i, tiledImage) { var colorIndex = this.viewer.world.getIndexOfItem(tiledImage) % this.debugGridColor.length; var context = this.context; @@ -1045,13 +881,13 @@ $.extend( $.CanvasDrawer.prototype, $.DrawerBase.prototype, /** @lends OpenSeadr } context.restore(); - }, + } // private - _updateImageSmoothingEnabled: function(context){ + _updateImageSmoothingEnabled(context){ context.msImageSmoothingEnabled = this._imageSmoothingEnabled; context.imageSmoothingEnabled = this._imageSmoothingEnabled; - }, + } /** * @private @@ -1060,10 +896,10 @@ $.extend( $.CanvasDrawer.prototype, $.DrawerBase.prototype, /** @lends OpenSeadr * @param {Boolean} sketch If set to true return the size of the sketch canvas * @returns {OpenSeadragon.Point} The size of the canvas */ - _getCanvasSize: function(sketch) { + _getCanvasSize(sketch) { var canvas = this._getContext(sketch).canvas; return new $.Point(canvas.width, canvas.height); - }, + } /** * @private @@ -1072,12 +908,12 @@ $.extend( $.CanvasDrawer.prototype, $.DrawerBase.prototype, /** @lends OpenSeadr * @param {Boolean} sketch If set to true return the center point of the sketch canvas * @returns {OpenSeadragon.Point} The center point of the canvas */ - _getCanvasCenter: function() { + _getCanvasCenter() { return new $.Point(this.canvas.width / 2, this.canvas.height / 2); - }, + } // private - _offsetForRotation: function(options) { + _offsetForRotation(options) { var point = options.point ? options.point.times($.pixelDensityRatio) : this._getCanvasCenter(); @@ -1093,10 +929,10 @@ $.extend( $.CanvasDrawer.prototype, $.DrawerBase.prototype, /** @lends OpenSeadr context.rotate(Math.PI / 180 * options.degrees); } context.translate(-point.x, -point.y); - }, + } // private - _flip: function(options) { + _flip(options) { options = options || {}; var point = options.point ? options.point.times($.pixelDensityRatio) : @@ -1106,16 +942,16 @@ $.extend( $.CanvasDrawer.prototype, $.DrawerBase.prototype, /** @lends OpenSeadr context.translate(point.x, 0); context.scale(-1, 1); context.translate(-point.x, 0); - }, + } // private - _restoreRotationChanges: function(useSketch) { + _restoreRotationChanges(useSketch) { var context = this._getContext(useSketch); context.restore(); - }, + } // private - _calculateCanvasSize: function() { + _calculateCanvasSize() { var pixelDensityRatio = $.pixelDensityRatio; var viewportSize = this.viewport.getContainerSize(); return { @@ -1123,10 +959,10 @@ $.extend( $.CanvasDrawer.prototype, $.DrawerBase.prototype, /** @lends OpenSeadr x: Math.round(viewportSize.x * pixelDensityRatio), y: Math.round(viewportSize.y * pixelDensityRatio) }; - }, + } // private - _calculateSketchCanvasSize: function() { + _calculateSketchCanvasSize() { var canvasSize = this._calculateCanvasSize(); if (this.viewport.getRotation() === 0) { return canvasSize; @@ -1140,11 +976,9 @@ $.extend( $.CanvasDrawer.prototype, $.DrawerBase.prototype, /** @lends OpenSeadr x: sketchCanvasSize, y: sketchCanvasSize }; - }, - - -}); - + } +} +$.CanvasDrawer = CanvasDrawer; /** diff --git a/src/drawerbase.js b/src/drawerbase.js index 42357b71..faa4b3eb 100644 --- a/src/drawerbase.js +++ b/src/drawerbase.js @@ -43,119 +43,113 @@ * @param {OpenSeadragon.Viewport} options.viewport - Reference to Viewer viewport. * @param {Element} options.element - Parent element. */ -$.DrawerBase = function( options ) { - $.console.assert( options.viewer, "[Drawer] options.viewer is required" ); +class DrawerBase{ + constructor(options){ + $.console.assert( options.viewer, "[Drawer] options.viewer is required" ); - //backward compatibility for positional args while preferring more - //idiomatic javascript options object as the only argument - var args = arguments; + //backward compatibility for positional args while preferring more + //idiomatic javascript options object as the only argument + var args = arguments; - if( !$.isPlainObject( options ) ){ - options = { - source: args[ 0 ], // Reference to Viewer tile source. - viewport: args[ 1 ], // Reference to Viewer viewport. - element: args[ 2 ] // Parent element. - }; + if( !$.isPlainObject( options ) ){ + options = { + source: args[ 0 ], // Reference to Viewer tile source. + viewport: args[ 1 ], // Reference to Viewer viewport. + element: args[ 2 ] // Parent element. + }; + } + + $.console.assert( options.viewport, "[Drawer] options.viewport is required" ); + $.console.assert( options.element, "[Drawer] options.element is required" ); + + if ( options.source ) { + $.console.error( "[Drawer] options.source is no longer accepted; use TiledImage instead" ); + } + + this.viewer = options.viewer; + this.viewport = options.viewport; + this.debugGridColor = typeof options.debugGridColor === 'string' ? [options.debugGridColor] : options.debugGridColor || $.DEFAULT_SETTINGS.debugGridColor; + + if (options.opacity) { + $.console.error( "[Drawer] options.opacity is no longer accepted; set the opacity on the TiledImage instead" ); + } + + this.useCanvas = $.supportsCanvas && ( this.viewer ? this.viewer.useCanvas : true ); + /** + * The parent element of this Drawer instance, passed in when the Drawer was created. + * The parent of {@link OpenSeadragon.DrawerBase#canvas}. + * @member {Element} container + * @memberof OpenSeadragon.DrawerBase# + */ + this.container = $.getElement( options.element ); + /** + * A <canvas> element if the browser supports them, otherwise a <div> element. + * Child element of {@link OpenSeadragon.DrawerBase#container}. + * @member {Element} canvas + * @memberof OpenSeadragon.DrawerBase# + */ + this.canvas = $.makeNeutralElement( this.useCanvas ? "canvas" : "div" ); + + + /** + * @member {Element} element + * @memberof OpenSeadragon.DrawerBase# + * @deprecated Alias for {@link OpenSeadragon.DrawerBase#container}. + */ + this.element = this.container; + + // TO DO: Does this need to be in DrawerBase, or only in Drawer implementations? + // We force our container to ltr because our drawing math doesn't work in rtl. + // This issue only affects our canvas renderer, but we do it always for consistency. + // Note that this means overlays you want to be rtl need to be explicitly set to rtl. + this.container.dir = 'ltr'; + + if (this.useCanvas) { + var viewportSize = this._calculateCanvasSize(); + this.canvas.width = viewportSize.x; + this.canvas.height = viewportSize.y; + } + + this.canvas.style.width = "100%"; + this.canvas.style.height = "100%"; + this.canvas.style.position = "absolute"; + $.setElementOpacity( this.canvas, this.opacity, true ); + + // Allow pointer events to pass through the canvas element so implicit + // pointer capture works on touch devices + $.setElementPointerEventsNone( this.canvas ); + $.setElementTouchActionNone( this.canvas ); + + // explicit left-align + this.container.style.textAlign = "left"; + this.container.appendChild( this.canvas ); + + this._checkForAPIOverrides(); } - - $.console.assert( options.viewport, "[Drawer] options.viewport is required" ); - $.console.assert( options.element, "[Drawer] options.element is required" ); - - if ( options.source ) { - $.console.error( "[Drawer] options.source is no longer accepted; use TiledImage instead" ); + get isOpenSeadragonDrawer(){ + return true; } - - this.viewer = options.viewer; - this.viewport = options.viewport; - this.debugGridColor = typeof options.debugGridColor === 'string' ? [options.debugGridColor] : options.debugGridColor || $.DEFAULT_SETTINGS.debugGridColor; - - if (options.opacity) { - $.console.error( "[Drawer] options.opacity is no longer accepted; set the opacity on the TiledImage instead" ); - } - - this.useCanvas = $.supportsCanvas && ( this.viewer ? this.viewer.useCanvas : true ); - /** - * The parent element of this Drawer instance, passed in when the Drawer was created. - * The parent of {@link OpenSeadragon.DrawerBase#canvas}. - * @member {Element} container - * @memberof OpenSeadragon.DrawerBase# - */ - this.container = $.getElement( options.element ); - /** - * A <canvas> element if the browser supports them, otherwise a <div> element. - * Child element of {@link OpenSeadragon.DrawerBase#container}. - * @member {Element} canvas - * @memberof OpenSeadragon.DrawerBase# - */ - this.canvas = $.makeNeutralElement( this.useCanvas ? "canvas" : "div" ); - - - /** - * @member {Element} element - * @memberof OpenSeadragon.DrawerBase# - * @deprecated Alias for {@link OpenSeadragon.DrawerBase#container}. - */ - this.element = this.container; - - // TO DO: Does this need to be in DrawerBase, or only in Drawer implementations? - // We force our container to ltr because our drawing math doesn't work in rtl. - // This issue only affects our canvas renderer, but we do it always for consistency. - // Note that this means overlays you want to be rtl need to be explicitly set to rtl. - this.container.dir = 'ltr'; - - if (this.useCanvas) { - var viewportSize = this._calculateCanvasSize(); - this.canvas.width = viewportSize.x; - this.canvas.height = viewportSize.y; - } - - this.canvas.style.width = "100%"; - this.canvas.style.height = "100%"; - this.canvas.style.position = "absolute"; - $.setElementOpacity( this.canvas, this.opacity, true ); - - // Allow pointer events to pass through the canvas element so implicit - // pointer capture works on touch devices - $.setElementPointerEventsNone( this.canvas ); - $.setElementTouchActionNone( this.canvas ); - - // explicit left-align - this.container.style.textAlign = "left"; - this.container.appendChild( this.canvas ); - - this._checkForAPIOverrides(); -}; - -/** @lends OpenSeadragon.DrawerBaseBase.prototype */ -$.DrawerBase.prototype = { - - // Drawer implementaions must define the next four methods. These are called - // by core OSD and/or public APIs, and forcing overrides (even for nullop methods) makes the - // behavior of the implementations explicitly clear in the code. - // Whether these have been overridden by child classes is checked in the - // constructor (via _checkForAPIOverrides). - /** * @param tiledImage the TiledImage that is ready to be drawn */ - draw: function(tiledImage) { + draw(tiledImage) { $.console.error('Drawer.draw must be implemented by child class'); - }, + } /** * @returns {Boolean} True if rotation is supported. */ - canRotate: function() { + canRotate() { $.console.error('Drawer.canRotate must be implemented by child class'); - }, + } /** * Destroy the drawer (unload current loaded tiles) */ - destroy: function() { + destroy() { $.console.error('Drawer.destroy must be implemented by child class'); - }, + } /** * Turns image smoothing on or off for this viewer. Note: Ignored in some (especially older) browsers that do not support this property. @@ -165,23 +159,23 @@ $.DrawerBase.prototype = { * drawn smoothly on the canvas; see imageSmoothingEnabled in * {@link OpenSeadragon.Options} for more explanation. */ - setImageSmoothingEnabled: function(imageSmoothingEnabled){ + setImageSmoothingEnabled(imageSmoothingEnabled){ $.console.error('Drawer.setImageSmoothingEnabled must be implemented by child class'); - }, + } /** * Optional public API to draw a rectangle (e.g. for debugging purposes) * Child classes can override this method if they wish to support this * @param {OpenSeadragon.Rect} rect */ - drawDebuggingRect: function(rect) { + drawDebuggingRect(rect) { $.console.warn('[drawer].drawDebuggingRect is not implemented by this drawer'); - }, + } // Deprecated functions - clear: function(){ + clear(){ $.console.warn('[drawer].clear() is deprecated. The drawer is responsible for clearing itself as needed before drawing tiles.'); - }, + } // Private functions @@ -192,7 +186,7 @@ $.DrawerBase.prototype = { * draw, canRotate, destroy, and setImageSmoothinEnabled. Throws an exception if the original * placeholder methods are still in place. */ - _checkForAPIOverrides: function(){ + _checkForAPIOverrides(){ if(this.draw === $.DrawerBase.prototype.draw){ throw("[drawer].draw must be implemented by child class"); } @@ -206,7 +200,7 @@ $.DrawerBase.prototype = { if(this.setImageSmoothingEnabled === $.DrawerBase.prototype.setImageSmoothingEnabled){ throw("[drawer].setImageSmoothingEnabled must be implemented by child class"); } - }, + } // Utility functions internal API @@ -219,7 +213,7 @@ $.DrawerBase.prototype = { * @param {OpenSeadragon.Rect} rectangle - The rectangle in viewport coordinate system. * @returns {OpenSeadragon.Rect} Rectangle in drawer coordinate system. */ - _viewportToDrawerRectangle: function(rectangle) { + _viewportToDrawerRectangle(rectangle) { var topLeft = this.viewport.pixelFromPointNoRotate(rectangle.getTopLeft(), true); var size = this.viewport.deltaPixelsFromPointsNoRotate(rectangle.getSize(), true); @@ -229,7 +223,7 @@ $.DrawerBase.prototype = { size.x * $.pixelDensityRatio, size.y * $.pixelDensityRatio ); - }, + } /** * @private @@ -241,13 +235,13 @@ $.DrawerBase.prototype = { * @param {OpenSeadragon.Point} point - the pixel point to convert * @returns {OpenSeadragon.Point} Point in drawer coordinate system. */ - _viewportCoordToDrawerCoord: function(point) { + _viewportCoordToDrawerCoord(point) { var vpPoint = this.viewport.pixelFromPointNoRotate(point, true); return new $.Point( vpPoint.x * $.pixelDensityRatio, vpPoint.y * $.pixelDensityRatio ); - }, + } /** * @private @@ -256,7 +250,7 @@ $.DrawerBase.prototype = { * and pixelDensityRatio * @returns {Dictionary} {x, y} size of the canvas */ - _calculateCanvasSize: function() { + _calculateCanvasSize() { var pixelDensityRatio = $.pixelDensityRatio; var viewportSize = this.viewport.getContainerSize(); return { @@ -264,15 +258,240 @@ $.DrawerBase.prototype = { x: Math.round(viewportSize.x * pixelDensityRatio), y: Math.round(viewportSize.y * pixelDensityRatio) }; - }, - -}; - -Object.defineProperty($.DrawerBase.prototype, "isOpenSeadragonDrawer", { - get: function get() { - return true; } -}); + +} +$.DrawerBase = DrawerBase; +// $.DrawerBase = function( options ) { + +// $.console.assert( options.viewer, "[Drawer] options.viewer is required" ); + +// //backward compatibility for positional args while preferring more +// //idiomatic javascript options object as the only argument +// var args = arguments; + +// if( !$.isPlainObject( options ) ){ +// options = { +// source: args[ 0 ], // Reference to Viewer tile source. +// viewport: args[ 1 ], // Reference to Viewer viewport. +// element: args[ 2 ] // Parent element. +// }; +// } + +// $.console.assert( options.viewport, "[Drawer] options.viewport is required" ); +// $.console.assert( options.element, "[Drawer] options.element is required" ); + +// if ( options.source ) { +// $.console.error( "[Drawer] options.source is no longer accepted; use TiledImage instead" ); +// } + +// this.viewer = options.viewer; +// this.viewport = options.viewport; +// this.debugGridColor = typeof options.debugGridColor === 'string' ? [options.debugGridColor] : options.debugGridColor || $.DEFAULT_SETTINGS.debugGridColor; + +// if (options.opacity) { +// $.console.error( "[Drawer] options.opacity is no longer accepted; set the opacity on the TiledImage instead" ); +// } + +// this.useCanvas = $.supportsCanvas && ( this.viewer ? this.viewer.useCanvas : true ); +// /** +// * The parent element of this Drawer instance, passed in when the Drawer was created. +// * The parent of {@link OpenSeadragon.DrawerBase#canvas}. +// * @member {Element} container +// * @memberof OpenSeadragon.DrawerBase# +// */ +// this.container = $.getElement( options.element ); +// /** +// * A <canvas> element if the browser supports them, otherwise a <div> element. +// * Child element of {@link OpenSeadragon.DrawerBase#container}. +// * @member {Element} canvas +// * @memberof OpenSeadragon.DrawerBase# +// */ +// this.canvas = $.makeNeutralElement( this.useCanvas ? "canvas" : "div" ); + + +// /** +// * @member {Element} element +// * @memberof OpenSeadragon.DrawerBase# +// * @deprecated Alias for {@link OpenSeadragon.DrawerBase#container}. +// */ +// this.element = this.container; + +// // TO DO: Does this need to be in DrawerBase, or only in Drawer implementations? +// // We force our container to ltr because our drawing math doesn't work in rtl. +// // This issue only affects our canvas renderer, but we do it always for consistency. +// // Note that this means overlays you want to be rtl need to be explicitly set to rtl. +// this.container.dir = 'ltr'; + +// if (this.useCanvas) { +// var viewportSize = this._calculateCanvasSize(); +// this.canvas.width = viewportSize.x; +// this.canvas.height = viewportSize.y; +// } + +// this.canvas.style.width = "100%"; +// this.canvas.style.height = "100%"; +// this.canvas.style.position = "absolute"; +// $.setElementOpacity( this.canvas, this.opacity, true ); + +// // Allow pointer events to pass through the canvas element so implicit +// // pointer capture works on touch devices +// $.setElementPointerEventsNone( this.canvas ); +// $.setElementTouchActionNone( this.canvas ); + +// // explicit left-align +// this.container.style.textAlign = "left"; +// this.container.appendChild( this.canvas ); + +// this._checkForAPIOverrides(); +// }; + +// /** @lends OpenSeadragon.DrawerBaseBase.prototype */ +// $.DrawerBase.prototype = { + +// // Drawer implementaions must define the next four methods. These are called +// // by core OSD and/or public APIs, and forcing overrides (even for nullop methods) makes the +// // behavior of the implementations explicitly clear in the code. +// // Whether these have been overridden by child classes is checked in the +// // constructor (via _checkForAPIOverrides). + +// /** +// * @param tiledImage the TiledImage that is ready to be drawn +// */ +// draw: function(tiledImage) { +// $.console.error('Drawer.draw must be implemented by child class'); +// }, + +// /** +// * @returns {Boolean} True if rotation is supported. +// */ +// canRotate: function() { +// $.console.error('Drawer.canRotate must be implemented by child class'); +// }, + +// /** +// * Destroy the drawer (unload current loaded tiles) +// */ +// destroy: function() { +// $.console.error('Drawer.destroy must be implemented by child class'); +// }, + +// /** +// * Turns image smoothing on or off for this viewer. Note: Ignored in some (especially older) browsers that do not support this property. +// * +// * @function +// * @param {Boolean} [imageSmoothingEnabled] - Whether or not the image is +// * drawn smoothly on the canvas; see imageSmoothingEnabled in +// * {@link OpenSeadragon.Options} for more explanation. +// */ +// setImageSmoothingEnabled: function(imageSmoothingEnabled){ +// $.console.error('Drawer.setImageSmoothingEnabled must be implemented by child class'); +// }, + +// /** +// * Optional public API to draw a rectangle (e.g. for debugging purposes) +// * Child classes can override this method if they wish to support this +// * @param {OpenSeadragon.Rect} rect +// */ +// drawDebuggingRect: function(rect) { +// $.console.warn('[drawer].drawDebuggingRect is not implemented by this drawer'); +// }, + +// // Deprecated functions +// clear: function(){ +// $.console.warn('[drawer].clear() is deprecated. The drawer is responsible for clearing itself as needed before drawing tiles.'); +// }, + +// // Private functions + +// /** +// * @private +// * @inner +// * Ensures that child classes have provided implementations for public API methods +// * draw, canRotate, destroy, and setImageSmoothinEnabled. Throws an exception if the original +// * placeholder methods are still in place. +// */ +// _checkForAPIOverrides: function(){ +// if(this.draw === $.DrawerBase.prototype.draw){ +// throw("[drawer].draw must be implemented by child class"); +// } +// if(this.canRotate === $.DrawerBase.prototype.canRotate){ +// throw("[drawer].canRotate must be implemented by child class"); +// } +// if(this.destroy === $.DrawerBase.prototype.destroy){ +// throw("[drawer].destroy must be implemented by child class"); +// } + +// if(this.setImageSmoothingEnabled === $.DrawerBase.prototype.setImageSmoothingEnabled){ +// throw("[drawer].setImageSmoothingEnabled must be implemented by child class"); +// } +// }, + + +// // Utility functions internal API + +// /** +// * @private +// * @inner +// * Scale from OpenSeadragon viewer rectangle to drawer rectangle +// * (ignoring rotation) +// * @param {OpenSeadragon.Rect} rectangle - The rectangle in viewport coordinate system. +// * @returns {OpenSeadragon.Rect} Rectangle in drawer coordinate system. +// */ +// _viewportToDrawerRectangle: function(rectangle) { +// var topLeft = this.viewport.pixelFromPointNoRotate(rectangle.getTopLeft(), true); +// var size = this.viewport.deltaPixelsFromPointsNoRotate(rectangle.getSize(), true); + +// return new $.Rect( +// topLeft.x * $.pixelDensityRatio, +// topLeft.y * $.pixelDensityRatio, +// size.x * $.pixelDensityRatio, +// size.y * $.pixelDensityRatio +// ); +// }, + +// /** +// * @private +// * @inner +// * This function converts the given point from to the drawer coordinate by +// * multiplying it with the pixel density. +// * This function does not take rotation into account, thus assuming provided +// * point is at 0 degree. +// * @param {OpenSeadragon.Point} point - the pixel point to convert +// * @returns {OpenSeadragon.Point} Point in drawer coordinate system. +// */ +// _viewportCoordToDrawerCoord: function(point) { +// var vpPoint = this.viewport.pixelFromPointNoRotate(point, true); +// return new $.Point( +// vpPoint.x * $.pixelDensityRatio, +// vpPoint.y * $.pixelDensityRatio +// ); +// }, + +// /** +// * @private +// * @inner +// * Calculate width and height of the canvas based on viewport dimensions +// * and pixelDensityRatio +// * @returns {Dictionary} {x, y} size of the canvas +// */ +// _calculateCanvasSize: function() { +// var pixelDensityRatio = $.pixelDensityRatio; +// var viewportSize = this.viewport.getContainerSize(); +// return { +// // canvas width and height are integers +// x: Math.round(viewportSize.x * pixelDensityRatio), +// y: Math.round(viewportSize.y * pixelDensityRatio) +// }; +// }, + +// }; + +// Object.defineProperty($.DrawerBase.prototype, "isOpenSeadragonDrawer", { +// get: function get() { +// return true; +// } +// }); }( OpenSeadragon )); diff --git a/src/htmldrawer.js b/src/htmldrawer.js index fbadf3c4..4d078709 100644 --- a/src/htmldrawer.js +++ b/src/htmldrawer.js @@ -1,8 +1,8 @@ /* - * OpenSeadragon - Drawer + * OpenSeadragon - HTMLDrawer * * Copyright (C) 2009 CodePlex Foundation - * Copyright (C) 2010-2022 OpenSeadragon contributors + * Copyright (C) 2010-2023 OpenSeadragon contributors * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -44,36 +44,54 @@ * @param {Element} options.element - Parent element. * @param {Number} [options.debugGridColor] - See debugGridColor in {@link OpenSeadragon.Options} for details. */ -$.HTMLDrawer = function(options) { - $.DrawerBase.call(this, options); +class HTMLDrawer extends $.DrawerBase{ + constructor(options){ + super(options); - /** - * 2d drawing context for {@link OpenSeadragon.Drawer#canvas} if it's a <canvas> element, otherwise null. - * @member {Object} context - * @memberof OpenSeadragon.Drawer# - */ - this.context = null; + /** + * 2d drawing context for {@link OpenSeadragon.Drawer#canvas} if it's a <canvas> element, otherwise null. + * @member {Object} context + * @memberof OpenSeadragon.Drawer# + */ + this.context = null; - // We force our container to ltr because our drawing math doesn't work in rtl. - // This issue only affects our canvas renderer, but we do it always for consistency. - // Note that this means overlays you want to be rtl need to be explicitly set to rtl. - this.container.dir = 'ltr'; + // We force our container to ltr because our drawing math doesn't work in rtl. + // This issue only affects our canvas renderer, but we do it always for consistency. + // Note that this means overlays you want to be rtl need to be explicitly set to rtl. + this.container.dir = 'ltr'; -}; + /** + * Override default element to enforce div for HTMLDrawer + */ + this.canvas.parentNode.removeChild(this.canvas); + this.canvas = $.makeNeutralElement( "div" ); -$.extend( $.HTMLDrawer.prototype, $.DrawerBase.prototype, /** @lends OpenSeadragon.Drawer.prototype */ { + this.canvas.style.width = "100%"; + this.canvas.style.height = "100%"; + this.canvas.style.position = "absolute"; + $.setElementOpacity( this.canvas, this.opacity, true ); + + // Allow pointer events to pass through the canvas element so implicit + // pointer capture works on touch devices + $.setElementPointerEventsNone( this.canvas ); + $.setElementTouchActionNone( this.canvas ); + + // explicit left-align + this.container.style.textAlign = "left"; + this.container.appendChild( this.canvas ); + + } /** * Draws the TiledImages */ - draw: function(tiledImages) { + draw(tiledImages) { var _this = this; this._prepareNewFrame(); // prepare to draw a new frame tiledImages.forEach(function(tiledImage){ if (tiledImage.opacity !== 0 || tiledImage._preload) { - // _this._updateViewportWithTiledImage(tiledImage); _this._drawTiles(tiledImage); } else { @@ -81,23 +99,22 @@ $.extend( $.HTMLDrawer.prototype, $.DrawerBase.prototype, /** @lends OpenSeadrag } }); - }, + } /** * @returns {Boolean} False - rotation is not supported. */ - canRotate: function() { + canRotate() { return false; - }, + } /** * Destroy the drawer (unload current loaded tiles) */ - destroy: function() { + destroy() { //force unloading of current canvas (1x1 will be gc later, trick not necessarily needed) - this.canvas.width = 1; - this.canvas.height = 1; - }, + this.canvas.innerHTML = ""; + } /** * Turns image smoothing on or off for this viewer. Note: Ignored by HTML Drawer @@ -107,10 +124,10 @@ $.extend( $.HTMLDrawer.prototype, $.DrawerBase.prototype, /** @lends OpenSeadrag * drawn smoothly on the canvas; see imageSmoothingEnabled in * {@link OpenSeadragon.Options} for more explanation. */ - setImageSmoothingEnabled: function(){ + setImageSmoothingEnabled(){ // noop - HTML Drawer does not deal with this property $.console.warn('HTMLDrawer.setImageSmoothingEnabled does not have an effect.'); - }, + } /** * @private @@ -118,108 +135,9 @@ $.extend( $.HTMLDrawer.prototype, $.DrawerBase.prototype, /** @lends OpenSeadrag * Clears the Drawer so it's ready to draw another frame. * */ - _prepareNewFrame: function() { + _prepareNewFrame() { this.canvas.innerHTML = ""; - }, - - /* Methods from TiledImage */ - - /** - * @private - * @inner - * Handles drawing a single TiledImage to the canvas - * - */ - _updateViewportWithTiledImage: function(tiledImage) { - var _this = this; - tiledImage._needsDraw = false; - tiledImage._tilesLoading = 0; - tiledImage.loadingCoverage = {}; - - // Reset tile's internal drawn state - while (tiledImage.lastDrawn.length > 0) { - var tile = tiledImage.lastDrawn.pop(); - tile.beingDrawn = false; - } - - - var drawArea = tiledImage.getDrawArea(); - if(!drawArea){ - return; - } - - function updateTile(info){ - var tile = info.tile; - if(tile && tile.loaded){ - var needsDraw = _this._blendTile( - tiledImage, - tile, - tile.x, - tile.y, - info.level, - info.levelOpacity, - info.currentTime - ); - if(needsDraw){ - tiledImage._needsDraw = true; - } - } - } - - var infoArray = tiledImage.getTileInfoForDrawing(); - infoArray.forEach(updateTile); - - this._drawTiles(tiledImage); - - }, - - - - /** - * @private - * @inner - * Updates the opacity of a tile according to the time it has been on screen - * to perform a fade-in. - * Updates coverage once a tile is fully opaque. - * Returns whether the fade-in has completed. - * - * @param {OpenSeadragon.Tile} tile - * @param {Number} x - * @param {Number} y - * @param {Number} level - * @param {Number} levelOpacity - * @param {Number} currentTime - * @returns {Boolean} - */ - _blendTile: function( tiledImage, tile, x, y, level, levelOpacity, currentTime ){ - var blendTimeMillis = 1000 * tiledImage.blendTime, - deltaTime, - opacity; - - if ( !tile.blendStart ) { - tile.blendStart = currentTime; - } - - deltaTime = currentTime - tile.blendStart; - opacity = blendTimeMillis ? Math.min( 1, deltaTime / ( blendTimeMillis ) ) : 1; - - if ( tiledImage.alwaysBlend ) { - opacity *= levelOpacity; - } - - tile.opacity = opacity; - - tiledImage.lastDrawn.push( tile ); - - if ( opacity === 1 ) { - tiledImage._setCoverage( tiledImage.coverage, level, x, y, true ); - tiledImage._hasOpaqueTile = true; - } else if ( deltaTime < blendTimeMillis ) { - return true; - } - - return false; - }, + } /** * @private @@ -227,7 +145,7 @@ $.extend( $.HTMLDrawer.prototype, $.DrawerBase.prototype, /** @lends OpenSeadrag * Draws a TiledImage. * */ - _drawTiles: function( tiledImage ) { + _drawTiles( tiledImage ) { var lastDrawn = tiledImage.lastDrawn; if (tiledImage.opacity === 0 || (lastDrawn.length === 0 && !tiledImage.placeholderFillStyle)) { return; @@ -258,9 +176,7 @@ $.extend( $.HTMLDrawer.prototype, $.DrawerBase.prototype, /** @lends OpenSeadrag } } - }, - - /* Methods from Tile */ + } /** * @private @@ -270,22 +186,11 @@ $.extend( $.HTMLDrawer.prototype, $.DrawerBase.prototype, /** @lends OpenSeadrag * @param {Function} drawingHandler - Method for firing the drawing event if using canvas. * drawingHandler({context, tile, rendered}) */ - _drawTile: function( tile ) { + _drawTile( tile ) { $.console.assert(tile, '[Drawer._drawTile] tile is required'); - this._drawTileToHTML( tile, this.canvas ); - }, + let container = this.canvas; - - /** - * @private - * @inner - * Renders the tile in an html container. - * @function - * @param {OpenSeadragon.Tile} tile - * @param {Element} container - */ - _drawTileToHTML: function( tile, container ) { if (!tile.cacheImageRecord) { $.console.warn( '[Drawer._drawTileToHTML] attempting to draw tile %s when it\'s not cached', @@ -319,6 +224,7 @@ $.extend( $.HTMLDrawer.prototype, $.DrawerBase.prototype, /** @lends OpenSeadrag tile.style = tile.element.style; tile.style.position = "absolute"; } + if ( tile.element.parentNode !== container ) { container.appendChild( tile.element ); } @@ -336,11 +242,11 @@ $.extend( $.HTMLDrawer.prototype, $.DrawerBase.prototype, /** @lends OpenSeadrag } $.setElementOpacity( tile.element, tile.opacity ); - }, - -}); + } +} +$.HTMLDrawer = HTMLDrawer; }( OpenSeadragon )); diff --git a/test/demo/webgl.html b/test/demo/webgl.html index fe5eabec..8e98f4e2 100644 --- a/test/demo/webgl.html +++ b/test/demo/webgl.html @@ -38,6 +38,7 @@ border: thin black solid; padding:10px; display:inline-block; + width:95%; } .description pre{ display:inline-block; @@ -164,9 +165,35 @@ + +

HTMLDrawer: legacy pre-HTML5 drawer that uses <img> elements for tiles

+
+
+
+ HTML-based rendering can be selected in two different ways: +
+
+    // via the useCanvas option:
+    let viewer = OpenSeadragon({
+        ...
+        useCanvas: false,
+        ...
+    });
+
+    // or by passing the HTMLDrawer constructor
+    let viewer = OpenSeadragon({
+        ...
+        customDrawer:OpenSeadragon.HTMLDrawer,
+        ...
+    });
+                
+
+
+
+ diff --git a/test/demo/webgl.js b/test/demo/webgl.js index a5e44431..e40044a3 100644 --- a/test/demo/webgl.js +++ b/test/demo/webgl.js @@ -69,6 +69,19 @@ var viewer2 = window.viewer2 = OpenSeadragon({ ajaxWithCredentials: false }); +// Single viewer showing how to use plugin Drawer via configuration +// Also shows sequence mode +var viewer3 = window.viewer3 = OpenSeadragon({ + id: "htmldrawer", + prefixUrl: "../../build/openseadragon/images/", + minZoomImageRatio:0.01, + customDrawer: OpenSeadragon.HTMLDrawer, + tileSources: [sources['leaves'], sources['rainbow'], sources['duomo']], + sequenceMode: true, + crossOriginPolicy: 'Anonymous', + ajaxWithCredentials: false +}); +