From d346d165f8409f5a0caa1c024f74dc749abd6546 Mon Sep 17 00:00:00 2001 From: Ian Gilman Date: Tue, 4 Nov 2014 11:53:39 -0800 Subject: [PATCH 1/7] Updated documentation --- changelog.txt | 3 +- src/drawer.js | 129 ++++++++++--------------------------------- src/navigator.js | 5 +- src/openseadragon.js | 2 +- src/tilecache.js | 50 ++++++++++------- src/tiledimage.js | 48 ++++++++++------ src/viewer.js | 44 ++++----------- src/viewport.js | 23 ++++++-- src/world.js | 32 +++-------- 9 files changed, 131 insertions(+), 205 deletions(-) diff --git a/changelog.txt b/changelog.txt index f4f2c205..ddb10df9 100644 --- a/changelog.txt +++ b/changelog.txt @@ -5,6 +5,7 @@ OPENSEADRAGON CHANGELOG * True multi-image mode (#450) * BREAKING CHANGE: Navigator no longer sends an open event when its viewer opens + * BREAKING CHANGE: Viewer.drawers and Viewer.drawersContainer no longer exist * DEPRECATION: use Viewer.addTiledImage instead of Viewer.addLayer * addTiledImage supports positioning config properties * DEPRECATION: use World.getItemAt instead of Viewer.getLayerAtLevel @@ -17,7 +18,6 @@ OPENSEADRAGON CHANGELOG * DEPRECATION: use World.resetItems instead of Drawer.reset * DEPRECATION: use Drawer.clear and World.update instead of Drawer.update * DEPRECATION: the layersAspectRatioEpsilon option is no longer necessary - * DEPRECATION: Viewer.drawers and Viewer.drawersContainer no longer exist * DEPRECATION: Viewer's add-layer event is now World's add-item event * DEPRECATION: Viewer's layer-level-changed event is now World's item-index-changed event * DEPRECATION: Viewer's remove-layer event is now World's remove-item event @@ -31,6 +31,7 @@ OPENSEADRAGON CHANGELOG * Rect and Point now have clone functions * New Viewport method for managing homeBounds as well as constraints: setHomeBounds * Viewport.open supports positioning config properties +* Margins option to push the home region in from the edges of the Viewer (#505) 1.2.0: (in progress) diff --git a/src/drawer.js b/src/drawer.js index fd1cd730..969c0e06 100644 --- a/src/drawer.js +++ b/src/drawer.js @@ -36,15 +36,17 @@ /** * @class Drawer - * @classdesc Handles rendering of tiles for an {@link OpenSeadragon.Viewer}. - * * @memberof OpenSeadragon - * @param {OpenSeadragon.TileSource} source - Reference to Viewer tile source. - * @param {OpenSeadragon.Viewport} viewport - Reference to Viewer viewport. - * @param {Element} element - Parent element. + * @classdesc Handles rendering of tiles for an {@link OpenSeadragon.Viewer}. + * @param {Object} options - Options for this Drawer. + * @param {OpenSeadragon.Viewer} options.viewer - The Viewer that owns this Drawer. + * @param {OpenSeadragon.Viewport} options.viewport - Reference to Viewer viewport. + * @param {Element} options.element - Parent element. + * @param {Number} [options.opacity=1] - See opacity in {@link OpenSeadragon.Options} for details. + * @param {Number} [options.debugGridColor] - See debugGridColor in {@link OpenSeadragon.Options} for details. */ $.Drawer = function( options ) { - var self = this; + var _this = this; $.console.assert( options.viewer, "[Drawer] options.viewer is required" ); @@ -117,7 +119,7 @@ $.Drawer = function( options ) { // We need a callback to give image manipulation a chance to happen this._drawingHandler = function(args) { - if (self.viewer) { + if (_this.viewer) { /** * This event is fired just before the tile is drawn giving the application a chance to alter the image. * @@ -130,80 +132,34 @@ $.Drawer = function( options ) { * @property {OpenSeadragon.Tile} tile * @property {?Object} userData - 'context', 'tile' and 'rendered'. */ - self.viewer.raiseEvent('tile-drawing', args); + _this.viewer.raiseEvent('tile-drawing', args); } }; }; $.Drawer.prototype = /** @lends OpenSeadragon.Drawer.prototype */{ - - /** - * Adds an html element as an overlay to the current viewport. Useful for - * highlighting words or areas of interest on an image or other zoomable - * interface. - * @method - * @param {Element|String|Object} element - A reference to an element or an id for - * the element which will overlayed. Or an Object specifying the configuration for the overlay - * @param {OpenSeadragon.Point|OpenSeadragon.Rect} location - The point or - * rectangle which will be overlayed. - * @param {OpenSeadragon.OverlayPlacement} placement - The position of the - * viewport which the location coordinates will be treated as relative - * to. - * @param {function} onDraw - If supplied the callback is called when the overlay - * needs to be drawn. It it the responsibility of the callback to do any drawing/positioning. - * It is passed position, size and element. - * @fires OpenSeadragon.Viewer.event:add-overlay - * @deprecated - use {@link OpenSeadragon.Viewer#addOverlay} instead. - */ + // deprecated addOverlay: function( element, location, placement, onDraw ) { $.console.error("drawer.addOverlay is deprecated. Use viewer.addOverlay instead."); this.viewer.addOverlay( element, location, placement, onDraw ); return this; }, - /** - * Updates the overlay represented by the reference to the element or - * element id moving it to the new location, relative to the new placement. - * @method - * @param {OpenSeadragon.Point|OpenSeadragon.Rect} location - The point or - * rectangle which will be overlayed. - * @param {OpenSeadragon.OverlayPlacement} placement - The position of the - * viewport which the location coordinates will be treated as relative - * to. - * @return {OpenSeadragon.Drawer} Chainable. - * @fires OpenSeadragon.Viewer.event:update-overlay - * @deprecated - use {@link OpenSeadragon.Viewer#updateOverlay} instead. - */ + // deprecated updateOverlay: function( element, location, placement ) { $.console.error("drawer.updateOverlay is deprecated. Use viewer.updateOverlay instead."); this.viewer.updateOverlay( element, location, placement ); return this; }, - /** - * Removes and overlay identified by the reference element or element id - * and schedules and update. - * @method - * @param {Element|String} element - A reference to the element or an - * element id which represent the ovelay content to be removed. - * @return {OpenSeadragon.Drawer} Chainable. - * @fires OpenSeadragon.Viewer.event:remove-overlay - * @deprecated - use {@link OpenSeadragon.Viewer#removeOverlay} instead. - */ + // deprecated removeOverlay: function( element ) { $.console.error("drawer.removeOverlay is deprecated. Use viewer.removeOverlay instead."); this.viewer.removeOverlay( element ); return this; }, - /** - * Removes all currently configured Overlays from this Drawer and schedules - * and update. - * @method - * @return {OpenSeadragon.Drawer} Chainable. - * @fires OpenSeadragon.Viewer.event:clear-overlay - * @deprecated - use {@link OpenSeadragon.Viewer#clearOverlays} instead. - */ + // deprecated clearOverlays: function() { $.console.error("drawer.clearOverlays is deprecated. Use viewer.clearOverlays instead."); this.viewer.clearOverlays(); @@ -212,7 +168,6 @@ $.Drawer.prototype = /** @lends OpenSeadragon.Drawer.prototype */{ /** * Set the opacity of the drawer. - * @method * @param {Number} opacity * @return {OpenSeadragon.Drawer} Chainable. */ @@ -224,60 +179,37 @@ $.Drawer.prototype = /** @lends OpenSeadragon.Drawer.prototype */{ /** * Get the opacity of the drawer. - * @method * @returns {Number} */ getOpacity: function() { return this.opacity; }, - /** - * Returns whether the Drawer is scheduled for an update at the - * soonest possible opportunity. - * @method - * @returns {Boolean} - Whether the Drawer is scheduled for an update at the - * soonest possible opportunity. - */ + // deprecated needsUpdate: function() { $.console.error( "[Drawer.needsUpdate] this function is deprecated." ); return false; }, - /** - * Returns the total number of tiles that have been loaded by this Drawer. - * @method - * @returns {Number} - The total number of tiles that have been loaded by - * this Drawer. - */ + // deprecated numTilesLoaded: function() { $.console.error( "[Drawer.numTilesLoaded] this function is deprecated." ); return 0; }, - /** - * Clears all tiles and triggers an update on the next call to - * Drawer.prototype.update(). - * @method - * @return {OpenSeadragon.Drawer} Chainable. - */ + // deprecated reset: function() { $.console.error( "[Drawer.reset] this function is deprecated." ); return this; }, - /** - * Forces the Drawer to update. - * @method - * @return {OpenSeadragon.Drawer} Chainable. - */ + // deprecated update: function() { $.console.error( "[Drawer.update] this function is deprecated." ); return this; }, /** - * Returns whether rotation is supported or not. - * @method * @return {Boolean} True if rotation is supported. */ canRotate: function() { @@ -286,8 +218,6 @@ $.Drawer.prototype = /** @lends OpenSeadragon.Drawer.prototype */{ /** * Destroy the drawer (unload current loaded tiles) - * @method - * @return null */ destroy: function() { //force unloading of current canvas (1x1 will be gc later, trick not necessarily needed) @@ -295,6 +225,9 @@ $.Drawer.prototype = /** @lends OpenSeadragon.Drawer.prototype */{ this.canvas.height = 1; }, + /** + * Clears the Drawer so it's ready to draw another frame. + */ clear: function() { this.canvas.innerHTML = ""; if ( this.useCanvas ) { @@ -308,6 +241,10 @@ $.Drawer.prototype = /** @lends OpenSeadragon.Drawer.prototype */{ } }, + /** + * Draws the given tile. + * @param {OpenSeadragon.Tile} tile - The tile to draw. + */ drawTile: function( tile ) { if ( this.useCanvas ) { // TODO do this in a more performant way @@ -324,9 +261,7 @@ $.Drawer.prototype = /** @lends OpenSeadragon.Drawer.prototype */{ } }, - /** - * @private - */ + // private drawDebugInfo: function( tile, count, i ){ if ( this.useCanvas ) { this.context.save(); @@ -399,9 +334,7 @@ $.Drawer.prototype = /** @lends OpenSeadragon.Drawer.prototype */{ } }, - /** - * @private - */ + // private debugRect: function(rect) { if ( this.useCanvas ) { this.context.save(); @@ -420,9 +353,7 @@ $.Drawer.prototype = /** @lends OpenSeadragon.Drawer.prototype */{ } }, - /** - * @private - */ + // private _offsetForRotation: function( tile, degrees ){ var cx = this.canvas.width / 2, cy = this.canvas.height / 2, @@ -437,9 +368,7 @@ $.Drawer.prototype = /** @lends OpenSeadragon.Drawer.prototype */{ tile.position.y = py; }, - /** - * @private - */ + // private _restoreRotationChanges: function( tile ){ var cx = this.canvas.width / 2, cy = this.canvas.height / 2, diff --git a/src/navigator.js b/src/navigator.js index 5f8eb89d..2cadc03f 100644 --- a/src/navigator.js +++ b/src/navigator.js @@ -344,10 +344,7 @@ $.extend( $.Navigator.prototype, $.EventSource.prototype, $.Viewer.prototype, /* }, - /** - * Overrides Viewer.addTiledImage - * @private - */ + // overrides Viewer.addTiledImage addTiledImage: function(options) { var original = options.originalTiledImage; delete options.original; diff --git a/src/openseadragon.js b/src/openseadragon.js index 91a7231d..14221847 100644 --- a/src/openseadragon.js +++ b/src/openseadragon.js @@ -2251,7 +2251,7 @@ window.OpenSeadragon = window.OpenSeadragon || function( options ){ info: nullfunction, warn: nullfunction, error: nullfunction, - assert: nullfunction + assert: nullfunction }; diff --git a/src/tilecache.js b/src/tilecache.js index 7228eff6..71a8f25a 100644 --- a/src/tilecache.js +++ b/src/tilecache.js @@ -34,17 +34,22 @@ (function( $ ){ -var TileRecord = function( params ) { - $.console.assert( params, "[TileCache.cacheTile] params is required" ); - $.console.assert( params.tile, "[TileCache.cacheTile] params.tile is required" ); - $.console.assert( params.tiledImage, "[TileCache.cacheTile] params.tiledImage is required" ); - this.tile = params.tile; - this.tiledImage = params.tiledImage; +// private +var TileRecord = function( options ) { + $.console.assert( options, "[TileCache.cacheTile] options is required" ); + $.console.assert( options.tile, "[TileCache.cacheTile] options.tile is required" ); + $.console.assert( options.tiledImage, "[TileCache.cacheTile] options.tiledImage is required" ); + this.tile = options.tile; + this.tiledImage = options.tiledImage; }; /** * @class TileCache - * @classdesc + * @memberof OpenSeadragon + * @classdesc Stores all the tiles displayed in a {@link OpenSeadragon.Viewer}. + * @param {Object} options - Configuration for this TileCache. + * @param {Number} [options.maxImageCacheCount] - See maxImageCacheCount in + * {@link OpenSeadragon.Options} for details. */ $.TileCache = function( options ) { options = options || {}; @@ -55,21 +60,29 @@ $.TileCache = function( options ) { $.TileCache.prototype = /** @lends OpenSeadragon.TileCache.prototype */{ /** - * Returns the total number of tiles that have been loaded by this TileCache. - * @method - * @returns {Number} - The total number of tiles that have been loaded by - * this TileCache. + * @returns {Number} The total number of tiles that have been loaded by + * this TileCache. */ numTilesLoaded: function() { return this._tilesLoaded.length; }, - cacheTile: function( params ) { - $.console.assert( params, "[TileCache.cacheTile] params is required" ); - $.console.assert( params.tile, "[TileCache.cacheTile] params.tile is required" ); - $.console.assert( params.tiledImage, "[TileCache.cacheTile] params.tiledImage is required" ); + /** + * Caches the specified tile, removing an old tile if necessary to stay under the + * maxImageCacheCount specified on construction. + * @param {Object} options - Tile info. + * @param {OpenSeadragon.Tile} options.tile - The tile to cache. + * @param {OpenSeadragon.TiledImage} options.tiledImage - The TiledImage that owns that tile. + * @param {Number} [options.cutoff=0] - If adding this tile goes over the cache max count, this + * function will release an old tile. The cutoff option specifies a tile level at or below which + * tiles will not be released. + */ + cacheTile: function( options ) { + $.console.assert( options, "[TileCache.cacheTile] options is required" ); + $.console.assert( options.tile, "[TileCache.cacheTile] options.tile is required" ); + $.console.assert( options.tiledImage, "[TileCache.cacheTile] options.tiledImage is required" ); - var cutoff = params.cutoff || 0; + var cutoff = options.cutoff || 0; var insertionIndex = this._tilesLoaded.length; if ( this._tilesLoaded.length >= this._maxImageCacheCount ) { @@ -108,14 +121,13 @@ $.TileCache.prototype = /** @lends OpenSeadragon.TileCache.prototype */{ } this._tilesLoaded[ insertionIndex ] = new TileRecord({ - tile: params.tile, - tiledImage: params.tiledImage + tile: options.tile, + tiledImage: options.tiledImage }); }, /** * Clears all tiles associated with the specified tiledImage. - * @method */ clearTilesFor: function( tiledImage ) { var tileRecord; diff --git a/src/tiledimage.js b/src/tiledimage.js index e2afbed5..dea44ef0 100644 --- a/src/tiledimage.js +++ b/src/tiledimage.js @@ -36,16 +36,35 @@ /** * @class TiledImage + * @memberof OpenSeadragon * @classdesc Handles rendering of tiles for an {@link OpenSeadragon.Viewer}. * A new instance is created for each TileSource opened. - * - * @memberof OpenSeadragon + * @param {Object} options - Configuration for this TiledImage. + * @param {OpenSeadragon.TileSource} options.source - The TileSource that defines this TiledImage. + * @param {OpenSeadragon.Viewer} options.viewer - The Viewer that owns this TiledImage. + * @param {OpenSeadragon.TileCache} options.tileCache - The TileCache for this TiledImage to use. + * @param {OpenSeadragon.Drawer} options.drawer - The Drawer for this TiledImage to draw onto. + * @param {OpenSeadragon.ImageLoader} options.imageLoader - The ImageLoader for this TiledImage to use. + * @param {Number} [options.x=0] - Left position, in world coordinates. + * @param {Number} [options.y=0] - Top position, in world coordinates. + * @param {Number} [options.width=1] - Width, in world coordinates. + * @param {Number} [options.height] - Height, in world coordinates. + * @param {Number} [options.minZoomImageRatio] - See {@link OpenSeadragon.Options}. + * @param {Boolean} [options.wrapHorizontal] - See {@link OpenSeadragon.Options}. + * @param {Boolean} [options.wrapVertical] - See {@link OpenSeadragon.Options}. + * @param {Boolean} [options.immediateRender] - See {@link OpenSeadragon.Options}. + * @param {Number} [options.blendTime] - See {@link OpenSeadragon.Options}. + * @param {Boolean} [options.alwaysBlend] - See {@link OpenSeadragon.Options}. + * @param {Number} [options.minPixelRatio] - See {@link OpenSeadragon.Options}. + * @param {Boolean} [options.debugMode] - See {@link OpenSeadragon.Options}. + * @param {String|Boolean} [options.crossOriginPolicy] - See {@link OpenSeadragon.Options}. */ $.TiledImage = function( options ) { $.console.assert( options.tileCache, "[TiledImage] options.tileCache is required" ); $.console.assert( options.drawer, "[TiledImage] options.drawer is required" ); $.console.assert( options.viewer, "[TiledImage] options.viewer is required" ); $.console.assert( options.imageLoader, "[TiledImage] options.imageLoader is required" ); + $.console.assert( options.source, "[TiledImage] options.source is required" ); this._tileCache = options.tileCache; delete options.tileCache; @@ -109,11 +128,8 @@ $.TiledImage = function( options ) { $.TiledImage.prototype = /** @lends OpenSeadragon.TiledImage.prototype */{ /** - * Returns whether the TiledImage is scheduled for an update at the - * soonest possible opportunity. - * @method - * @returns {Boolean} - Whether the TiledImage is scheduled for an update at the - * soonest possible opportunity. + * @returns {Boolean} Whether the TiledImage is scheduled for an update at the + * soonest possible opportunity. */ needsUpdate: function() { return this.updateAgain; @@ -121,42 +137,40 @@ $.TiledImage.prototype = /** @lends OpenSeadragon.TiledImage.prototype */{ /** * Clears all tiles and triggers an update on the next call to - * TiledImage.prototype.update(). - * @method - * @return {OpenSeadragon.TiledImage} Chainable. + * {@link OpenSeadragon.TiledImage#update}. */ reset: function() { this._tileCache.clearTilesFor(this); this.lastResetTime = $.now(); this.updateAgain = true; - return this; }, /** * Forces the TiledImage to update. - * @method - * @return {OpenSeadragon.TiledImage} Chainable. */ update: function() { this.midUpdate = true; updateViewport( this ); this.midUpdate = false; - return this; }, /** - * Destroy the TiledImage (unload current loaded tiles) - * @method - * @return null + * Destroy the TiledImage (unload current loaded tiles). */ destroy: function() { this.reset(); }, + /** + * @returns {OpenSeadragon.Rect} This TiledImage's bounds in world coordinates. + */ getWorldBounds: function() { return new $.Rect( this._worldX, this._worldY, this._worldWidth, this._worldHeight ); }, + /** + * @returns {OpenSeadragon.Point} This TiledImage's content size, in original pixels. + */ getContentSize: function() { return new $.Point(this.source.dimensions.x, this.source.dimensions.y); } diff --git a/src/viewer.js b/src/viewer.js index c0a6d900..727cbf9d 100644 --- a/src/viewer.js +++ b/src/viewer.js @@ -539,17 +539,13 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype, return !!this.world.getItemCount(); }, - /** - * @private - */ + // deprecated openDzi: function ( dzi ) { $.console.error( "[Viewer.openDzi] this function is deprecated; use Viewer.open() instead." ); return this.open( dzi ); }, - /** - * @private - */ + // deprecated openTileSource: function ( tileSource ) { $.console.error( "[Viewer.openTileSource] this function is deprecated; use Viewer.open() instead." ); return this.open( tileSource ); @@ -1329,24 +1325,21 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype, } ); }, - /** - * @function - * @private - */ + // deprecated addLayer: function( options ) { - var self = this; + var _this = this; $.console.error( "[Viewer.addLayer] this function is deprecated; use Viewer.addTiledImage() instead." ); var optionsClone = $.extend({}, options, { success: function(event) { - self.raiseEvent("add-layer", { + _this.raiseEvent("add-layer", { options: options, drawer: event.item }); }, error: function(event) { - self.raiseEvent("add-layer-failed", event); + _this.raiseEvent("add-layer-failed", event); } }); @@ -1354,46 +1347,31 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype, return this; }, - /** - * @function - * @private - */ + // deprecated getLayerAtLevel: function( level ) { $.console.error( "[Viewer.getLayerAtLevel] this function is deprecated; use World.getItemAt() instead." ); return this.world.getItemAt(level); }, - /** - * @function - * @private - */ + // deprecated getLevelOfLayer: function( drawer ) { $.console.error( "[Viewer.getLevelOfLayer] this function is deprecated; use World.getIndexOfItem() instead." ); return this.world.getIndexOfItem(drawer); }, - /** - * @function - * @private - */ + // deprecated getLayersCount: function() { $.console.error( "[Viewer.getLayersCount] this function is deprecated; use World.getItemCount() instead." ); return this.world.getItemCount(); }, - /** - * @function - * @private - */ + // deprecated setLayerLevel: function( drawer, level ) { $.console.error( "[Viewer.setLayerLevel] this function is deprecated; use World.setItemIndex() instead." ); return this.world.setItemIndex(drawer, level); }, - /** - * @function - * @private - */ + // deprecated removeLayer: function( drawer ) { $.console.error( "[Viewer.removeLayer] this function is deprecated; use World.removeItem() instead." ); return this.world.removeItem(drawer); diff --git a/src/viewport.js b/src/viewport.js index fab50455..2ecb4a8d 100644 --- a/src/viewport.js +++ b/src/viewport.js @@ -37,10 +37,23 @@ /** * @class Viewport - * @classdesc Handles coordinate-related functionality (zoom, pan, rotation, etc.) for an {@link OpenSeadragon.Viewer}. - * A new instance is created for each TileSource opened (see {@link OpenSeadragon.Viewer#viewport}). - * * @memberof OpenSeadragon + * @classdesc Handles coordinate-related functionality (zoom, pan, rotation, etc.) + * for an {@link OpenSeadragon.Viewer}. + * @param {Object} options - Options for this Viewport. + * @param {Object} [margins] - See viewportMargins in {@link OpenSeadragon.Options}. + * @param {Number} [springStiffness] - See springStiffness in {@link OpenSeadragon.Options}. + * @param {Number} [animationTime] - See animationTime in {@link OpenSeadragon.Options}. + * @param {Number} [minZoomImageRatio] - See minZoomImageRatio in {@link OpenSeadragon.Options}. + * @param {Number} [maxZoomPixelRatio] - See maxZoomPixelRatio in {@link OpenSeadragon.Options}. + * @param {Number} [visibilityRatio] - See visibilityRatio in {@link OpenSeadragon.Options}. + * @param {Boolean} [wrapHorizontal] - See wrapHorizontal in {@link OpenSeadragon.Options}. + * @param {Boolean} [wrapVertical] - See wrapVertical in {@link OpenSeadragon.Options}. + * @param {Number} [defaultZoomLevel] - See defaultZoomLevel in {@link OpenSeadragon.Options}. + * @param {Number} [minZoomLevel] - See minZoomLevel in {@link OpenSeadragon.Options}. + * @param {Number} [maxZoomLevel] - See maxZoomLevel in {@link OpenSeadragon.Options}. + * @param {Number} [degrees] - See degrees in {@link OpenSeadragon.Options}. + * @param {Boolean} [homeFillsViewer] - See homeFillsViewer in {@link OpenSeadragon.Options}. */ $.Viewport = function( options ) { @@ -933,9 +946,7 @@ $.Viewport.prototype = /** @lends OpenSeadragon.Viewport.prototype */{ return this._pixelFromPoint(point, this.getBounds( current )); }, - /** - * @private - */ + // private _pixelFromPoint: function( point, bounds ) { return point.minus( bounds.getTopLeft() diff --git a/src/world.js b/src/world.js index 3b39861f..3e4d3924 100644 --- a/src/world.js +++ b/src/world.js @@ -35,14 +35,12 @@ (function( $ ){ /** - * Keeps track of all of the tiled images in the scene. - * * @class World - * @classdesc - * * @memberof OpenSeadragon * @extends OpenSeadragon.EventSource - * @param {OpenSeadragon.Options} options - World options. + * @classdesc Keeps track of all of the tiled images in the scene. + * @param {Object} options - World options. + * @param {OpenSeadragon.Viewer} options.viewer - The Viewer that owns this World. **/ $.World = function( options ) { $.console.assert( options.viewer, "[World] options.viewer is required" ); @@ -59,7 +57,7 @@ $.extend( $.World.prototype, $.EventSource.prototype, /** @lends OpenSeadragon.W /** * Add the specified item. * @param {OpenSeadragon.TiledImage} item - The item to add. - * @param {Number} options.index - index for the item (optional). + * @param {Number} [options.index] - Index for the item. If not specified, goes at the top. * @fires OpenSeadragon.World.event:add-item */ addItem: function( item, options ) { @@ -83,7 +81,7 @@ $.extend( $.World.prototype, $.EventSource.prototype, /** @lends OpenSeadragon.W * @memberOf OpenSeadragon.World * @type {object} * @property {OpenSeadragon.Viewer} eventSource - A reference to the World which raised the event. - * @property {OpenSeadragon.Drawer} item - The item that has been added + * @property {OpenSeadragon.TiledImage} item - The item that has been added. * @property {?Object} userData - Arbitrary subscriber-defined object. */ this.raiseEvent( 'add-item', { @@ -112,7 +110,6 @@ $.extend( $.World.prototype, $.EventSource.prototype, /** @lends OpenSeadragon.W }, /** - * Get the number of items used. * @returns {Number} The number of items used. */ getItemCount: function() { @@ -164,7 +161,6 @@ $.extend( $.World.prototype, $.EventSource.prototype, /** @lends OpenSeadragon.W /** * Remove an item. - * @function * @param {OpenSeadragon.TiledImage} item - The item to remove. * @fires OpenSeadragon.World.event:remove-item */ @@ -184,7 +180,6 @@ $.extend( $.World.prototype, $.EventSource.prototype, /** @lends OpenSeadragon.W /** * Remove all items. - * @function * @fires OpenSeadragon.World.event:remove-item */ removeAll: function() { @@ -200,7 +195,6 @@ $.extend( $.World.prototype, $.EventSource.prototype, /** @lends OpenSeadragon.W /** * Clears all tiles and triggers updates for all items. - * @function */ resetItems: function() { for ( var i = 0; i < this._items.length; i++ ) { @@ -210,7 +204,6 @@ $.extend( $.World.prototype, $.EventSource.prototype, /** @lends OpenSeadragon.W /** * Updates (i.e. draws) all items. - * @function */ update: function() { for ( var i = 0; i < this._items.length; i++ ) { @@ -221,7 +214,6 @@ $.extend( $.World.prototype, $.EventSource.prototype, /** @lends OpenSeadragon.W }, /** - * @function * @returns {Boolean} true if any items need updating. */ needsUpdate: function() { @@ -234,8 +226,7 @@ $.extend( $.World.prototype, $.EventSource.prototype, /** @lends OpenSeadragon.W }, /** - * @function - * @returns {OpenSeadragon.Rect} the smallest rectangle that encloses all items, in world coordinates. + * @returns {OpenSeadragon.Rect} The smallest rectangle that encloses all items, in world coordinates. */ getHomeBounds: function() { return this._homeBounds.clone(); @@ -245,17 +236,13 @@ $.extend( $.World.prototype, $.EventSource.prototype, /** @lends OpenSeadragon.W * To facilitate zoom constraints, we keep track of the pixel density of the * densest item in the World (i.e. the item whose content size to world size * ratio is the highest) and save it as this "content factor". - * @function * @returns {Number} the number of content units per world unit. */ getContentFactor: function() { return this._contentFactor; }, - /** - * @function - * @private - */ + // private _figureSizes: function() { if ( !this._items.length ) { this._homeBounds = new $.Rect(0, 0, 1, 1); @@ -284,10 +271,7 @@ $.extend( $.World.prototype, $.EventSource.prototype, /** @lends OpenSeadragon.W this._homeBounds.height * this._contentFactor); }, - /** - * @function - * @private - */ + // private _raiseRemoveItem: function(item) { /** * Raised when a item is removed. From 8466a91470f69f0de01ca72e26a3e63cfa63fcbd Mon Sep 17 00:00:00 2001 From: Ian Gilman Date: Tue, 4 Nov 2014 11:57:58 -0800 Subject: [PATCH 2/7] One more doc fix --- src/viewport.js | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/viewport.js b/src/viewport.js index 2ecb4a8d..abb4e641 100644 --- a/src/viewport.js +++ b/src/viewport.js @@ -41,19 +41,19 @@ * @classdesc Handles coordinate-related functionality (zoom, pan, rotation, etc.) * for an {@link OpenSeadragon.Viewer}. * @param {Object} options - Options for this Viewport. - * @param {Object} [margins] - See viewportMargins in {@link OpenSeadragon.Options}. - * @param {Number} [springStiffness] - See springStiffness in {@link OpenSeadragon.Options}. - * @param {Number} [animationTime] - See animationTime in {@link OpenSeadragon.Options}. - * @param {Number} [minZoomImageRatio] - See minZoomImageRatio in {@link OpenSeadragon.Options}. - * @param {Number} [maxZoomPixelRatio] - See maxZoomPixelRatio in {@link OpenSeadragon.Options}. - * @param {Number} [visibilityRatio] - See visibilityRatio in {@link OpenSeadragon.Options}. - * @param {Boolean} [wrapHorizontal] - See wrapHorizontal in {@link OpenSeadragon.Options}. - * @param {Boolean} [wrapVertical] - See wrapVertical in {@link OpenSeadragon.Options}. - * @param {Number} [defaultZoomLevel] - See defaultZoomLevel in {@link OpenSeadragon.Options}. - * @param {Number} [minZoomLevel] - See minZoomLevel in {@link OpenSeadragon.Options}. - * @param {Number} [maxZoomLevel] - See maxZoomLevel in {@link OpenSeadragon.Options}. - * @param {Number} [degrees] - See degrees in {@link OpenSeadragon.Options}. - * @param {Boolean} [homeFillsViewer] - See homeFillsViewer in {@link OpenSeadragon.Options}. + * @param {Object} [options.margins] - See viewportMargins in {@link OpenSeadragon.Options}. + * @param {Number} [options.springStiffness] - See springStiffness in {@link OpenSeadragon.Options}. + * @param {Number} [options.animationTime] - See animationTime in {@link OpenSeadragon.Options}. + * @param {Number} [options.minZoomImageRatio] - See minZoomImageRatio in {@link OpenSeadragon.Options}. + * @param {Number} [options.maxZoomPixelRatio] - See maxZoomPixelRatio in {@link OpenSeadragon.Options}. + * @param {Number} [options.visibilityRatio] - See visibilityRatio in {@link OpenSeadragon.Options}. + * @param {Boolean} [options.wrapHorizontal] - See wrapHorizontal in {@link OpenSeadragon.Options}. + * @param {Boolean} [options.wrapVertical] - See wrapVertical in {@link OpenSeadragon.Options}. + * @param {Number} [options.defaultZoomLevel] - See defaultZoomLevel in {@link OpenSeadragon.Options}. + * @param {Number} [options.minZoomLevel] - See minZoomLevel in {@link OpenSeadragon.Options}. + * @param {Number} [options.maxZoomLevel] - See maxZoomLevel in {@link OpenSeadragon.Options}. + * @param {Number} [options.degrees] - See degrees in {@link OpenSeadragon.Options}. + * @param {Boolean} [options.homeFillsViewer] - See homeFillsViewer in {@link OpenSeadragon.Options}. */ $.Viewport = function( options ) { From 864127989047282808cdcad590b305a9d4d57ed0 Mon Sep 17 00:00:00 2001 From: Ian Gilman Date: Wed, 5 Nov 2014 13:48:27 -0800 Subject: [PATCH 3/7] Better tile caching for duplicate images --- src/tile.js | 28 +++++----- src/tilecache.js | 96 +++++++++++++++++++++++++++++++++-- src/tiledimage.js | 13 +++++ test/demo/collections/main.js | 32 +++++++----- 4 files changed, 137 insertions(+), 32 deletions(-) diff --git a/src/tile.js b/src/tile.js index 9aa4bde4..b54e9b32 100644 --- a/src/tile.js +++ b/src/tile.js @@ -33,7 +33,7 @@ */ (function( $ ){ - var TILE_CACHE = {}; + /** * @class Tile * @memberof OpenSeadragon @@ -241,16 +241,23 @@ $.Tile.prototype = /** @lends OpenSeadragon.Tile.prototype */{ rendered, canvas; - if ( !this.loaded || !( this.image || TILE_CACHE[ this.url ] ) ){ + if (!this.cacheImageRecord) { + $.console.warn('[Tile.drawCanvas] attempting to draw tile %s when it\'s not cached', this.toString()); + return; + } + + rendered = this.cacheImageRecord.getRenderedContext(); + + if ( !this.loaded || !( this.image || rendered) ){ $.console.warn( "Attempting to draw tile %s when it's not yet loaded.", this.toString() ); + return; } - context.globalAlpha = this.opacity; - //context.save(); + context.globalAlpha = this.opacity; //if we are supposed to be rendering fully opaque rectangle, //ie its done fading or fading is turned off, and if we are drawing @@ -268,24 +275,21 @@ $.Tile.prototype = /** @lends OpenSeadragon.Tile.prototype */{ } - if( !TILE_CACHE[ this.url ] ){ + if(!rendered){ canvas = document.createElement( 'canvas' ); canvas.width = this.image.width; canvas.height = this.image.height; rendered = canvas.getContext('2d'); rendered.drawImage( this.image, 0, 0 ); - TILE_CACHE[ this.url ] = rendered; + this.cacheImageRecord.setRenderedContext(rendered); //since we are caching the prerendered image on a canvas //allow the image to not be held in memory this.image = null; } - rendered = TILE_CACHE[ this.url ]; - // This gives the application a chance to make image manipulation changes as we are rendering the image drawingHandler({context: context, tile: this, rendered: rendered}); - //rendered.save(); context.drawImage( rendered.canvas, 0, @@ -297,9 +301,6 @@ $.Tile.prototype = /** @lends OpenSeadragon.Tile.prototype */{ size.x, size.y ); - //rendered.restore(); - - //context.restore(); }, /** @@ -313,9 +314,6 @@ $.Tile.prototype = /** @lends OpenSeadragon.Tile.prototype */{ if ( this.element && this.element.parentNode ) { this.element.parentNode.removeChild( this.element ); } - if ( TILE_CACHE[ this.url ]){ - delete TILE_CACHE[ this.url ]; - } this.element = null; this.imgElement = null; diff --git a/src/tilecache.js b/src/tilecache.js index 71a8f25a..627ecc54 100644 --- a/src/tilecache.js +++ b/src/tilecache.js @@ -43,6 +43,53 @@ var TileRecord = function( options ) { this.tiledImage = options.tiledImage; }; +// private +var ImageRecord = function(options) { + $.console.assert( options, "[ImageRecord] options is required" ); + $.console.assert( options.image, "[ImageRecord] options.image is required" ); + this._image = options.image; + this._tiles = []; +}; + +ImageRecord.prototype = { + destroy: function() { + this._image = null; + this._renderedContext = null; + this._tiles = null; + }, + + getImage: function() { + return this._image; + }, + + getRenderedContext: function() { + return this._renderedContext; + }, + + setRenderedContext: function(renderedContext) { + this._renderedContext = renderedContext; + }, + + addTile: function(tile) { + this._tiles.push(tile); + }, + + removeTile: function(tile) { + for (var i = 0; i < this._tiles.length; i++) { + if (this._tiles[i] === tile) { + this._tiles.splice(i, 1); + return; + } + } + + $.console.warn('[ImageRecord.removeTile] trying to remove unknown tile', tile); + }, + + getTileCount: function() { + return this._tiles.length; + } +}; + /** * @class TileCache * @memberof OpenSeadragon @@ -54,8 +101,10 @@ var TileRecord = function( options ) { $.TileCache = function( options ) { options = options || {}; - this._tilesLoaded = []; this._maxImageCacheCount = options.maxImageCacheCount || $.DEFAULT_SETTINGS.maxImageCacheCount; + this._tilesLoaded = []; + this._imagesLoaded = []; + this._imagesLoadedCount = 0; }; $.TileCache.prototype = /** @lends OpenSeadragon.TileCache.prototype */{ @@ -69,7 +118,10 @@ $.TileCache.prototype = /** @lends OpenSeadragon.TileCache.prototype */{ /** * Caches the specified tile, removing an old tile if necessary to stay under the - * maxImageCacheCount specified on construction. + * maxImageCacheCount specified on construction. Note that if multiple tiles reference + * the same image, there may be more tiles than maxImageCacheCount; the goal is to keep + * the number of images below that number. Note, as well, that even the number of images + * may temporarily surpass that number, but should eventually come back down to the max specified. * @param {Object} options - Tile info. * @param {OpenSeadragon.Tile} options.tile - The tile to cache. * @param {OpenSeadragon.TiledImage} options.tiledImage - The TiledImage that owns that tile. @@ -80,12 +132,28 @@ $.TileCache.prototype = /** @lends OpenSeadragon.TileCache.prototype */{ cacheTile: function( options ) { $.console.assert( options, "[TileCache.cacheTile] options is required" ); $.console.assert( options.tile, "[TileCache.cacheTile] options.tile is required" ); + $.console.assert( options.tile.url, "[TileCache.cacheTile] options.tile.url is required" ); + $.console.assert( options.tile.image, "[TileCache.cacheTile] options.tile.image is required" ); $.console.assert( options.tiledImage, "[TileCache.cacheTile] options.tiledImage is required" ); var cutoff = options.cutoff || 0; var insertionIndex = this._tilesLoaded.length; - if ( this._tilesLoaded.length >= this._maxImageCacheCount ) { + var imageRecord = this._imagesLoaded[options.tile.url]; + if (!imageRecord) { + imageRecord = this._imagesLoaded[options.tile.url] = new ImageRecord({ + image: options.tile.image + }); + + this._imagesLoadedCount++; + } + + imageRecord.addTile(options.tile); + options.tile.cacheImageRecord = imageRecord; + + // Note that just because we're unloading a tile doesn't necessarily mean + // we're unloading an image. With repeated calls it should sort itself out, though. + if ( this._imagesLoadedCount >= this._maxImageCacheCount ) { var worstTile = null; var worstTileIndex = -1; var prevTile, worstTime, worstLevel, prevTime, prevLevel, prevTileRecord; @@ -115,7 +183,7 @@ $.TileCache.prototype = /** @lends OpenSeadragon.TileCache.prototype */{ } if ( worstTile && worstTileIndex >= 0 ) { - worstTile.unload(); + this._unloadTile(worstTile); insertionIndex = worstTileIndex; } } @@ -134,11 +202,29 @@ $.TileCache.prototype = /** @lends OpenSeadragon.TileCache.prototype */{ for ( var i = 0; i < this._tilesLoaded.length; ++i ) { tileRecord = this._tilesLoaded[ i ]; if ( tileRecord.tiledImage === tiledImage ) { - tileRecord.tile.unload(); + this._unloadTile(tileRecord.tile); this._tilesLoaded.splice( i, 1 ); i--; } } + }, + + getImageRecord: function(url) { + return this._imagesLoaded[url]; + }, + + // private + _unloadTile: function(tile) { + tile.unload(); + tile.cacheImageRecord = null; + + var imageRecord = this._imagesLoaded[tile.url]; + imageRecord.removeTile(tile); + if (!imageRecord.getTileCount()) { + imageRecord.destroy(); + delete this._imagesLoaded[tile.url]; + this._imagesLoadedCount--; + } } }; diff --git a/src/tiledimage.js b/src/tiledimage.js index dea44ef0..6d169d40 100644 --- a/src/tiledimage.js +++ b/src/tiledimage.js @@ -485,6 +485,19 @@ function updateTile( tiledImage, drawLevel, haveDrawn, x, y, level, levelOpacity tiledImage ); + if (!tile.loaded) { + var imageRecord = tiledImage._tileCache.getImageRecord(tile.url); + if (imageRecord) { + tile.loaded = true; + tile.image = imageRecord.getImage(); + + tiledImage._tileCache.cacheTile({ + tile: tile, + tiledImage: tiledImage + }); + } + } + if ( tile.loaded ) { var needsUpdate = blendTile( tiledImage, diff --git a/test/demo/collections/main.js b/test/demo/collections/main.js index f558fa66..2479166a 100644 --- a/test/demo/collections/main.js +++ b/test/demo/collections/main.js @@ -9,12 +9,15 @@ var testInitialOpen = false; var testOverlays = false; var testMargins = false; + var testNavigator = false; var margins; var config = { debugMode: true, zoomPerScroll: 1.02, - showNavigator: true, + showNavigator: testNavigator, + wrapHorizontal: true, + wrapVertical: true, id: "contentDiv", prefixUrl: "../../../build/openseadragon/images/" }; @@ -83,7 +86,7 @@ } // this.crossTest3(); - this.basicTest(); + this.crossTest2(); }, // ---------- @@ -119,7 +122,8 @@ self.viewer.addTiledImage( options ); }); - this.viewer.open("../../data/tall.dzi", { + this.viewer.open({ + tileSource: "../../data/tall.dzi", x: 1.5, y: 0, width: 1 @@ -129,12 +133,13 @@ // ---------- crossTest2: function() { this.viewer.open([ + // { + // tileSource: "../../data/tall.dzi", + // x: 1.5, + // y: 0, + // width: 1 + // }, { - tileSource: "../../data/tall.dzi", - x: 1.5, - y: 0, - width: 1 - }, { tileSource: '../../data/wide.dzi', opacity: 1, x: 0, @@ -184,7 +189,7 @@ self.viewer.world.addHandler('add-item', function() { loaded++; if (loaded === expected) { - self.viewer.viewport.goHome(); + self.viewer.viewport.goHome(true); } }); @@ -208,7 +213,8 @@ } }); - this.viewer.open("../../data/testpattern.dzi", { + this.viewer.open({ + tileSource: "../../data/testpattern.dzi", x: startX, y: 0, width: 1 @@ -217,7 +223,8 @@ // ---------- bigTest: function() { - this.viewer.open("../../data/testpattern.dzi", { + this.viewer.open({ + tileSource: "../../data/testpattern.dzi", x: -2, y: -2, width: 6 @@ -246,7 +253,8 @@ } }; - this.viewer.open(dzi, { + this.viewer.open({ + tileSource: dzi, width: 100 }); }, From e52e2fef3461968e62c98828ea6a6a98087cd9ee Mon Sep 17 00:00:00 2001 From: Ian Gilman Date: Wed, 5 Nov 2014 14:48:37 -0800 Subject: [PATCH 4/7] Improved docs --- src/imageLoader.js | 32 ++++++++++---------------------- src/tilecache.js | 11 +++++++++-- src/tiledimage.js | 2 ++ 3 files changed, 21 insertions(+), 24 deletions(-) diff --git a/src/imageLoader.js b/src/imageLoader.js index 0f79546c..1934051f 100644 --- a/src/imageLoader.js +++ b/src/imageLoader.js @@ -3,7 +3,7 @@ * * Copyright (C) 2009 CodePlex Foundation * Copyright (C) 2010-2013 OpenSeadragon contributors - + * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: @@ -34,23 +34,14 @@ (function( $ ){ -/** - * @private - * @class ImageJob - * @classdesc Handles loading a single image for use in a single {@link OpenSeadragon.Tile}. - * - * @memberof OpenSeadragon - * @param {String} source - URL of image to download. - * @param {String} crossOriginPolicy - CORS policy to use for downloads - * @param {Function} callback - Called once image has finished downloading. - */ +// private class function ImageJob ( options ) { - + $.extend( true, this, { timeout: $.DEFAULT_SETTINGS.timeout, jobId: null }, options ); - + /** * Image object which will contain downloaded image. * @member {Image} image @@ -60,11 +51,6 @@ function ImageJob ( options ) { } ImageJob.prototype = { - - /** - * Initiates downloading of associated image. - * @method - */ start: function(){ var _this = this; @@ -104,11 +90,13 @@ ImageJob.prototype = { }; /** - * @class + * @class ImageLoader + * @memberof OpenSeadragon * @classdesc Handles downloading of a set of images using asynchronous queue pattern. + * You generally won't have to interact with the ImageLoader directly. */ $.ImageLoader = function() { - + $.extend( true, this, { jobLimit: $.DEFAULT_SETTINGS.imageLoaderLimit, jobQueue: [], @@ -117,8 +105,8 @@ $.ImageLoader = function() { }; -$.ImageLoader.prototype = { - +$.ImageLoader.prototype = /** @lends OpenSeadragon.ImageLoader.prototype */{ + /** * Add an unloaded image to the loader queue. * @method diff --git a/src/tilecache.js b/src/tilecache.js index 627ecc54..a643ae49 100644 --- a/src/tilecache.js +++ b/src/tilecache.js @@ -34,7 +34,7 @@ (function( $ ){ -// private +// private class var TileRecord = function( options ) { $.console.assert( options, "[TileCache.cacheTile] options is required" ); $.console.assert( options.tile, "[TileCache.cacheTile] options.tile is required" ); @@ -43,7 +43,7 @@ var TileRecord = function( options ) { this.tiledImage = options.tiledImage; }; -// private +// private class var ImageRecord = function(options) { $.console.assert( options, "[ImageRecord] options is required" ); $.console.assert( options.image, "[ImageRecord] options.image is required" ); @@ -71,6 +71,7 @@ ImageRecord.prototype = { }, addTile: function(tile) { + $.console.assert(tile, '[ImageRecord.addTile] tile is required'); this._tiles.push(tile); }, @@ -94,6 +95,7 @@ ImageRecord.prototype = { * @class TileCache * @memberof OpenSeadragon * @classdesc Stores all the tiles displayed in a {@link OpenSeadragon.Viewer}. + * You generally won't have to interact with the TileCache directly. * @param {Object} options - Configuration for this TileCache. * @param {Number} [options.maxImageCacheCount] - See maxImageCacheCount in * {@link OpenSeadragon.Options} for details. @@ -196,8 +198,10 @@ $.TileCache.prototype = /** @lends OpenSeadragon.TileCache.prototype */{ /** * Clears all tiles associated with the specified tiledImage. + * @param {OpenSeadragon.TiledImage} tiledImage */ clearTilesFor: function( tiledImage ) { + $.console.assert(tiledImage, '[TileCache.clearTilesFor] tiledImage is required'); var tileRecord; for ( var i = 0; i < this._tilesLoaded.length; ++i ) { tileRecord = this._tilesLoaded[ i ]; @@ -209,12 +213,15 @@ $.TileCache.prototype = /** @lends OpenSeadragon.TileCache.prototype */{ } }, + // private getImageRecord: function(url) { + $.console.assert(url, '[TileCache.getImageRecord] url is required'); return this._imagesLoaded[url]; }, // private _unloadTile: function(tile) { + $.console.assert(tile, '[TileCache._unloadTile] tile is required'); tile.unload(); tile.cacheImageRecord = null; diff --git a/src/tiledimage.js b/src/tiledimage.js index 6d169d40..4467d971 100644 --- a/src/tiledimage.js +++ b/src/tiledimage.js @@ -35,6 +35,8 @@ (function( $ ){ /** + * You shouldn't have to create a TiledImage directly; use {@link OpenSeadragon.Viewer#open} + * or {@link OpenSeadragon.Viewer#addTiledImage} instead. * @class TiledImage * @memberof OpenSeadragon * @classdesc Handles rendering of tiles for an {@link OpenSeadragon.Viewer}. From a9c9478752cd06a70b5de27a54f8011c501015c8 Mon Sep 17 00:00:00 2001 From: Ian Gilman Date: Wed, 5 Nov 2014 15:24:31 -0800 Subject: [PATCH 5/7] Wraparound now works for images of other widths than 1 --- src/tiledimage.js | 4 ++-- test/demo/collections/main.js | 21 +++++++++++---------- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/tiledimage.js b/src/tiledimage.js index 4467d971..8079b375 100644 --- a/src/tiledimage.js +++ b/src/tiledimage.js @@ -545,8 +545,8 @@ function getTile( x, y, level, tileSource, tilesMatrix, time, numTiles, worldWid exists = tileSource.tileExists( level, xMod, yMod ); url = tileSource.getTileUrl( level, xMod, yMod ); - bounds.x += worldWidth * ( x - xMod ) / numTiles.x; - bounds.y += worldHeight * ( y - yMod ) / numTiles.y; + bounds.x += ( x - xMod ) / numTiles.x; + bounds.y += (worldHeight / worldWidth) * (( y - yMod ) / numTiles.y); tilesMatrix[ level ][ x ][ y ] = new $.Tile( level, diff --git a/test/demo/collections/main.js b/test/demo/collections/main.js index 2479166a..0e3ab824 100644 --- a/test/demo/collections/main.js +++ b/test/demo/collections/main.js @@ -16,8 +16,8 @@ debugMode: true, zoomPerScroll: 1.02, showNavigator: testNavigator, - wrapHorizontal: true, - wrapVertical: true, + // wrapHorizontal: true, + // wrapVertical: true, id: "contentDiv", prefixUrl: "../../../build/openseadragon/images/" }; @@ -96,7 +96,9 @@ this.viewer.addHandler('open', function() { }); - this.viewer.open("../../data/testpattern.dzi"); + this.viewer.open({ + tileSource: "../../data/testpattern.dzi" + }); }, // ---------- @@ -133,15 +135,14 @@ // ---------- crossTest2: function() { this.viewer.open([ - // { - // tileSource: "../../data/tall.dzi", - // x: 1.5, - // y: 0, - // width: 1 - // }, + { + tileSource: "../../data/tall.dzi", + x: 1.5, + y: 0, + width: 1 + }, { tileSource: '../../data/wide.dzi', - opacity: 1, x: 0, y: 1.5, height: 1 From 8bdc55bd6324a5a046088d57dd82ed1cb9662641 Mon Sep 17 00:00:00 2001 From: Ian Gilman Date: Wed, 5 Nov 2014 15:57:44 -0800 Subject: [PATCH 6/7] Fixed fitVertically and fitHorizontally --- src/viewport.js | 51 +++++--------------------------- test/demo/collections/index.html | 1 + test/demo/collections/main.js | 2 +- 3 files changed, 10 insertions(+), 44 deletions(-) diff --git a/src/viewport.js b/src/viewport.js index abb4e641..1f07ebbe 100644 --- a/src/viewport.js +++ b/src/viewport.js @@ -178,15 +178,6 @@ $.Viewport.prototype = /** @lends OpenSeadragon.Viewport.prototype */{ this.contentAspectX = this.contentSize.x / this.contentSize.y; this.contentAspectY = this.contentSize.y / this.contentSize.x; - // TODO: seems like fitWidthBounds and fitHeightBounds should be thin slices - // across the appropriate axis, centered in the image, rather than what we have - // here. - this.fitWidthBounds = new $.Rect(this.homeBounds.x, this.homeBounds.y, - this.homeBounds.width, this.homeBounds.width); - - this.fitHeightBounds = new $.Rect(this.homeBounds.x, this.homeBounds.y, - this.homeBounds.height, this.homeBounds.height); - if( this.viewer ){ /** * Raised when the viewer's content size or home bounds are reset @@ -631,53 +622,27 @@ $.Viewport.prototype = /** @lends OpenSeadragon.Viewport.prototype */{ }, /** - * @function + * Zooms so the image just fills the viewer vertically. * @param {Boolean} immediately * @return {OpenSeadragon.Viewport} Chainable. */ fitVertically: function( immediately ) { - var center = this.getCenter(); + var box = new $.Rect(this.homeBounds.x + (this.homeBounds.width / 2), this.homeBounds.y, + 0, this.homeBounds.height); - if ( this.wrapHorizontal ) { - center.x = ( 1 + ( center.x % 1 ) ) % 1; - this.centerSpringX.resetTo( center.x ); - this.centerSpringX.update(); - } - - if ( this.wrapVertical ) { - center.y = ( - this.contentAspectY + ( center.y % this.contentAspectY ) - ) % this.contentAspectY; - this.centerSpringY.resetTo( center.y ); - this.centerSpringY.update(); - } - - return this.fitBounds( this.fitHeightBounds, immediately ); + return this.fitBounds( box, immediately ); }, /** - * @function + * Zooms so the image just fills the viewer horizontally. * @param {Boolean} immediately * @return {OpenSeadragon.Viewport} Chainable. */ fitHorizontally: function( immediately ) { - var center = this.getCenter(); + var box = new $.Rect(this.homeBounds.x, this.homeBounds.y + (this.homeBounds.height / 2), + this.homeBounds.width, 0); - if ( this.wrapHorizontal ) { - center.x = ( - this.contentAspectX + ( center.x % this.contentAspectX ) - ) % this.contentAspectX; - this.centerSpringX.resetTo( center.x ); - this.centerSpringX.update(); - } - - if ( this.wrapVertical ) { - center.y = ( 1 + ( center.y % 1 ) ) % 1; - this.centerSpringY.resetTo( center.y ); - this.centerSpringY.update(); - } - - return this.fitBounds( this.fitWidthBounds, immediately ); + return this.fitBounds( box, immediately ); }, diff --git a/test/demo/collections/index.html b/test/demo/collections/index.html index fc1766cc..b6aca4a1 100644 --- a/test/demo/collections/index.html +++ b/test/demo/collections/index.html @@ -12,6 +12,7 @@ .openseadragon1 { width: 100%; height: 100%; + margin: 0; } .openseadragon-overlay { diff --git a/test/demo/collections/main.js b/test/demo/collections/main.js index 0e3ab824..af83c343 100644 --- a/test/demo/collections/main.js +++ b/test/demo/collections/main.js @@ -86,7 +86,7 @@ } // this.crossTest3(); - this.crossTest2(); + this.basicTest(); }, // ---------- From b5a9116a0bf2335bd6302c87d35271f8ffbf85a1 Mon Sep 17 00:00:00 2001 From: Ian Gilman Date: Wed, 5 Nov 2014 16:39:35 -0800 Subject: [PATCH 7/7] Fixed rotation with multiple images --- src/tiledimage.js | 29 ++++++++++++----------------- test/demo/collections/main.js | 4 ++-- 2 files changed, 14 insertions(+), 19 deletions(-) diff --git a/src/tiledimage.js b/src/tiledimage.js index 8079b375..c8ad9d93 100644 --- a/src/tiledimage.js +++ b/src/tiledimage.js @@ -195,8 +195,6 @@ function updateViewport( tiledImage ) { haveDrawn = false, currentTime = $.now(), viewportBounds = tiledImage.viewport.getBoundsWithMargins( true ), - viewportTL = viewportBounds.getTopLeft(), - viewportBR = viewportBounds.getBottomRight(), zeroRatioC = tiledImage.viewport.deltaPixelsFromPoints( tiledImage.source.getPixelRatio( 0 ), true @@ -223,10 +221,8 @@ function updateViewport( tiledImage ) { levelOpacity, levelVisibility; - viewportTL.x -= tiledImage._worldX; - viewportTL.y -= tiledImage._worldY; - viewportBR.x -= tiledImage._worldX; - viewportBR.y -= tiledImage._worldY; + viewportBounds.x -= tiledImage._worldX; + viewportBounds.y -= tiledImage._worldY; // Reset tile's internal drawn state while ( tiledImage.lastDrawn.length > 0 ) { @@ -236,27 +232,25 @@ function updateViewport( tiledImage ) { //Change bounds for rotation if (degrees === 90 || degrees === 270) { - var rotatedBounds = viewportBounds.rotate( degrees ); - viewportTL = rotatedBounds.getTopLeft(); - viewportBR = rotatedBounds.getBottomRight(); - } else if (degrees !== 0) { + viewportBounds = viewportBounds.rotate( degrees ); + } else if (degrees !== 0 && degrees !== 180) { // This is just an approximation. var orthBounds = viewportBounds.rotate(90); viewportBounds.x -= orthBounds.width / 2; viewportBounds.y -= orthBounds.height / 2; viewportBounds.width += orthBounds.width; viewportBounds.height += orthBounds.height; - viewportTL = viewportBounds.getTopLeft(); - viewportBR = viewportBounds.getBottomRight(); } + var viewportTL = viewportBounds.getTopLeft(); + var viewportBR = viewportBounds.getBottomRight(); + //Don't draw if completely outside of the viewport - if ( !tiledImage.wrapHorizontal && - ( viewportBR.x < 0 || viewportTL.x > tiledImage._worldWidth ) ) { + if ( !tiledImage.wrapHorizontal && (viewportBR.x < 0 || viewportTL.x > tiledImage._worldWidth ) ) { return; - } else if - ( !tiledImage.wrapVertical && - ( viewportBR.y < 0 || viewportTL.y > tiledImage._worldHeight ) ) { + } + + if ( !tiledImage.wrapVertical && ( viewportBR.y < 0 || viewportTL.y > tiledImage._worldHeight ) ) { return; } @@ -265,6 +259,7 @@ function updateViewport( tiledImage ) { viewportTL.x = Math.max( viewportTL.x, 0 ); viewportBR.x = Math.min( viewportBR.x, tiledImage._worldWidth ); } + if ( !tiledImage.wrapVertical ) { viewportTL.y = Math.max( viewportTL.y, 0 ); viewportBR.y = Math.min( viewportBR.y, tiledImage._worldHeight ); diff --git a/test/demo/collections/main.js b/test/demo/collections/main.js index af83c343..e9cde3d3 100644 --- a/test/demo/collections/main.js +++ b/test/demo/collections/main.js @@ -13,7 +13,7 @@ var margins; var config = { - debugMode: true, + // debugMode: true, zoomPerScroll: 1.02, showNavigator: testNavigator, // wrapHorizontal: true, @@ -86,7 +86,7 @@ } // this.crossTest3(); - this.basicTest(); + this.gridTest(); }, // ----------