diff --git a/changelog.txt b/changelog.txt index 42979ad6..a01774af 100644 --- a/changelog.txt +++ b/changelog.txt @@ -9,12 +9,14 @@ OPENSEADRAGON CHANGELOG * Fixed flickering tiles with useCanvas=false when no cache is used (#661) * Added additional coordinates conversion methods to TiledImage (#662) * 'display: none' no longer gets reset on overlays during draw (#668) +* Added `preserveImageSizeOnResize` option (#666) +* Better error reporting for tile load failures (#679) +* Added collectionColumns as a configuration parameter (#680) * Added support for non-square tiles (#673) * TileSource.Options objects can now optionally provide tileWidth/tileWidth instead of tileSize for non-square tile support. * IIIFTileSources will now respect non-square tiles if available. * DEPRECATION: TileSource.getTileSize is deprecated use TileSource.getTileWidth and TileSource.getTileHeight instead. - 2.0.0: * True multi-image mode (#450) diff --git a/package.json b/package.json index c979f4b8..d2081b58 100644 --- a/package.json +++ b/package.json @@ -5,16 +5,16 @@ "devDependencies": { "grunt": "^0.4.5", "grunt-contrib-clean": "^0.5.0", - "grunt-text-replace": "^0.3.11", + "grunt-contrib-compress": "^0.9.1", "grunt-contrib-concat": "^0.4.0", - "grunt-git-describe": "^2.3.2", + "grunt-contrib-connect": "^0.7.1", + "grunt-contrib-jshint": "^0.10.0", "grunt-contrib-uglify": "^0.4.0", "grunt-contrib-watch": "^0.6.1", - "grunt-contrib-jshint": "^0.10.0", - "grunt-contrib-compress": "^0.9.1", - "grunt-contrib-connect": "^0.7.1", - "qunitjs": "^1.14.0", - "grunt-qunit-istanbul": "^0.4.5" + "grunt-git-describe": "^2.3.2", + "grunt-qunit-istanbul": "^0.5.0", + "grunt-text-replace": "^0.3.11", + "qunitjs": "^1.18.0" }, "scripts": { "test": "grunt test" diff --git a/src/imageloader.js b/src/imageloader.js index a61c8936..ef3a4f4f 100644 --- a/src/imageloader.js +++ b/src/imageloader.js @@ -51,6 +51,7 @@ function ImageJob ( options ) { } ImageJob.prototype = { + errorMsg: null, start: function(){ var _this = this; @@ -64,10 +65,12 @@ ImageJob.prototype = { _this.finish( true ); }; this.image.onabort = this.image.onerror = function(){ + _this.errorMsg = "Image load aborted"; _this.finish( false ); }; this.jobId = window.setTimeout( function(){ + _this.errorMsg = "Image load exceeded timeout"; _this.finish( false ); }, this.timeout); @@ -173,7 +176,7 @@ function completeJob( loader, job, callback ) { loader.jobsInProgress++; } - callback( job.image ); + callback( job.image, job.errorMsg ); } }( OpenSeadragon )); diff --git a/src/openseadragon.js b/src/openseadragon.js index 461f9d22..64349972 100644 --- a/src/openseadragon.js +++ b/src/openseadragon.js @@ -252,6 +252,9 @@ * @property {Boolean} [autoResize=true] * Set to false to prevent polling for viewer size changes. Useful for providing custom resize behavior. * + * @property {Boolean} [preserveImageSizeOnResize=false] + * Set to true to have the image size preserved when the viewer is resized. This requires autoResize=true (default). + * * @property {Number} [pixelsPerWheelLine=40] * For pixel-resolution scrolling devices, the number of pixels equal to one scroll line. * @@ -556,6 +559,10 @@ * If collectionMode is true, specifies how many rows the grid should have. Use 1 to make a line. * If collectionLayout is 'vertical', specifies how many columns instead. * + * @property {Number} [collectionColumns=0] + * If collectionMode is true, specifies how many columns the grid should have. Use 1 to make a line. + * If collectionLayout is 'vertical', specifies how many rows instead. Ignored if collectionRows is not set to a falsy value. + * * @property {String} [collectionLayout='horizontal'] * If collectionMode is true, specifies whether to arrange vertically or horizontally. * @@ -987,6 +994,7 @@ window.OpenSeadragon = window.OpenSeadragon || function( options ){ maxZoomPixelRatio: 1.1, //-> higher allows 'over zoom' into pixels pixelsPerWheelLine: 40, autoResize: true, + preserveImageSizeOnResize: false, // requires autoResize=true //DEFAULT CONTROL SETTINGS showSequenceControl: true, //SEQUENCE @@ -1035,6 +1043,7 @@ window.OpenSeadragon = window.OpenSeadragon || function( options ){ //COLLECTION VISUALIZATION SETTINGS collectionRows: 3, //or columns depending on layout + collectionColumns: 0, //columns in horizontal layout, rows in vertical layout collectionLayout: 'horizontal', //vertical collectionMode: false, collectionTileSize: 800, diff --git a/src/tiledimage.js b/src/tiledimage.js index ded6b480..4aaef1db 100644 --- a/src/tiledimage.js +++ b/src/tiledimage.js @@ -1011,8 +1011,8 @@ function loadTile( tiledImage, tile, time ) { tiledImage._imageLoader.addJob({ src: tile.url, crossOriginPolicy: tiledImage.crossOriginPolicy, - callback: function( image ){ - onTileLoad( tiledImage, tile, time, image ); + callback: function( image, errorMsg ){ + onTileLoad( tiledImage, tile, time, image, errorMsg ); }, abort: function() { tile.loading = false; @@ -1020,9 +1020,9 @@ function loadTile( tiledImage, tile, time ) { }); } -function onTileLoad( tiledImage, tile, time, image ) { +function onTileLoad( tiledImage, tile, time, image, errorMsg ) { if ( !image ) { - $.console.log( "Tile %s failed to load: %s", tile, tile.url ); + $.console.log( "Tile %s failed to load: %s - error: %s", tile, tile.url, errorMsg ); if( !tiledImage.debugMode ){ tile.loading = false; tile.exists = false; diff --git a/src/viewer.js b/src/viewer.js index 7143443d..01560f01 100644 --- a/src/viewer.js +++ b/src/viewer.js @@ -1318,6 +1318,7 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype, _this.world.arrange({ immediately: queueItem.options.collectionImmediately, rows: _this.collectionRows, + columns: _this.collectionColumns, layout: _this.collectionLayout, tileSize: _this.collectionTileSize, tileMargin: _this.collectionTileMargin @@ -1710,7 +1711,7 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype, * is closed which include when changing page. * @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 + * the element which will be 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 @@ -1770,6 +1771,8 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype, * 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 {Element|String} element - A reference to an element or an id for + * the element which is overlayed. * @param {OpenSeadragon.Point|OpenSeadragon.Rect} location - The point or * rectangle which will be overlayed. * @param {OpenSeadragon.OverlayPlacement} placement - The position of the @@ -2824,13 +2827,31 @@ function updateOnce( viewer ) { return; } + var containerSize; if ( viewer.autoResize ) { - var containerSize = _getSafeElemSize( viewer.container ); + containerSize = _getSafeElemSize( viewer.container ); if ( !containerSize.equals( THIS[ viewer.hash ].prevContainerSize ) ) { - // maintain image position - var oldBounds = viewer.viewport.getBounds(); - var oldCenter = viewer.viewport.getCenter(); - resizeViewportAndRecenter(viewer, containerSize, oldBounds, oldCenter); + if ( viewer.preserveImageSizeOnResize ) { + var prevContainerSize = THIS[ viewer.hash ].prevContainerSize; + var bounds = viewer.viewport.getBounds(true); + var deltaX = (containerSize.x - prevContainerSize.x); + var deltaY = (containerSize.y - prevContainerSize.y); + var viewportDiff = viewer.viewport.deltaPointsFromPixels(new OpenSeadragon.Point(deltaX, deltaY), true); + viewer.viewport.resize(new OpenSeadragon.Point(containerSize.x, containerSize.y), false); + + // Keep the center of the image in the center and just adjust the amount of image shown + bounds.width += viewportDiff.x; + bounds.height += viewportDiff.y; + bounds.x -= (viewportDiff.x / 2); + bounds.y -= (viewportDiff.y / 2); + viewer.viewport.fitBoundsWithConstraints(bounds, true); + } + else { + // maintain image position + var oldBounds = viewer.viewport.getBounds(); + var oldCenter = viewer.viewport.getCenter(); + resizeViewportAndRecenter(viewer, containerSize, oldBounds, oldCenter); + } THIS[ viewer.hash ].prevContainerSize = containerSize; THIS[ viewer.hash ].forceRedraw = true; } diff --git a/src/world.js b/src/world.js index c9e65225..73b28a67 100644 --- a/src/world.js +++ b/src/world.js @@ -281,6 +281,7 @@ $.extend( $.World.prototype, $.EventSource.prototype, /** @lends OpenSeadragon.W * @param {Boolean} [options.immediately=false] - Whether to animate to the new arrangement. * @param {String} [options.layout] - See collectionLayout in {@link OpenSeadragon.Options}. * @param {Number} [options.rows] - See collectionRows in {@link OpenSeadragon.Options}. + * @param {Number} [options.columns] - See collectionColumns in {@link OpenSeadragon.Options}. * @param {Number} [options.tileSize] - See collectionTileSize in {@link OpenSeadragon.Options}. * @param {Number} [options.tileMargin] - See collectionTileMargin in {@link OpenSeadragon.Options}. * @fires OpenSeadragon.World.event:metrics-change @@ -290,10 +291,16 @@ $.extend( $.World.prototype, $.EventSource.prototype, /** @lends OpenSeadragon.W var immediately = options.immediately || false; var layout = options.layout || $.DEFAULT_SETTINGS.collectionLayout; var rows = options.rows || $.DEFAULT_SETTINGS.collectionRows; + var columns = options.columns || $.DEFAULT_SETTINGS.collectionColumns; var tileSize = options.tileSize || $.DEFAULT_SETTINGS.collectionTileSize; var tileMargin = options.tileMargin || $.DEFAULT_SETTINGS.collectionTileMargin; var increment = tileSize + tileMargin; - var wrap = Math.ceil(this._items.length / rows); + var wrap; + if (!options.rows && columns) { + wrap = columns; + } else { + wrap = Math.ceil(this._items.length / rows); + } var x = 0; var y = 0; var item, box, width, height, position; diff --git a/test/demo/tilesource-swap.html b/test/demo/tilesource-swap.html new file mode 100644 index 00000000..3420927c --- /dev/null +++ b/test/demo/tilesource-swap.html @@ -0,0 +1,96 @@ + + + + TileSource Swapping + + + + + +
This is a demo of using a single image stand-in and then swapping to a full TileSource on zooming. Click the image to see it in action.
+
+ + + diff --git a/test/modules/world.js b/test/modules/world.js index ce63f02a..0c5aebf7 100644 --- a/test/modules/world.js +++ b/test/modules/world.js @@ -213,6 +213,26 @@ checkBounds(new OpenSeadragon.Rect(0, 0, 1, 4), 'one vertical column'); + viewer.world.arrange({ + layout: 'horizontal', + rows: false, + columns: 3, + tileSize: 1, + tileMargin: 0.5 + }); + + checkBounds(new OpenSeadragon.Rect(0, 0, 4, 1), 'three horizontal columns (one horizontal row)'); + + viewer.world.arrange({ + layout: 'vertical', + rows: false, + columns: 3, + tileSize: 1, + tileMargin: 0.5 + }); + + checkBounds(new OpenSeadragon.Rect(0, 0, 1, 4), 'three vertical rows (one vertical column)'); + start(); });