image springs start

This commit is contained in:
Ian Gilman 2014-11-24 17:47:16 -08:00
parent bf9ccd5458
commit 4e788473b0

View File

@ -82,17 +82,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 +101,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, {
@ -118,6 +117,8 @@ $.TiledImage = function( options ) {
updateAgain: true, // Does the tiledImage need to update the viewport again? updateAgain: 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 +131,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) {
/** /**
@ -190,9 +211,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 +237,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 +338,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,46 +370,87 @@ $.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) { if (immediately) {
if (this._xSpring.target.value === position.x && this._ySpring.target.value === position.y &&
this._xSpring.current.value === position.x && this._ySpring.current.value === position.y) {
return; return;
} }
this._worldX = position.x; this._xSpring.resetTo(position.x);
this._worldY = position.y; this._ySpring.resetTo(position.y);
this._xSpring.update();
this._ySpring.update();
this.updateAgain = true; this.updateAgain = true;
} else {
if (this._xSpring.target.value === position.x && this._ySpring.target.value === position.y) {
return;
}
this._xSpring.springTo(position.x);
this._ySpring.springTo(position.y);
}
this._raiseBoundsChange(); 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) { if (immediately) {
if (this._worldWidthTarget === width && this._worldWidthCurrent === width) {
return; return;
} }
this._setScale(width); this._scaleSpring.resetTo(width);
this._scaleSpring.update();
this._updateForScale();
this.updateAgain = true; this.updateAgain = true;
} else {
if (this._worldWidthTarget === width) {
return;
}
this._scaleSpring.springTo(width);
this._updateForScale();
}
this._raiseBoundsChange(); 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) { var scale = height / this.normHeight;
if (immediately) {
if (this._worldHeightTarget === height && this._worldHeightCurrent === height) {
return; return;
} }
this._setScale(height / this.normHeight); this._scaleSpring.resetTo(scale);
this._scaleSpring.update();
this._updateForScale();
this.updateAgain = true; this.updateAgain = true;
} else {
if (this._worldHeightTarget === height) {
return;
}
this._scaleSpring.springTo(scale);
this._updateForScale();
}
this._raiseBoundsChange(); this._raiseBoundsChange();
}, },
@ -388,6 +461,14 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
this._worldHeight = this.normHeight * this._scale; this._worldHeight = this.normHeight * this._scale;
}, },
// private
_updateForScale: function() {
this._worldWidthTarget = this._scale.target.value;
this._worldHeightTarget = this.normHeight * this._scale.target.value;
this._worldWidthCurrent = this._scale.current.value;
this._worldHeightCurrent = this.normHeight * this._scale.current.value;
},
// private // private
_raiseBoundsChange: function() { _raiseBoundsChange: function() {
/** /**
@ -445,8 +526,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 ) {
@ -843,8 +924,8 @@ function positionTile( tile, overlap, viewport, viewportCenter, levelVisibility,
boundsTL.x *= tiledImage._scale; boundsTL.x *= tiledImage._scale;
boundsTL.y *= tiledImage._scale; boundsTL.y *= tiledImage._scale;
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();