Merge pull request #533 from openseadragon/ian2

tiledImages can now animate their positions and sizes
This commit is contained in:
Ian Gilman 2014-12-03 13:42:13 -08:00
commit b22864ca6e
12 changed files with 365 additions and 192 deletions

View File

@ -15,10 +15,10 @@ OPENSEADRAGON CHANGELOG
* DEPRECATION: use World.getItemCount instead of Viewer.getLayersCount * DEPRECATION: use World.getItemCount instead of Viewer.getLayersCount
* DEPRECATION: use World.setItemIndex instead of Viewer.setLayerLevel * DEPRECATION: use World.setItemIndex instead of Viewer.setLayerLevel
* DEPRECATION: use World.removeItem instead of Viewer.removeLayer * DEPRECATION: use World.removeItem instead of Viewer.removeLayer
* DEPRECATION: use World.needsUpdate instead of Drawer.needsUpdate * DEPRECATION: use World.needsDraw instead of Drawer.needsUpdate
* DEPRECATION: use TileCache.numTilesLoaded instead of Drawer.numTilesLoaded * DEPRECATION: use TileCache.numTilesLoaded instead of Drawer.numTilesLoaded
* DEPRECATION: use World.resetItems instead of Drawer.reset * DEPRECATION: use World.resetItems instead of Drawer.reset
* DEPRECATION: use Drawer.clear and World.update instead of Drawer.update * DEPRECATION: use Drawer.clear and World.draw instead of Drawer.update
* DEPRECATION: the layersAspectRatioEpsilon option is no longer necessary * DEPRECATION: the layersAspectRatioEpsilon option is no longer necessary
* DEPRECATION: Viewer's add-layer event is now World's add-item event * 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-change event * DEPRECATION: Viewer's layer-level-changed event is now World's item-index-change event

View File

