Fixed home/constraints for multi-image.

This commit is contained in:
Ian Gilman 2014-08-18 16:04:49 -07:00
parent 26e9575f41
commit 8efad6f3a0
8 changed files with 137 additions and 74 deletions

View File

@ -1,6 +1,8 @@
OPENSEADRAGON CHANGELOG OPENSEADRAGON CHANGELOG
======================= =======================
2.0.0: (in progress)
1.2.0: (in progress) 1.2.0: (in progress)
* New combined IIIF TileSource for 1.0 through 2.0 (#441) * New combined IIIF TileSource for 1.0 through 2.0 (#441)

View File

@ -60,6 +60,13 @@ $.Point = function( x, y ) {
}; };
$.Point.prototype = /** @lends OpenSeadragon.Point.prototype */{ $.Point.prototype = /** @lends OpenSeadragon.Point.prototype */{
/**
* @function
* @returns {OpenSeadragon.Point} a duplicate of this Point
*/
clone: function() {
return new $.Point(this.x, this.y);
},
/** /**
* Add another Point to this point and return a new Point. * Add another Point to this point and return a new Point.

View File

@ -75,6 +75,13 @@ $.Rect = function( x, y, width, height ) {
}; };
$.Rect.prototype = /** @lends OpenSeadragon.Rect.prototype */{ $.Rect.prototype = /** @lends OpenSeadragon.Rect.prototype */{
/**
* @function
* @returns {OpenSeadragon.Rect} a duplicate of this Rect
*/
clone: function() {
return new $.Rect(this.x, this.y, this.width, this.height);
},
/** /**
* The aspect ratio is simply the ratio of width to height. * The aspect ratio is simply the ratio of width to height.

View File

@ -155,6 +155,10 @@ $.TiledImage.prototype = /** @lends OpenSeadragon.TiledImage.prototype */{
getWorldBounds: function() { getWorldBounds: function() {
return new $.Rect( this._worldX, this._worldY, this._worldWidth, this._worldHeight ); return new $.Rect( this._worldX, this._worldY, this._worldWidth, this._worldHeight );
},
getContentSize: function() {
return new $.Point(this.source.dimensions.x, this.source.dimensions.y);
} }
}; };

View File

@ -333,7 +333,7 @@ $.Viewer = function( options ) {
_this.viewport.applyConstraints(); _this.viewport.applyConstraints();
return false; return false;
case 48://0|) case 48://0|)
_this.goHome(); _this.viewport.goHome();
_this.viewport.applyConstraints(); _this.viewport.applyConstraints();
return false; return false;
case 119://w case 119://w
@ -622,29 +622,6 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype,
this.element = null; this.element = null;
}, },
/**
* @function
* @param {Boolean} immediately
* @fires OpenSeadragon.Viewer.event:home
*/
goHome: function(immediately) {
/**
* Raised when the "home" operation occurs (see {@link OpenSeadragon.Viewport#goHome}).
*
* @event home
* @memberof OpenSeadragon.Viewer
* @type {object}
* @property {OpenSeadragon.Viewer} eventSource - A reference to the Viewer which raised this event.
* @property {Boolean} immediately
* @property {?Object} userData - Arbitrary subscriber-defined object.
*/
this.raiseEvent( 'home', {
immediately: immediately
});
this.viewport.fitBounds( this.world.getHomeBounds(), immediately );
},
/** /**
* @function * @function
* @return {Boolean} * @return {Boolean}
@ -1137,6 +1114,7 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype,
debugGridColor: _this.debugGridColor debugGridColor: _this.debugGridColor
}); });
_this.world.addItem( tiledImage ); _this.world.addItem( tiledImage );
_this.viewport.setHomeBounds(_this.world.getHomeBounds(), _this.world.getContentFactor());
if ( options.level !== undefined ) { if ( options.level !== undefined ) {
_this.world.setItemLevel( tiledImage, options.level ); _this.world.setItemLevel( tiledImage, options.level );
} }
@ -1868,7 +1846,6 @@ function openTileSource( viewer, source, options ) {
collectionMode: true, collectionMode: true,
collectionTileSource: _this.source, collectionTileSource: _this.source,
containerSize: THIS[ _this.hash ].prevContainerSize, containerSize: THIS[ _this.hash ].prevContainerSize,
contentSize: _this.source.dimensions,
springStiffness: _this.springStiffness, springStiffness: _this.springStiffness,
animationTime: _this.animationTime, animationTime: _this.animationTime,
showNavigator: false, showNavigator: false,
@ -1886,7 +1863,6 @@ function openTileSource( viewer, source, options ) {
} }
_this.viewport = _this.viewport ? _this.viewport : new $.Viewport({ _this.viewport = _this.viewport ? _this.viewport : new $.Viewport({
containerSize: THIS[ _this.hash ].prevContainerSize, containerSize: THIS[ _this.hash ].prevContainerSize,
contentSize: _this.source.dimensions,
springStiffness: _this.springStiffness, springStiffness: _this.springStiffness,
animationTime: _this.animationTime, animationTime: _this.animationTime,
minZoomImageRatio: _this.minZoomImageRatio, minZoomImageRatio: _this.minZoomImageRatio,
@ -1903,9 +1879,10 @@ function openTileSource( viewer, source, options ) {
}); });
} }
if( _this.preserveViewport ){ // TODO: what to do about this?
_this.viewport.resetContentSize( _this.source.dimensions ); // if( _this.preserveViewport ){
} // _this.viewport.resetContentSize( _this.source.dimensions );
// }
_this.source.overlays = _this.source.overlays || []; _this.source.overlays = _this.source.overlays || [];
@ -1952,7 +1929,8 @@ function openTileSource( viewer, source, options ) {
}); });
_this.world.addItem( tiledImage ); _this.world.addItem( tiledImage );
_this.goHome( true ); _this.viewport.setHomeBounds(_this.world.getHomeBounds(), _this.world.getContentFactor());
_this.viewport.goHome( true );
// Now that we have a drawer, see if it supports rotate. If not we need to remove the rotate buttons // Now that we have a drawer, see if it supports rotate. If not we need to remove the rotate buttons
if (!_this.drawer.canRotate()) { if (!_this.drawer.canRotate()) {
@ -2818,7 +2796,7 @@ function lightUp() {
function onHome() { function onHome() {
this.goHome(); this.viewport.goHome();
} }

View File

@ -104,43 +104,82 @@ $.Viewport = function( options ) {
animationTime: this.animationTime animationTime: this.animationTime
}); });
if (this.contentSize) {
this.resetContentSize( this.contentSize ); this.resetContentSize( this.contentSize );
} else {
this.setHomeBounds(new $.Rect(0, 0, 1, 1), 1);
}
this.goHome( true );
this.update(); this.update();
}; };
$.Viewport.prototype = /** @lends OpenSeadragon.Viewport.prototype */{ $.Viewport.prototype = /** @lends OpenSeadragon.Viewport.prototype */{
/** /**
* Updates the viewport's home bounds and constraints for the given content size.
* @function * @function
* @param {OpenSeadragon.Point} contentSize - size of the content in content units
* @return {OpenSeadragon.Viewport} Chainable. * @return {OpenSeadragon.Viewport} Chainable.
* @fires OpenSeadragon.Viewer.event:reset-size * @fires OpenSeadragon.Viewer.event:reset-size
*/ */
resetContentSize: function( contentSize ){ resetContentSize: function( contentSize ){
this.contentSize = contentSize; $.console.assert(contentSize, "[Viewport.resetContentSize] contentSize is required");
$.console.assert(contentSize instanceof $.Point, "[Viewport.resetContentSize] contentSize must be an OpenSeadragon.Point");
$.console.assert(contentSize.x > 0, "[Viewport.resetContentSize] contentSize.x must be greater than 0");
$.console.assert(contentSize.y > 0, "[Viewport.resetContentSize] contentSize.y must be greater than 0");
this.setHomeBounds(new $.Rect(0, 0, 1, contentSize.y / contentSize.x), contentSize.x);
return this;
},
/**
* Updates the viewport's home bounds and constraints.
* @function
* @param {OpenSeadragon.Rect} bounds - the new bounds in world coordinates
* @param {Number} contentFactor - how many content units per world unit
* @fires OpenSeadragon.Viewer.event:reset-size
*/
setHomeBounds: function(bounds, contentFactor) {
$.console.assert(bounds, "[Viewport.setHomeBounds] bounds is required");
$.console.assert(bounds instanceof $.Rect, "[Viewport.setHomeBounds] bounds must be an OpenSeadragon.Rect");
$.console.assert(bounds.width > 0, "[Viewport.setHomeBounds] bounds.width must be greater than 0");
$.console.assert(bounds.height > 0, "[Viewport.setHomeBounds] bounds.height must be greater than 0");
this.homeBounds = bounds.clone();
this.contentSize = this.homeBounds.getSize().times(contentFactor);
this.contentAspectX = this.contentSize.x / this.contentSize.y; this.contentAspectX = this.contentSize.x / this.contentSize.y;
this.contentAspectY = this.contentSize.y / this.contentSize.x; this.contentAspectY = this.contentSize.y / this.contentSize.x;
this.fitWidthBounds = new $.Rect( 0, 0, 1, this.contentAspectY );
this.fitHeightBounds = new $.Rect( 0, 0, this.contentAspectY, this.contentAspectY);
this.homeBounds = new $.Rect( 0, 0, 1, this.contentAspectY ); // 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 ){ if( this.viewer ){
/** /**
* Raised when the viewer's content size is reset (see {@link OpenSeadragon.Viewport#resetContentSize}). * Raised when the viewer's content size or home bounds are reset
* (see {@link OpenSeadragon.Viewport#resetContentSize},
* {@link OpenSeadragon.Viewport#setHomeBounds}).
* *
* @event reset-size * @event reset-size
* @memberof OpenSeadragon.Viewer * @memberof OpenSeadragon.Viewer
* @type {object} * @type {object}
* @property {OpenSeadragon.Viewer} eventSource - A reference to the Viewer which raised this event. * @property {OpenSeadragon.Viewer} eventSource - A reference to the Viewer which raised this event.
* @property {OpenSeadragon.Point} contentSize * @property {OpenSeadragon.Point} contentSize
* @property {OpenSeadragon.Rect} homeBounds
* @property {Number} contentFactor
* @property {?Object} userData - Arbitrary subscriber-defined object. * @property {?Object} userData - Arbitrary subscriber-defined object.
*/ */
this.viewer.raiseEvent( 'reset-size', { this.viewer.raiseEvent( 'reset-size', {
contentSize: contentSize contentSize: this.contentSize.clone(),
contentFactor: contentFactor,
homeBounds: this.homeBounds.clone()
}); });
} }
return this;
}, },
/** /**
@ -153,9 +192,11 @@ $.Viewport.prototype = /** @lends OpenSeadragon.Viewport.prototype */{
if( this.defaultZoomLevel ){ if( this.defaultZoomLevel ){
return this.defaultZoomLevel; return this.defaultZoomLevel;
} else { } else {
return ( aspectFactor >= 1 ) ? var output = ( aspectFactor >= 1 ) ?
1 : 1 :
aspectFactor; aspectFactor;
return output / this.homeBounds.width;
} }
}, },
@ -163,29 +204,31 @@ $.Viewport.prototype = /** @lends OpenSeadragon.Viewport.prototype */{
* @function * @function
*/ */
getHomeBounds: function() { getHomeBounds: function() {
var center = this.homeBounds.getCenter( ), return this.homeBounds.clone();
width = 1.0 / this.getHomeZoom( ),
height = width / this.getAspectRatio();
return new $.Rect(
center.x - ( width / 2.0 ),
center.y - ( height / 2.0 ),
width,
height
);
}, },
/** /**
* @function * @function
* @private * @param {Boolean} immediately
* @fires OpenSeadragon.Viewer.event:home
*/ */
goHome: function( immediately ) { goHome: function( immediately ) {
$.console.error("[Viewport.goHome] this function is deprecated; use Viewer.goHome instead");
if( this.viewer ){ if( this.viewer ){
this.viewer.goHome(immediately); /**
* Raised when the "home" operation occurs (see {@link OpenSeadragon.Viewport#goHome}).
*
* @event home
* @memberof OpenSeadragon.Viewer
* @type {object}
* @property {OpenSeadragon.Viewer} eventSource - A reference to the Viewer which raised this event.
* @property {Boolean} immediately
* @property {?Object} userData - Arbitrary subscriber-defined object.
*/
this.viewer.raiseEvent( 'home', {
immediately: immediately
});
} }
return this.fitBounds( this.getHomeBounds(), immediately );
return this;
}, },
/** /**
@ -204,9 +247,11 @@ $.Viewport.prototype = /** @lends OpenSeadragon.Viewport.prototype */{
* @function * @function
*/ */
getMaxZoom: function() { getMaxZoom: function() {
var zoom = this.maxZoomLevel ? var zoom = this.maxZoomLevel;
this.maxZoomLevel : if (!zoom) {
( this.contentSize.x * this.maxZoomPixelRatio / this.containerSize.x ); zoom = this.contentSize.x * this.maxZoomPixelRatio / this.containerSize.x;
zoom /= this.homeBounds.width;
}
return Math.max( zoom, this.getHomeZoom() ); return Math.max( zoom, this.getHomeZoom() );
}, },
@ -335,9 +380,9 @@ $.Viewport.prototype = /** @lends OpenSeadragon.Viewport.prototype */{
verticalThreshold = this.visibilityRatio * newBounds.height; verticalThreshold = this.visibilityRatio * newBounds.height;
left = newBounds.x + newBounds.width; left = newBounds.x + newBounds.width;
right = 1 - newBounds.x; right = this.homeBounds.width - newBounds.x;
top = newBounds.y + newBounds.height; top = newBounds.y + newBounds.height;
bottom = this.contentAspectY - newBounds.y; bottom = this.homeBounds.height - newBounds.y;
if ( this.wrapHorizontal ) { if ( this.wrapHorizontal ) {
//do nothing //do nothing
@ -368,11 +413,11 @@ $.Viewport.prototype = /** @lends OpenSeadragon.Viewport.prototype */{
if ( dx || dy || immediately ) { if ( dx || dy || immediately ) {
newBounds.x += dx; newBounds.x += dx;
newBounds.y += dy; newBounds.y += dy;
if( newBounds.width > 1 ){ if( newBounds.width > this.homeBounds.width ){
newBounds.x = 0.5 - newBounds.width/2; newBounds.x = this.homeBounds.width / 2 - newBounds.width/2;
} }
if( newBounds.height > this.contentAspectY ){ if( newBounds.height > this.homeBounds.height){
newBounds.y = this.contentAspectY/2 - newBounds.height/2; newBounds.y = this.homeBounds.height / 2 - newBounds.height/2;
} }
} }
@ -401,10 +446,6 @@ $.Viewport.prototype = /** @lends OpenSeadragon.Viewport.prototype */{
* @fires OpenSeadragon.Viewer.event:constrain * @fires OpenSeadragon.Viewer.event:constrain
*/ */
applyConstraints: function( immediately ) { applyConstraints: function( immediately ) {
if (true) {
return; // TEMP
}
var actualZoom = this.getZoom(), var actualZoom = this.getZoom(),
constrainedZoom = Math.max( constrainedZoom = Math.max(
Math.min( actualZoom, this.getMaxZoom() ), Math.min( actualZoom, this.getMaxZoom() ),

View File

@ -43,11 +43,13 @@ $.World = function( options ) {
this.viewer = options.viewer; this.viewer = options.viewer;
this._items = []; this._items = [];
this._figureSizes();
}; };
$.World.prototype = /** @lends OpenSeadragon.World.prototype */{ $.World.prototype = /** @lends OpenSeadragon.World.prototype */{
addItem: function( item ) { addItem: function( item ) {
this._items.push( item ); this._items.push( item );
this._figureSizes();
}, },
/** /**
@ -132,6 +134,8 @@ $.World.prototype = /** @lends OpenSeadragon.World.prototype */{
} }
this._items.splice( index, 1 ); this._items.splice( index, 1 );
this._figureSizes();
/** /**
* Raised when a layer is removed. * Raised when a layer is removed.
* @event remove-layer * @event remove-layer
@ -167,11 +171,26 @@ $.World.prototype = /** @lends OpenSeadragon.World.prototype */{
}, },
getHomeBounds: function() { getHomeBounds: function() {
return this._homeBounds.clone();
},
getContentSize: function() {
return this._contentSize.clone();
},
getContentFactor: function() {
return this._contentFactor;
},
_figureSizes: function() {
if ( !this._items.length ) { if ( !this._items.length ) {
return new $.Rect(0, 0, 1, 1); this._homeBounds = new $.Rect(0, 0, 1, 1);
this._contentSize = new $.Point(1, 1);
return;
} }
var bounds = this._items[0].getWorldBounds(); var bounds = this._items[0].getWorldBounds();
this._contentFactor = this._items[0].getContentSize().x / bounds.width;
var left = bounds.x; var left = bounds.x;
var top = bounds.y; var top = bounds.y;
var right = bounds.x + bounds.width; var right = bounds.x + bounds.width;
@ -179,13 +198,16 @@ $.World.prototype = /** @lends OpenSeadragon.World.prototype */{
var box; var box;
for ( var i = 1; i < this._items.length; i++ ) { for ( var i = 1; i < this._items.length; i++ ) {
box = this._items[i].getWorldBounds(); box = this._items[i].getWorldBounds();
this._contentFactor = Math.max(this._contentFactor, this._items[i].getContentSize().x / bounds.width);
left = Math.min( left, box.x ); left = Math.min( left, box.x );
top = Math.min( top, box.y ); top = Math.min( top, box.y );
right = Math.max( right, box.x + box.width ); right = Math.max( right, box.x + box.width );
bottom = Math.max( bottom, box.y + box.height ); bottom = Math.max( bottom, box.y + box.height );
} }
return new $.Rect( left, top, right - left, bottom - top ); this._homeBounds = new $.Rect( left, top, right - left, bottom - top );
this._contentSize = new $.Point(this._homeBounds.width * this._contentFactor,
this._homeBounds.height * this._contentFactor);
} }
}; };

View File

@ -1,6 +1,8 @@
/* globals $, App */
(function() { (function() {
var App = { window.App = {
init: function() { init: function() {
var self = this; var self = this;
@ -38,7 +40,7 @@
var addLayerHandler = function( event ) { var addLayerHandler = function( event ) {
if ( event.options === options ) { if ( event.options === options ) {
self.viewer.removeHandler( "add-layer", addLayerHandler ); self.viewer.removeHandler( "add-layer", addLayerHandler );
self.viewer.goHome(); self.viewer.viewport.goHome();
} }
}; };
this.viewer.addHandler( "add-layer", addLayerHandler ); this.viewer.addHandler( "add-layer", addLayerHandler );