diff --git a/src/tiledimage.js b/src/tiledimage.js index a925104c..248f0ece 100644 --- a/src/tiledimage.js +++ b/src/tiledimage.js @@ -570,32 +570,50 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag fitBounds: function(bounds, anchor, immediately) { anchor = anchor || $.Placement.CENTER; var anchorProperties = $.Placement.properties[anchor]; - if (bounds.getAspectRatio() > this.contentAspectX) { + var aspectRatio = this.contentAspectX; + var xOffset = 0; + var yOffset = 0; + var displayedWidthRatio = 1; + var displayedHeightRatio = 1; + if (this._clip) { + aspectRatio = this._clip.getAspectRatio(); + displayedWidthRatio = this._clip.width / this.source.dimensions.x; + displayedHeightRatio = this._clip.height / this.source.dimensions.y; + if (bounds.getAspectRatio() > aspectRatio) { + xOffset = this._clip.x / this._clip.height * bounds.height; + yOffset = this._clip.y / this._clip.height * bounds.height; + } else { + xOffset = this._clip.x / this._clip.width * bounds.width; + yOffset = this._clip.y / this._clip.width * bounds.width; + } + } + + if (bounds.getAspectRatio() > aspectRatio) { // We will have margins on the X axis - var targetWidth = bounds.height * this.contentAspectX; + var height = bounds.height / displayedHeightRatio; var marginLeft = 0; if (anchorProperties.isHorizontallyCentered) { - marginLeft = (bounds.width - targetWidth) / 2; + marginLeft = (bounds.width - bounds.height * aspectRatio) / 2; } else if (anchorProperties.isRight) { - marginLeft = bounds.width - targetWidth; + marginLeft = bounds.width - bounds.height * aspectRatio; } this.setPosition( - new $.Point(bounds.x + marginLeft, bounds.y), + new $.Point(bounds.x - xOffset + marginLeft, bounds.y - yOffset), immediately); - this.setHeight(bounds.height, immediately); + this.setHeight(height, immediately); } else { // We will have margins on the Y axis - var targetHeight = bounds.width / this.contentAspectX; + var width = bounds.width / displayedWidthRatio; var marginTop = 0; if (anchorProperties.isVerticallyCentered) { - marginTop = (bounds.height - targetHeight) / 2; + marginTop = (bounds.height - bounds.width / aspectRatio) / 2; } else if (anchorProperties.isBottom) { - marginTop = bounds.height - targetHeight; + marginTop = bounds.height - bounds.width / aspectRatio; } this.setPosition( - new $.Point(bounds.x, bounds.y + marginTop), + new $.Point(bounds.x - xOffset, bounds.y - yOffset + marginTop), immediately); - this.setWidth(bounds.width, immediately); + this.setWidth(width, immediately); } }, diff --git a/test/modules/tiledimage.js b/test/modules/tiledimage.js index 76b55541..f281d076 100644 --- a/test/modules/tiledimage.js +++ b/test/modules/tiledimage.js @@ -347,4 +347,48 @@ fitBoundsPlacement: OpenSeadragon.Placement.BOTTOM_RIGHT }]); }); + + asyncTest('fitBounds with clipping', function() { + + function assertRectEquals(actual, expected, message) { + ok(actual.equals(expected), message + ' should be ' + + expected.toString() + ', found ' + actual.toString()); + } + + viewer.addHandler('open', function openHandler() { + viewer.removeHandler('open', openHandler); + + var squareImage = viewer.world.getItemAt(0); + var actualBounds = squareImage.getBounds(true); + var expectedBounds = new OpenSeadragon.Rect(-1, -1, 2, 2); + assertRectEquals(actualBounds, expectedBounds, 'Square image bounds'); + + var tallImage = viewer.world.getItemAt(1); + actualBounds = tallImage.getBounds(true); + expectedBounds = new OpenSeadragon.Rect(1, 1, 2, 8); + assertRectEquals(actualBounds, expectedBounds, 'Tall image bounds'); + + var wideImage = viewer.world.getItemAt(2); + actualBounds = wideImage.getBounds(true); + expectedBounds = new OpenSeadragon.Rect(1, 1, 16, 4); + assertRectEquals(actualBounds, expectedBounds, 'Wide image bounds'); + start(); + }); + + viewer.open([{ + tileSource: '/test/data/testpattern.dzi', + clip: new OpenSeadragon.Rect(500, 500, 500, 500), + fitBounds: new OpenSeadragon.Rect(0, 0, 1, 1) + }, { + tileSource: '/test/data/tall.dzi', + clip: new OpenSeadragon.Rect(0, 0, 250, 100), + fitBounds: new OpenSeadragon.Rect(1, 1, 1, 2), + fitBoundsPlacement: OpenSeadragon.Placement.TOP + }, { + tileSource: '/test/data/wide.dzi', + clip: new OpenSeadragon.Rect(0, 0, 100, 250), + fitBounds: new OpenSeadragon.Rect(1, 1, 1, 2), + fitBoundsPlacement: OpenSeadragon.Placement.TOP_LEFT + }]); + }); })();