@ -168,8 +168,8 @@ $.Drawer.prototype = /** @lends OpenSeadragon.Drawer.prototype */{
// deprecated // deprecated
needsUpdate: function() { needsUpdate: function() {
$.console.error( "[Drawer.needsUpdate] this function is deprecated. Use World.needsUpdate instead." ); $.console.error( "[Drawer.needsUpdate] this function is deprecated. Use World.needsDraw instead." );
return this.viewer.world.needsUpdate(); return this.viewer.world.needsDraw();
}, },
// deprecated // deprecated
@ -187,9 +187,9 @@ $.Drawer.prototype = /** @lends OpenSeadragon.Drawer.prototype */{
// deprecated // deprecated
update: function() { update: function() {
$.console.error( "[Drawer.update] this function is deprecated. Use Drawer.clear and World.update instead." ); $.console.error( "[Drawer.update] this function is deprecated. Use Drawer.clear and World.draw instead." );
this.clear(); this.clear();
this.viewer.world.update(); this.viewer.world.draw();
return this; return this;
}, },

View File

@ -277,7 +277,8 @@ $.extend( $.Navigator.prototype, $.EventSource.prototype, $.Viewer.prototype, /*
this.viewport.resize( containerSize, true ); this.viewport.resize( containerSize, true );
this.viewport.goHome(true); this.viewport.goHome(true);
this.oldContainerSize = containerSize; this.oldContainerSize = containerSize;
this.drawer.update(); this.drawer.clear();
this.world.draw();
} }
} }
}, },

View File

@ -52,6 +52,8 @@
* @param {Number} [options.y=0] - Top position, in viewport coordinates. * @param {Number} [options.y=0] - Top position, in viewport coordinates.
* @param {Number} [options.width=1] - Width, in viewport coordinates. * @param {Number} [options.width=1] - Width, in viewport coordinates.
* @param {Number} [options.height] - Height, in viewport coordinates. * @param {Number} [options.height] - Height, in viewport coordinates.
* @param {Number} [options.springStiffness] - See {@link OpenSeadragon.Options}.
* @param {Boolean} [options.animationTime] - See {@link OpenSeadragon.Options}.
* @param {Number} [options.minZoomImageRatio] - See {@link OpenSeadragon.Options}. * @param {Number} [options.minZoomImageRatio] - See {@link OpenSeadragon.Options}.
* @param {Boolean} [options.wrapHorizontal] - See {@link OpenSeadragon.Options}. * @param {Boolean} [options.wrapHorizontal] - See {@link OpenSeadragon.Options}.
* @param {Boolean} [options.wrapVertical] - See {@link OpenSeadragon.Options}. * @param {Boolean} [options.wrapVertical] - See {@link OpenSeadragon.Options}.
@ -82,17 +84,18 @@ $.TiledImage = function( options ) {
this._imageLoader = options.imageLoader; this._imageLoader = options.imageLoader;
delete options.imageLoader; delete options.imageLoader;
this._worldX = options.x || 0; var x = options.x || 0;
delete options.x; delete options.x;
this._worldY = options.y || 0; var y = options.y || 0;
delete options.y; delete options.y;
// Ratio of zoomable image height to width. // Ratio of zoomable image height to width.
this.normHeight = options.source.dimensions.y / options.source.dimensions.x; this.normHeight = options.source.dimensions.y / options.source.dimensions.x;
this.contentAspectX = options.source.dimensions.x / options.source.dimensions.y; this.contentAspectX = options.source.dimensions.x / options.source.dimensions.y;
var scale = 1;
if ( options.width ) { if ( options.width ) {
this._setScale(options.width); scale = options.width;
delete options.width; delete options.width;
if ( options.height ) { if ( options.height ) {
@ -100,10 +103,8 @@ $.TiledImage = function( options ) {
delete options.height; delete options.height;
} }
} else if ( options.height ) { } else if ( options.height ) {
this._setScale(options.height / this.normHeight); scale = options.height / this.normHeight;
delete options.height; delete options.height;
} else {
this._setScale(1);
} }
$.extend( true, this, { $.extend( true, this, {
@ -114,10 +115,12 @@ $.TiledImage = function( options ) {
coverage: {}, // A '3d' dictionary [level][x][y] --> Boolean. coverage: {}, // A '3d' dictionary [level][x][y] --> Boolean.
lastDrawn: [], // An unordered list of Tiles drawn last frame. lastDrawn: [], // An unordered list of Tiles drawn last frame.
lastResetTime: 0, // Last time for which the tiledImage was reset. lastResetTime: 0, // Last time for which the tiledImage was reset.
midUpdate: false, // Is the tiledImage currently updating the viewport? _midDraw: false, // Is the tiledImage currently updating the viewport?
updateAgain: true, // Does the tiledImage need to update the viewport again? _needsDraw: true, // Does the tiledImage need to update the viewport again?
//configurable settings //configurable settings
springStiffness: $.DEFAULT_SETTINGS.springStiffness,
animationTime: $.DEFAULT_SETTINGS.animationTime,
minZoomImageRatio: $.DEFAULT_SETTINGS.minZoomImageRatio, minZoomImageRatio: $.DEFAULT_SETTINGS.minZoomImageRatio,
wrapHorizontal: $.DEFAULT_SETTINGS.wrapHorizontal, wrapHorizontal: $.DEFAULT_SETTINGS.wrapHorizontal,
wrapVertical: $.DEFAULT_SETTINGS.wrapVertical, wrapVertical: $.DEFAULT_SETTINGS.wrapVertical,
@ -130,6 +133,26 @@ $.TiledImage = function( options ) {
}, options ); }, options );
this._xSpring = new $.Spring({
initial: x,
springStiffness: this.springStiffness,
animationTime: this.animationTime
});
this._ySpring = new $.Spring({
initial: y,
springStiffness: this.springStiffness,
animationTime: this.animationTime
});
this._scaleSpring = new $.Spring({
initial: scale,
springStiffness: this.springStiffness,
animationTime: this.animationTime
});
this._updateForScale();
// We need a callback to give image manipulation a chance to happen // We need a callback to give image manipulation a chance to happen
this._drawingHandler = function(args) { this._drawingHandler = function(args) {
/** /**
@ -155,11 +178,10 @@ $.TiledImage = function( options ) {
$.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadragon.TiledImage.prototype */{ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadragon.TiledImage.prototype */{
/** /**
* @returns {Boolean} Whether the TiledImage is scheduled for an update at the * @returns {Boolean} Whether the TiledImage needs to be drawn.
* soonest possible opportunity.
*/ */
needsUpdate: function() { needsDraw: function() {
return this.updateAgain; return this._needsDraw;
}, },
/** /**
@ -169,16 +191,39 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
reset: function() { reset: function() {
this._tileCache.clearTilesFor(this); this._tileCache.clearTilesFor(this);
this.lastResetTime = $.now(); this.lastResetTime = $.now();
this.updateAgain = true; this._needsDraw = true;
}, },
/** /**
* Forces the TiledImage to update. * Updates the TiledImage's bounds, animating if needed.
* @returns {Boolean} Whether the TiledImage animated.
*/ */
update: function() { update: function() {
this.midUpdate = true; var oldX = this._xSpring.current.value;
var oldY = this._ySpring.current.value;
var oldScale = this._scaleSpring.current.value;
this._xSpring.update();
this._ySpring.update();
this._scaleSpring.update();
if (this._xSpring.current.value !== oldX || this._ySpring.current.value !== oldY ||
this._scaleSpring.current.value !== oldScale) {
this._updateForScale();
this._needsDraw = true;
return true;
}
return false;
},
/**
* Draws the TiledImage to its Drawer.
*/
draw: function() {
this._midDraw = true;
updateViewport( this ); updateViewport( this );
this.midUpdate = false; this._midDraw = false;
}, },
/** /**
@ -190,9 +235,16 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
/** /**
* @returns {OpenSeadragon.Rect} This TiledImage's bounds in viewport coordinates. * @returns {OpenSeadragon.Rect} This TiledImage's bounds in viewport coordinates.
* @param {Boolean} [current=false] - Pass true for the current location; false for target location.
*/ */
getBounds: function() { getBounds: function(current) {
return new $.Rect( this._worldX, this._worldY, this._worldWidth, this._worldHeight ); if (current) {
return new $.Rect( this._xSpring.current.value, this._ySpring.current.value,
this._worldWidthCurrent, this._worldHeightCurrent );
}
return new $.Rect( this._xSpring.target.value, this._ySpring.target.value,
this._worldWidthTarget, this._worldHeightTarget );
}, },
// deprecated // deprecated
@ -209,89 +261,96 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
}, },
// private // private
_viewportToImageDelta: function( viewerX, viewerY ) { _viewportToImageDelta: function( viewerX, viewerY, current ) {
return new $.Point(viewerX * (this.source.dimensions.x / this._scale), var scale = current ? this._scaleSpring.current.value : this._scaleSpring.target.value;
viewerY * ((this.source.dimensions.y * this.contentAspectX) / this._scale)); return new $.Point(viewerX * (this.source.dimensions.x / scale),
viewerY * ((this.source.dimensions.y * this.contentAspectX) / scale));
}, },
/** /**
* Translates from OpenSeadragon viewer coordinate system to image coordinate system. * Translates from OpenSeadragon viewer coordinate system to image coordinate system.
* This method can be called either by passing X,Y coordinates or an * This method can be called either by passing X,Y coordinates or an {@link OpenSeadragon.Point}.
* OpenSeadragon.Point * @param {Number|OpenSeadragon.Point} viewerX - The X coordinate or point in viewport coordinate system.
* @function * @param {Number} [viewerY] - The Y coordinate in viewport coordinate system.
* @param {OpenSeadragon.Point} viewerX the point in viewport coordinate system. * @param {Boolean} [current=false] - Pass true to use the current location; false for target location.
* @param {Number} viewerX X coordinate in viewport coordinate system. * @return {OpenSeadragon.Point} A point representing the coordinates in the image.
* @param {Number} viewerY Y coordinate in viewport coordinate system.
* @return {OpenSeadragon.Point} a point representing the coordinates in the image.
*/ */
viewportToImageCoordinates: function( viewerX, viewerY ) { viewportToImageCoordinates: function( viewerX, viewerY, current ) {
if ( arguments.length == 1 ) { if (viewerX instanceof $.Point) {
//they passed a point instead of individual components //they passed a point instead of individual components
return this.viewportToImageCoordinates( viewerX.x, viewerX.y ); current = viewerY;
viewerY = viewerX.y;
viewerX = viewerX.x;
} }
return this._viewportToImageDelta(viewerX - this._worldX, viewerY - this._worldY); if (current) {
return this._viewportToImageDelta(viewerX - this._xSpring.current.value,
viewerY - this._ySpring.current.value);
}
return this._viewportToImageDelta(viewerX - this._xSpring.target.value,
viewerY - this._ySpring.target.value);
}, },
// private // private
_imageToViewportDelta: function( imageX, imageY ) { _imageToViewportDelta: function( imageX, imageY, current ) {
return new $.Point((imageX / this.source.dimensions.x) * this._scale, var scale = current ? this._scaleSpring.current.value : this._scaleSpring.target.value;
(imageY / this.source.dimensions.y / this.contentAspectX) * this._scale); return new $.Point((imageX / this.source.dimensions.x) * scale,
(imageY / this.source.dimensions.y / this.contentAspectX) * scale);
}, },
/** /**
* Translates from image coordinate system to OpenSeadragon viewer coordinate system * Translates from image coordinate system to OpenSeadragon viewer coordinate system
* This method can be called either by passing X,Y coordinates or an * This method can be called either by passing X,Y coordinates or an {@link OpenSeadragon.Point}.
* OpenSeadragon.Point * @param {Number|OpenSeadragon.Point} imageX - The X coordinate or point in image coordinate system.
* @function * @param {Number} [imageY] - The Y coordinate in image coordinate system.
* @param {OpenSeadragon.Point} imageX the point in image coordinate system. * @param {Boolean} [current=false] - Pass true to use the current location; false for target location.
* @param {Number} imageX X coordinate in image coordinate system. * @return {OpenSeadragon.Point} A point representing the coordinates in the viewport.
* @param {Number} imageY Y coordinate in image coordinate system.
* @return {OpenSeadragon.Point} a point representing the coordinates in the viewport.
*/ */
imageToViewportCoordinates: function( imageX, imageY ) { imageToViewportCoordinates: function( imageX, imageY, current ) {
if ( arguments.length == 1 ) { if (imageX instanceof $.Point) {
//they passed a point instead of individual components //they passed a point instead of individual components
return this.imageToViewportCoordinates( imageX.x, imageX.y ); current = imageY;
imageY = imageX.y;
imageX = imageX.x;
} }
var point = this._imageToViewportDelta(imageX, imageY); var point = this._imageToViewportDelta(imageX, imageY);
point.x += this._worldX; if (current) {
point.y += this._worldY; point.x += this._xSpring.current.value;
point.y += this._ySpring.current.value;
} else {
point.x += this._xSpring.target.value;
point.y += this._ySpring.target.value;
}
return point; return point;
}, },
/** /**
* Translates from a rectangle which describes a portion of the image in * Translates from a rectangle which describes a portion of the image in
* pixel coordinates to OpenSeadragon viewport rectangle coordinates. * pixel coordinates to OpenSeadragon viewport rectangle coordinates.
* This method can be called either by passing X,Y,width,height or an * This method can be called either by passing X,Y,width,height or an {@link OpenSeadragon.Rect}.
* OpenSeadragon.Rect * @param {Number|OpenSeadragon.Rect} imageX - The left coordinate or rectangle in image coordinate system.
* @function * @param {Number} [imageY] - The top coordinate in image coordinate system.
* @param {OpenSeadragon.Rect} imageX the rectangle in image coordinate system. * @param {Number} [pixelWidth] - The width in pixel of the rectangle.
* @param {Number} imageX the X coordinate of the top left corner of the rectangle * @param {Number} [pixelHeight] - The height in pixel of the rectangle.
* in image coordinate system. * @param {Boolean} [current=false] - Pass true to use the current location; false for target location.
* @param {Number} imageY the Y coordinate of the top left corner of the rectangle * @return {OpenSeadragon.Rect} A rect representing the coordinates in the viewport.
* in image coordinate system.
* @param {Number} pixelWidth the width in pixel of the rectangle.
* @param {Number} pixelHeight the height in pixel of the rectangle.
*/ */
imageToViewportRectangle: function( imageX, imageY, pixelWidth, pixelHeight ) { imageToViewportRectangle: function( imageX, imageY, pixelWidth, pixelHeight, current ) {
var coordA, if (imageX instanceof $.Rect) {
coordB, //they passed a rect instead of individual components
rect; current = imageY;
if( arguments.length == 1 ) { pixelWidth = imageX.width;
//they passed a rectangle instead of individual components pixelHeight = imageX.height;
rect = imageX; imageY = imageX.y;
return this.imageToViewportRectangle( imageX = imageX.x;
rect.x, rect.y, rect.width, rect.height
);
} }
coordA = this.imageToViewportCoordinates(
imageX, imageY var coordA = this.imageToViewportCoordinates(imageX, imageY, current);
); var coordB = this._imageToViewportDelta(pixelWidth, pixelHeight, current);
coordB = this._imageToViewportDelta(
pixelWidth, pixelHeight
);
return new $.Rect( return new $.Rect(
coordA.x, coordA.x,
coordA.y, coordA.y,
@ -303,30 +362,27 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
/** /**
* Translates from a rectangle which describes a portion of * Translates from a rectangle which describes a portion of
* the viewport in point coordinates to image rectangle coordinates. * the viewport in point coordinates to image rectangle coordinates.
* This method can be called either by passing X,Y,width,height or an * This method can be called either by passing X,Y,width,height or an {@link OpenSeadragon.Rect}.
* OpenSeadragon.Rect * @param {Number|OpenSeadragon.Rect} viewerX - The left coordinate or rectangle in viewport coordinate system.
* @function * @param {Number} [viewerY] - The top coordinate in viewport coordinate system.
* @param {OpenSeadragon.Rect} viewerX the rectangle in viewport coordinate system. * @param {Number} [pointWidth] - The width in viewport coordinate system.
* @param {Number} viewerX the X coordinate of the top left corner of the rectangle * @param {Number} [pointHeight] - The height in viewport coordinate system.
* in viewport coordinate system. * @param {Boolean} [current=false] - Pass true to use the current location; false for target location.
* @param {Number} imageY the Y coordinate of the top left corner of the rectangle * @return {OpenSeadragon.Rect} A rect representing the coordinates in the image.
* in viewport coordinate system.
* @param {Number} pointWidth the width of the rectangle in viewport coordinate system.
* @param {Number} pointHeight the height of the rectangle in viewport coordinate system.
*/ */
viewportToImageRectangle: function( viewerX, viewerY, pointWidth, pointHeight ) { viewportToImageRectangle: function( viewerX, viewerY, pointWidth, pointHeight, current ) {
var coordA, if (viewerX instanceof $.Rect) {
coordB, //they passed a rect instead of individual components
rect; current = viewerY;
if ( arguments.length == 1 ) { pointWidth = viewerX.width;
//they passed a rectangle instead of individual components pointHeight = viewerX.height;
rect = viewerX; viewerY = viewerX.y;
return this.viewportToImageRectangle( viewerX = viewerX.x;
rect.x, rect.y, rect.width, rect.height
);
} }
coordA = this.viewportToImageCoordinates( viewerX, viewerY );
coordB = this._viewportToImageDelta(pointWidth, pointHeight); var coordA = this.viewportToImageCoordinates(viewerX, viewerY, current);
var coordB = this._viewportToImageDelta(pointWidth, pointHeight, current);
return new $.Rect( return new $.Rect(
coordA.x, coordA.x,
coordA.y, coordA.y,
@ -338,60 +394,96 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
/** /**
* Sets the TiledImage's position in the world. * Sets the TiledImage's position in the world.
* @param {OpenSeadragon.Point} position - The new position, in viewport coordinates. * @param {OpenSeadragon.Point} position - The new position, in viewport coordinates.
* @param {Boolean} [immediately=false] - Whether to animate to the new position or snap immediately.
* @fires OpenSeadragon.TiledImage.event:bounds-change * @fires OpenSeadragon.TiledImage.event:bounds-change
*/ */
setPosition: function(position) { setPosition: function(position, immediately) {
if (this._worldX === position.x && this._worldY === position.y) { var sameTarget = (this._xSpring.target.value === position.x &&
return; this._ySpring.target.value === position.y);
if (immediately) {
if (sameTarget && this._xSpring.current.value === position.x &&
this._ySpring.current.value === position.y) {
return;
}
this._xSpring.resetTo(position.x);
this._ySpring.resetTo(position.y);
this._xSpring.update();
this._ySpring.update();
} else {
if (sameTarget) {
return;
}
this._xSpring.springTo(position.x);
this._ySpring.springTo(position.y);
} }
this._worldX = position.x; if (!sameTarget) {
this._worldY = position.y; this._raiseBoundsChange();
this.updateAgain = true; }
this._raiseBoundsChange();
}, },
/** /**
* Sets the TiledImage's width in the world, adjusting the height to match based on aspect ratio. * Sets the TiledImage's width in the world, adjusting the height to match based on aspect ratio.
* @param {Number} width - The new width, in viewport coordinates. * @param {Number} width - The new width, in viewport coordinates.
* @param {Boolean} [immediately=false] - Whether to animate to the new size or snap immediately.
* @fires OpenSeadragon.TiledImage.event:bounds-change * @fires OpenSeadragon.TiledImage.event:bounds-change
*/ */
setWidth: function(width) { setWidth: function(width, immediately) {
if (this._worldWidth === width) { this._setScale(width, immediately);
return;
}
this._setScale(width);
this.updateAgain = true;
this._raiseBoundsChange();
}, },
/** /**
* Sets the TiledImage's height in the world, adjusting the width to match based on aspect ratio. * Sets the TiledImage's height in the world, adjusting the width to match based on aspect ratio.
* @param {Number} height - The new height, in viewport coordinates. * @param {Number} height - The new height, in viewport coordinates.
* @param {Boolean} [immediately=false] - Whether to animate to the new size or snap immediately.
* @fires OpenSeadragon.TiledImage.event:bounds-change * @fires OpenSeadragon.TiledImage.event:bounds-change
*/ */
setHeight: function(height) { setHeight: function(height, immediately) {
if (this._worldHeight === height) { this._setScale(height / this.normHeight, immediately);
return;
}
this._setScale(height / this.normHeight);
this.updateAgain = true;
this._raiseBoundsChange();
}, },
// private // private
_setScale: function(scale) { _setScale: function(scale, immediately) {
this._scale = scale; var sameTarget = (this._scaleSpring.target.value === scale);
this._worldWidth = this._scale; if (immediately) {
this._worldHeight = this.normHeight * this._scale; if (sameTarget && this._scaleSpring.current.value === scale) {
return;
}
this._scaleSpring.resetTo(scale);
this._scaleSpring.update();
this._updateForScale();
} else {
if (sameTarget) {
return;
}
this._scaleSpring.springTo(scale);
this._updateForScale();
}
if (!sameTarget) {
this._raiseBoundsChange();
}
},
// private
_updateForScale: function() {
this._worldWidthTarget = this._scaleSpring.target.value;
this._worldHeightTarget = this.normHeight * this._scaleSpring.target.value;
this._worldWidthCurrent = this._scaleSpring.current.value;
this._worldHeightCurrent = this.normHeight * this._scaleSpring.current.value;
}, },
// private // private
_raiseBoundsChange: function() { _raiseBoundsChange: function() {
/** /**
* Raised when the TiledImage's bounds are changed. * Raised when the TiledImage's bounds are changed.
* Note that this event is triggered only when the animation target is changed;
* not for every frame of animation.
* @event bounds-change * @event bounds-change
* @memberOf OpenSeadragon.TiledImage * @memberOf OpenSeadragon.TiledImage
* @type {object} * @type {object}
@ -411,7 +503,7 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
*/ */
function updateViewport( tiledImage ) { function updateViewport( tiledImage ) {
tiledImage.updateAgain = false; tiledImage._needsDraw = false;
var tile, var tile,
level, level,
@ -422,7 +514,7 @@ function updateViewport( tiledImage ) {
zeroRatioC = tiledImage.viewport.deltaPixelsFromPoints( zeroRatioC = tiledImage.viewport.deltaPixelsFromPoints(
tiledImage.source.getPixelRatio( 0 ), tiledImage.source.getPixelRatio( 0 ),
true true
).x * tiledImage._scale, ).x * tiledImage._scaleSpring.current.value,
lowestLevel = Math.max( lowestLevel = Math.max(
tiledImage.source.minLevel, tiledImage.source.minLevel,
Math.floor( Math.floor(
@ -445,8 +537,8 @@ function updateViewport( tiledImage ) {
levelOpacity, levelOpacity,
levelVisibility; levelVisibility;
viewportBounds.x -= tiledImage._worldX; viewportBounds.x -= tiledImage._xSpring.current.value;
viewportBounds.y -= tiledImage._worldY; viewportBounds.y -= tiledImage._ySpring.current.value;
// Reset tile's internal drawn state // Reset tile's internal drawn state
while ( tiledImage.lastDrawn.length > 0 ) { while ( tiledImage.lastDrawn.length > 0 ) {
@ -470,23 +562,23 @@ function updateViewport( tiledImage ) {
var viewportBR = viewportBounds.getBottomRight(); var viewportBR = viewportBounds.getBottomRight();
//Don't draw if completely outside of the viewport //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._worldWidthCurrent ) ) {
return; return;
} }
if ( !tiledImage.wrapVertical && ( viewportBR.y < 0 || viewportTL.y > tiledImage._worldHeight ) ) { if ( !tiledImage.wrapVertical && ( viewportBR.y < 0 || viewportTL.y > tiledImage._worldHeightCurrent ) ) {
return; return;
} }
// Calculate viewport rect / bounds // Calculate viewport rect / bounds
if ( !tiledImage.wrapHorizontal ) { if ( !tiledImage.wrapHorizontal ) {
viewportTL.x = Math.max( viewportTL.x, 0 ); viewportTL.x = Math.max( viewportTL.x, 0 );
viewportBR.x = Math.min( viewportBR.x, tiledImage._worldWidth ); viewportBR.x = Math.min( viewportBR.x, tiledImage._worldWidthCurrent );
} }
if ( !tiledImage.wrapVertical ) { if ( !tiledImage.wrapVertical ) {
viewportTL.y = Math.max( viewportTL.y, 0 ); viewportTL.y = Math.max( viewportTL.y, 0 );
viewportBR.y = Math.min( viewportBR.y, tiledImage._worldHeight ); viewportBR.y = Math.min( viewportBR.y, tiledImage._worldHeightCurrent );
} }
// Calculations for the interval of levels to draw // Calculations for the interval of levels to draw
@ -503,7 +595,7 @@ function updateViewport( tiledImage ) {
renderPixelRatioC = tiledImage.viewport.deltaPixelsFromPoints( renderPixelRatioC = tiledImage.viewport.deltaPixelsFromPoints(
tiledImage.source.getPixelRatio( level ), tiledImage.source.getPixelRatio( level ),
true true
).x * tiledImage._scale; ).x * tiledImage._scaleSpring.current.value;
if ( ( !haveDrawn && renderPixelRatioC >= tiledImage.minPixelRatio ) || if ( ( !haveDrawn && renderPixelRatioC >= tiledImage.minPixelRatio ) ||
( level == lowestLevel ) ) { ( level == lowestLevel ) ) {
@ -517,7 +609,7 @@ function updateViewport( tiledImage ) {
renderPixelRatioT = tiledImage.viewport.deltaPixelsFromPoints( renderPixelRatioT = tiledImage.viewport.deltaPixelsFromPoints(
tiledImage.source.getPixelRatio( level ), tiledImage.source.getPixelRatio( level ),
false false
).x * tiledImage._scale; ).x * tiledImage._scaleSpring.current.value;
zeroRatioT = tiledImage.viewport.deltaPixelsFromPoints( zeroRatioT = tiledImage.viewport.deltaPixelsFromPoints(
tiledImage.source.getPixelRatio( tiledImage.source.getPixelRatio(
@ -527,7 +619,7 @@ function updateViewport( tiledImage ) {
) )
), ),
false false
).x * tiledImage._scale; ).x * tiledImage._scaleSpring.current.value;
optimalRatio = tiledImage.immediateRender ? optimalRatio = tiledImage.immediateRender ?
1 : 1 :
@ -567,7 +659,7 @@ function updateViewport( tiledImage ) {
if ( best ) { if ( best ) {
loadTile( tiledImage, best, currentTime ); loadTile( tiledImage, best, currentTime );
// because we haven't finished drawing, so // because we haven't finished drawing, so
tiledImage.updateAgain = true; tiledImage._needsDraw = true;
} }
} }
@ -615,8 +707,8 @@ function updateLevel( tiledImage, haveDrawn, drawLevel, level, levelOpacity, lev
} }
//OK, a new drawing so do your calculations //OK, a new drawing so do your calculations
tileTL = tiledImage.source.getTileAtPoint( level, viewportTL.divide( tiledImage._scale )); tileTL = tiledImage.source.getTileAtPoint( level, viewportTL.divide( tiledImage._scaleSpring.current.value ));
tileBR = tiledImage.source.getTileAtPoint( level, viewportBR.divide( tiledImage._scale )); tileBR = tiledImage.source.getTileAtPoint( level, viewportBR.divide( tiledImage._scaleSpring.current.value ));
numberOfTiles = tiledImage.source.getNumTiles( level ); numberOfTiles = tiledImage.source.getNumTiles( level );
resetCoverage( tiledImage.coverage, level ); resetCoverage( tiledImage.coverage, level );
@ -660,8 +752,8 @@ function updateTile( tiledImage, drawLevel, haveDrawn, x, y, level, levelOpacity
tiledImage.tilesMatrix, tiledImage.tilesMatrix,
currentTime, currentTime,
numberOfTiles, numberOfTiles,
tiledImage._worldWidth, tiledImage._worldWidthCurrent,
tiledImage._worldHeight tiledImage._worldHeightCurrent
), ),
drawTile = drawLevel; drawTile = drawLevel;
@ -724,7 +816,7 @@ function updateTile( tiledImage, drawLevel, haveDrawn, x, y, level, levelOpacity
} }
if ( tile.loaded ) { if ( tile.loaded ) {
var needsUpdate = blendTile( var needsDraw = blendTile(
tiledImage, tiledImage,
tile, tile,
x, y, x, y,
@ -733,8 +825,8 @@ function updateTile( tiledImage, drawLevel, haveDrawn, x, y, level, levelOpacity
currentTime currentTime
); );
if ( needsUpdate ) { if ( needsDraw ) {
tiledImage.updateAgain = true; tiledImage._needsDraw = true;
} }
} else if ( tile.loading ) { } else if ( tile.loading ) {
// the tile is already in the download queue // the tile is already in the download queue
@ -827,29 +919,29 @@ function onTileLoad( tiledImage, tile, time, image ) {
// Check if we're mid-update; this can happen on IE8 because image load events for // Check if we're mid-update; this can happen on IE8 because image load events for
// cached images happen immediately there // cached images happen immediately there
if ( !tiledImage.midUpdate ) { if ( !tiledImage._midDraw ) {
finish(); finish();
} else { } else {
// Wait until after the update, in case caching unloads any tiles // Wait until after the update, in case caching unloads any tiles
window.setTimeout( finish, 1); window.setTimeout( finish, 1);
} }
tiledImage.updateAgain = true; tiledImage._needsDraw = true;
} }
function positionTile( tile, overlap, viewport, viewportCenter, levelVisibility, tiledImage ){ function positionTile( tile, overlap, viewport, viewportCenter, levelVisibility, tiledImage ){
var boundsTL = tile.bounds.getTopLeft(); var boundsTL = tile.bounds.getTopLeft();
boundsTL.x *= tiledImage._scale; boundsTL.x *= tiledImage._scaleSpring.current.value;
boundsTL.y *= tiledImage._scale; boundsTL.y *= tiledImage._scaleSpring.current.value;
boundsTL.x += tiledImage._worldX; boundsTL.x += tiledImage._xSpring.current.value;
boundsTL.y += tiledImage._worldY; boundsTL.y += tiledImage._ySpring.current.value;
var boundsSize = tile.bounds.getSize(); var boundsSize = tile.bounds.getSize();
boundsSize.x *= tiledImage._scale; boundsSize.x *= tiledImage._scaleSpring.current.value;
boundsSize.y *= tiledImage._scale; boundsSize.y *= tiledImage._scaleSpring.current.value;
var positionC = viewport.pixelFromPoint( boundsTL, true ), var positionC = viewport.pixelFromPoint( boundsTL, true ),
positionT = viewport.pixelFromPoint( boundsTL, false ), positionT = viewport.pixelFromPoint( boundsTL, false ),

View File

@ -666,6 +666,10 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype,
delete options.index; delete options.index;
} }
if (options.collectionImmediately === undefined) {
options.collectionImmediately = true;
}
var originalSuccess = options.success; var originalSuccess = options.success;
options.success = function(event) { options.success = function(event) {
successes++; successes++;
@ -1237,6 +1241,8 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype,
* supports except arrays of images. * supports except arrays of images.
* Note that you can specify options.width or options.height, but not both. * Note that you can specify options.width or options.height, but not both.
* The other dimension will be calculated according to the item's aspect ratio. * The other dimension will be calculated according to the item's aspect ratio.
* If collectionMode is on (see {@link OpenSeadragon.Options}), the new image is
* automatically arranged with the others.
* @function * @function
* @param {Object} options * @param {Object} options
* @param {String|Object|Function} options.tileSource - The TileSource specifier. * @param {String|Object|Function} options.tileSource - The TileSource specifier.
@ -1260,6 +1266,8 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype,
* @param {Function} [options.error] A function that gets called if the image is * @param {Function} [options.error] A function that gets called if the image is
* unable to be added. It's passed the error event object, which contains "message" * unable to be added. It's passed the error event object, which contains "message"
* and "source" properties. * and "source" properties.
* @param {Boolean} [options.collectionImmediately=false] If collectionMode is on,
* specifies whether to snap to the new arrangement immediately or to animate to it.
* @fires OpenSeadragon.World.event:add-item * @fires OpenSeadragon.World.event:add-item
* @fires OpenSeadragon.Viewer.event:add-item-failed * @fires OpenSeadragon.Viewer.event:add-item-failed
*/ */
@ -1337,7 +1345,8 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype,
y: queueItem.options.y, y: queueItem.options.y,
width: queueItem.options.width, width: queueItem.options.width,
height: queueItem.options.height, height: queueItem.options.height,
imageLoaderLimit: _this.imageLoaderLimit, springStiffness: _this.springStiffness,
animationTime: _this.animationTime,
minZoomImageRatio: _this.minZoomImageRatio, minZoomImageRatio: _this.minZoomImageRatio,
wrapHorizontal: _this.wrapHorizontal, wrapHorizontal: _this.wrapHorizontal,
wrapVertical: _this.wrapVertical, wrapVertical: _this.wrapVertical,
@ -1345,8 +1354,7 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype,
blendTime: _this.blendTime, blendTime: _this.blendTime,
alwaysBlend: _this.alwaysBlend, alwaysBlend: _this.alwaysBlend,
minPixelRatio: _this.minPixelRatio, minPixelRatio: _this.minPixelRatio,
debugMode: _this.debugMode, debugMode: _this.debugMode
debugGridColor: _this.debugGridColor
}); });
_this.world.addItem( tiledImage, { _this.world.addItem( tiledImage, {
@ -1355,6 +1363,7 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype,
if (_this.collectionMode) { if (_this.collectionMode) {
_this.world.arrange({ _this.world.arrange({
immediately: queueItem.options.collectionImmediately,
rows: _this.collectionRows, rows: _this.collectionRows,
layout: _this.collectionLayout, layout: _this.collectionLayout,
tileSize: _this.collectionTileSize, tileSize: _this.collectionTileSize,
@ -2659,6 +2668,7 @@ function updateOnce( viewer ) {
} }
animated = viewer.viewport.update(); animated = viewer.viewport.update();
animated = viewer.world.update() || animated;
if( viewer.referenceStrip ){ if( viewer.referenceStrip ){
animated = viewer.referenceStrip.update( viewer.viewport ) || animated; animated = viewer.referenceStrip.update( viewer.viewport ) || animated;
@ -2678,8 +2688,8 @@ function updateOnce( viewer ) {
abortControlsAutoHide( viewer ); abortControlsAutoHide( viewer );
} }
if ( animated || THIS[ viewer.hash ].forceRedraw || viewer.world.needsUpdate() ) { if ( animated || THIS[ viewer.hash ].forceRedraw || viewer.world.needsDraw() ) {
updateWorld( viewer ); drawWorld( viewer );
viewer._drawOverlays(); viewer._drawOverlays();
if( viewer.navigator ){ if( viewer.navigator ){
viewer.navigator.update( viewer.viewport ); viewer.navigator.update( viewer.viewport );
@ -2748,9 +2758,9 @@ function resizeViewportAndRecenter( viewer, containerSize, oldBounds, oldCenter
viewport.fitBounds( newBounds, true ); viewport.fitBounds( newBounds, true );
} }
function updateWorld( viewer ) { function drawWorld( viewer ) {
viewer.drawer.clear(); viewer.drawer.clear();
viewer.world.update(); viewer.world.draw();
/** /**
* <em>- Needs documentation -</em> * <em>- Needs documentation -</em>

View File

@ -51,7 +51,7 @@ $.World = function( options ) {
this.viewer = options.viewer; this.viewer = options.viewer;
this._items = []; this._items = [];
this._needsUpdate = false; this._needsDraw = false;
this._delegatedFigureSizes = function(event) { this._delegatedFigureSizes = function(event) {
_this._figureSizes(); _this._figureSizes();
}; };
@ -80,7 +80,7 @@ $.extend( $.World.prototype, $.EventSource.prototype, /** @lends OpenSeadragon.W
} }
this._figureSizes(); this._figureSizes();
this._needsUpdate = true; this._needsDraw = true;
item.addHandler('bounds-change', this._delegatedFigureSizes); item.addHandler('bounds-change', this._delegatedFigureSizes);
@ -147,7 +147,7 @@ $.extend( $.World.prototype, $.EventSource.prototype, /** @lends OpenSeadragon.W
this._items.splice( oldIndex, 1 ); this._items.splice( oldIndex, 1 );
this._items.splice( index, 0, item ); this._items.splice( index, 0, item );
this._needsUpdate = true; this._needsDraw = true;
/** /**
* Raised when the order of the indexes has been changed. * Raised when the order of the indexes has been changed.
@ -185,7 +185,7 @@ $.extend( $.World.prototype, $.EventSource.prototype, /** @lends OpenSeadragon.W
item.removeHandler('bounds-change', this._delegatedFigureSizes); item.removeHandler('bounds-change', this._delegatedFigureSizes);
this._items.splice( index, 1 ); this._items.splice( index, 1 );
this._figureSizes(); this._figureSizes();
this._needsUpdate = true; this._needsDraw = true;
this._raiseRemoveItem(item); this._raiseRemoveItem(item);
}, },
@ -204,7 +204,7 @@ $.extend( $.World.prototype, $.EventSource.prototype, /** @lends OpenSeadragon.W
var removedItems = this._items; var removedItems = this._items;
this._items = []; this._items = [];
this._figureSizes(); this._figureSizes();
this._needsUpdate = true; this._needsDraw = true;
for (i = 0; i < removedItems.length; i++) { for (i = 0; i < removedItems.length; i++) {
item = removedItems[i]; item = removedItems[i];
@ -222,26 +222,38 @@ $.extend( $.World.prototype, $.EventSource.prototype, /** @lends OpenSeadragon.W
}, },
/** /**
* Updates (i.e. draws) all items. * Updates (i.e. animates bounds of) all items.
*/ */
update: function() { update: function() {
var animated = false;
for ( var i = 0; i < this._items.length; i++ ) { for ( var i = 0; i < this._items.length; i++ ) {
this._items[i].update(); animated = this._items[i].update() || animated;
} }
this._needsUpdate = false; return animated;
},
/**
* Draws all items.
*/
draw: function() {
for ( var i = 0; i < this._items.length; i++ ) {
this._items[i].draw();
}
this._needsDraw = false;
}, },
/** /**
* @returns {Boolean} true if any items need updating. * @returns {Boolean} true if any items need updating.
*/ */
needsUpdate: function() { needsDraw: function() {
for ( var i = 0; i < this._items.length; i++ ) { for ( var i = 0; i < this._items.length; i++ ) {
if ( this._items[i].needsUpdate() ) { if ( this._items[i].needsDraw() ) {
return true; return true;
} }
} }
return this._needsUpdate; return this._needsDraw;
}, },
/** /**
@ -264,6 +276,7 @@ $.extend( $.World.prototype, $.EventSource.prototype, /** @lends OpenSeadragon.W
/** /**
* Arranges all of the TiledImages with the specified settings. * Arranges all of the TiledImages with the specified settings.
* @param {Object} options - Specifies how to arrange. * @param {Object} options - Specifies how to arrange.
* @param {Boolean} [options.immediately=false] - Whether to animate to the new arrangement.
* @param {String} [options.layout] - See collectionLayout in {@link OpenSeadragon.Options}. * @param {String} [options.layout] - See collectionLayout in {@link OpenSeadragon.Options}.
* @param {Number} [options.rows] - See collectionRows in {@link OpenSeadragon.Options}. * @param {Number} [options.rows] - See collectionRows in {@link OpenSeadragon.Options}.
* @param {Number} [options.tileSize] - See collectionTileSize in {@link OpenSeadragon.Options}. * @param {Number} [options.tileSize] - See collectionTileSize in {@link OpenSeadragon.Options}.
@ -272,6 +285,7 @@ $.extend( $.World.prototype, $.EventSource.prototype, /** @lends OpenSeadragon.W
*/ */
arrange: function(options) { arrange: function(options) {
options = options || {}; options = options || {};
var immediately = options.immediately || false;
var layout = options.layout || $.DEFAULT_SETTINGS.collectionLayout; var layout = options.layout || $.DEFAULT_SETTINGS.collectionLayout;
var rows = options.rows || $.DEFAULT_SETTINGS.collectionRows; var rows = options.rows || $.DEFAULT_SETTINGS.collectionRows;
var tileSize = options.tileSize || $.DEFAULT_SETTINGS.collectionTileSize; var tileSize = options.tileSize || $.DEFAULT_SETTINGS.collectionTileSize;
@ -304,8 +318,8 @@ $.extend( $.World.prototype, $.EventSource.prototype, /** @lends OpenSeadragon.W
position = new $.Point(x + ((tileSize - width) / 2), position = new $.Point(x + ((tileSize - width) / 2),
y + ((tileSize - height) / 2)); y + ((tileSize - height) / 2));
item.setPosition(position); item.setPosition(position, immediately);
item.setWidth(width); item.setWidth(width, immediately);
if (layout === 'horizontal') { if (layout === 'horizontal') {
x += increment; x += increment;

View File

@ -6,7 +6,7 @@
init: function() { init: function() {
var self = this; var self = this;
var testInitialOpen = true; var testInitialOpen = false;
var testOverlays = false; var testOverlays = false;
var testMargins = false; var testMargins = false;
var testNavigator = true; var testNavigator = true;
@ -21,7 +21,7 @@
// referenceStripScroll: 'vertical', // referenceStripScroll: 'vertical',
navPrevNextWrap: false, navPrevNextWrap: false,
preserveViewport: false, preserveViewport: false,
// collectionMode: true, collectionMode: true,
// collectionRows: 3, // collectionRows: 3,
// collectionLayout: 'vertical', // collectionLayout: 'vertical',
// collectionTileSize: 10, // collectionTileSize: 10,
@ -112,10 +112,39 @@
} }
if (!testInitialOpen) { if (!testInitialOpen) {
this.collectionTest(); this.basicTest();
} }
}, },
// ----------
shrink: function(index) {
index = index || 0;
var image = this.viewer.world.getItemAt(index);
image.setWidth(image.getBounds().width * 0.3);
},
// ----------
move: function(index) {
index = index || 0;
var image = this.viewer.world.getItemAt(index);
var point = image.getBounds().getTopLeft();
point.x += image.getBounds().width * 0.3;
image.setPosition(point);
},
// ----------
add: function() {
var self = this;
this.viewer.addTiledImage({
tileSource: "../../data/testpattern.dzi",
width: 1,
success: function() {
self.viewer.viewport.goHome();
}
});
},
// ---------- // ----------
toggle: function() { toggle: function() {
var $el = $(this.viewer.element); var $el = $(this.viewer.element);
@ -130,7 +159,8 @@
}); });
this.viewer.open({ this.viewer.open({
tileSource: "../../data/testpattern.dzi" tileSource: "../../data/testpattern.dzi",
width: 1
}); });
}, },

View File

@ -74,10 +74,10 @@
Util.testDeprecation(viewer.drawer, 'updateOverlay', viewer, 'updateOverlay'); Util.testDeprecation(viewer.drawer, 'updateOverlay', viewer, 'updateOverlay');
Util.testDeprecation(viewer.drawer, 'removeOverlay', viewer, 'removeOverlay'); Util.testDeprecation(viewer.drawer, 'removeOverlay', viewer, 'removeOverlay');
Util.testDeprecation(viewer.drawer, 'clearOverlays', viewer, 'clearOverlays'); Util.testDeprecation(viewer.drawer, 'clearOverlays', viewer, 'clearOverlays');
Util.testDeprecation(viewer.drawer, 'needsUpdate', viewer.world, 'needsUpdate'); Util.testDeprecation(viewer.drawer, 'needsUpdate', viewer.world, 'needsDraw');
Util.testDeprecation(viewer.drawer, 'numTilesLoaded', viewer.tileCache, 'numTilesLoaded'); Util.testDeprecation(viewer.drawer, 'numTilesLoaded', viewer.tileCache, 'numTilesLoaded');
Util.testDeprecation(viewer.drawer, 'reset', viewer.world, 'resetItems'); Util.testDeprecation(viewer.drawer, 'reset', viewer.world, 'resetItems');
Util.testDeprecation(viewer.drawer, 'update', viewer.world, 'update'); Util.testDeprecation(viewer.drawer, 'update', viewer.world, 'draw');
start(); start();
}); });

View File

@ -140,7 +140,7 @@
currentDisplayRegionLeft = displayRegion.position().left; currentDisplayRegionLeft = displayRegion.position().left;
currentDisplayWidth = displayRegion.width(); currentDisplayWidth = displayRegion.width();
viewerAndNavigatorDisplayReady = viewer.drawer !== null && viewerAndNavigatorDisplayReady = viewer.drawer !== null &&
!viewer.drawer.needsUpdate() && !viewer.world.needsDraw() &&
currentDisplayWidth > 0 && currentDisplayWidth > 0 &&
Util.equalsWithVariance(lastDisplayRegionLeft, currentDisplayRegionLeft, 0.0001) && Util.equalsWithVariance(lastDisplayRegionLeft, currentDisplayRegionLeft, 0.0001) &&
Util.equalsWithVariance(lastDisplayWidth, currentDisplayWidth, 0.0001) && Util.equalsWithVariance(lastDisplayWidth, currentDisplayWidth, 0.0001) &&
@ -160,7 +160,7 @@
else { else {
if (count === 40) { if (count === 40) {
console.log("waitForViewer:" + console.log("waitForViewer:" +
viewer.drawer + ":" + viewer.drawer.needsUpdate() + ":" + viewer.drawer + ":" + viewer.world.needsDraw() + ":" +
viewerAndNavigatorDisplayReady + ":" + viewerAndNavigatorDisplayReady + ":" +
lastDisplayRegionLeft + ":" + currentDisplayRegionLeft + ":" + lastDisplayRegionLeft + ":" + currentDisplayRegionLeft + ":" +
lastDisplayWidth + ":" + currentDisplayWidth + ":" + lastDisplayWidth + ":" + currentDisplayWidth + ":" +

View File

@ -29,7 +29,7 @@
} }
var ready = viewer.isOpen() && var ready = viewer.isOpen() &&
viewer.drawer !== null && viewer.drawer !== null &&
!viewer.drawer.needsUpdate() && !viewer.world.needsDraw() &&
Util.equalsWithVariance( viewer.viewport.getBounds( true ).x, Util.equalsWithVariance( viewer.viewport.getBounds( true ).x,
viewer.viewport.getBounds().x, 0.000 ) && viewer.viewport.getBounds().x, 0.000 ) &&
Util.equalsWithVariance( viewer.viewport.getBounds( true ).y, Util.equalsWithVariance( viewer.viewport.getBounds( true ).y,
@ -46,7 +46,7 @@
}, 100 ); }, 100 );
} else { } else {
console.log( "waitForViewer:" + viewer.isOpen( ) + ":" + viewer.drawer + console.log( "waitForViewer:" + viewer.isOpen( ) + ":" + viewer.drawer +
":" + viewer.drawer.needsUpdate() ); ":" + viewer.world.needsDraw() );
handler(); handler();
} }
} }

View File

@ -85,13 +85,39 @@
}); });
}); });
// ----------
asyncTest('animation', function() {
viewer.addHandler("open", function () {
var image = viewer.world.getItemAt(0);
propEqual(image.getBounds(), new OpenSeadragon.Rect(0, 0, 1, 1), 'target bounds on open');
propEqual(image.getBounds(true), new OpenSeadragon.Rect(0, 0, 1, 1), 'current bounds on open');
image.setPosition(new OpenSeadragon.Point(1, 2));
propEqual(image.getBounds(), new OpenSeadragon.Rect(1, 2, 1, 1), 'target bounds after position');
propEqual(image.getBounds(true), new OpenSeadragon.Rect(0, 0, 1, 1), 'current bounds after position');
image.setWidth(3);
propEqual(image.getBounds(), new OpenSeadragon.Rect(1, 2, 3, 3), 'target bounds after width');
propEqual(image.getBounds(true), new OpenSeadragon.Rect(0, 0, 1, 1), 'current bounds after width');
viewer.addHandler('animation-finish', function animationHandler() {
viewer.removeHandler('animation-finish', animationHandler);
propEqual(image.getBounds(), new OpenSeadragon.Rect(1, 2, 3, 3), 'target bounds after animation');
propEqual(image.getBounds(true), new OpenSeadragon.Rect(1, 2, 3, 3), 'current bounds after animation');
start();
});
});
viewer.open('/test/data/testpattern.dzi');
});
// ---------- // ----------
asyncTest('update', function() { asyncTest('update', function() {
var handlerCount = 0; var handlerCount = 0;
viewer.addHandler('open', function(event) { viewer.addHandler('open', function(event) {
var image = viewer.world.getItemAt(0); var image = viewer.world.getItemAt(0);
equal(image.needsUpdate(), true, 'needs update after open'); equal(image.needsDraw(), true, 'needs draw after open');
viewer.addHandler('update-level', function updateLevelHandler(event) { viewer.addHandler('update-level', function updateLevelHandler(event) {
viewer.removeHandler('update-level', updateLevelHandler); viewer.removeHandler('update-level', updateLevelHandler);
@ -137,7 +163,7 @@
start(); start();
}); });
image.update(); image.draw();
}); });
viewer.open('/test/data/testpattern.dzi'); viewer.open('/test/data/testpattern.dzi');

View File

@ -144,24 +144,24 @@
}); });
// ---------- // ----------
asyncTest('update', function() { asyncTest('draw', function() {
var handlerCount = 0; var handlerCount = 0;
viewer.addHandler('open', function(event) { viewer.addHandler('open', function(event) {
equal(viewer.world.needsUpdate(), true, 'needs update after open'); equal(viewer.world.needsDraw(), true, 'needs draw after open');
viewer.addHandler('update-level', function updateHandler() { viewer.addHandler('update-level', function updateHandler() {
viewer.removeHandler('update-level', updateHandler); viewer.removeHandler('update-level', updateHandler);
handlerCount++; handlerCount++;
}); });
viewer.world.update(); viewer.world.draw();
equal(handlerCount, 1, 'correct number of handlers called'); equal(handlerCount, 1, 'correct number of handlers called');
start(); start();
}); });
equal(viewer.world.needsUpdate(), false, 'needs no update at first'); equal(viewer.world.needsDraw(), false, 'needs no draw at first');
viewer.open('/test/data/testpattern.dzi'); viewer.open('/test/data/testpattern.dzi');
}); });