mirror of
https://github.com/openseadragon/openseadragon.git
synced 2024-11-25 14:46:10 +03:00
Merge pull request #1100 from avandecreme/animate_rotation
Animate rotation
This commit is contained in:
commit
8df10f2177
@ -500,9 +500,9 @@ $.Drawer.prototype = {
|
|||||||
if ( this.viewport.degrees !== 0 ) {
|
if ( this.viewport.degrees !== 0 ) {
|
||||||
this._offsetForRotation({degrees: this.viewport.degrees});
|
this._offsetForRotation({degrees: this.viewport.degrees});
|
||||||
}
|
}
|
||||||
if (tiledImage.getRotation() !== 0) {
|
if (tiledImage.getRotation(true) % 360 !== 0) {
|
||||||
this._offsetForRotation({
|
this._offsetForRotation({
|
||||||
degrees: tiledImage.getRotation(),
|
degrees: tiledImage.getRotation(true),
|
||||||
point: tiledImage.viewport.pixelFromPointNoRotate(
|
point: tiledImage.viewport.pixelFromPointNoRotate(
|
||||||
tiledImage._getRotationPoint(true), true)
|
tiledImage._getRotationPoint(true), true)
|
||||||
});
|
});
|
||||||
@ -569,7 +569,7 @@ $.Drawer.prototype = {
|
|||||||
if ( this.viewport.degrees !== 0 ) {
|
if ( this.viewport.degrees !== 0 ) {
|
||||||
this._restoreRotationChanges();
|
this._restoreRotationChanges();
|
||||||
}
|
}
|
||||||
if (tiledImage.getRotation() !== 0) {
|
if (tiledImage.getRotation(true) % 360 !== 0) {
|
||||||
this._restoreRotationChanges();
|
this._restoreRotationChanges();
|
||||||
}
|
}
|
||||||
context.restore();
|
context.restore();
|
||||||
|
@ -369,9 +369,11 @@ $.extend( $.Navigator.prototype, $.EventSource.prototype, $.Viewer.prototype, /*
|
|||||||
|
|
||||||
// private
|
// private
|
||||||
_matchBounds: function(myItem, theirItem, immediately) {
|
_matchBounds: function(myItem, theirItem, immediately) {
|
||||||
var bounds = theirItem.getBounds();
|
var bounds = theirItem.getBoundsNoRotate();
|
||||||
myItem.setPosition(bounds.getTopLeft(), immediately);
|
myItem.setPosition(bounds.getTopLeft(), immediately);
|
||||||
myItem.setWidth(bounds.width, immediately);
|
myItem.setWidth(bounds.width, immediately);
|
||||||
|
myItem.setRotation(theirItem.getRotation(), immediately);
|
||||||
|
myItem.setClip(theirItem.getClip());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -206,6 +206,7 @@ $.Spring.prototype = {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @function
|
* @function
|
||||||
|
* @returns true if the value got updated, false otherwise
|
||||||
*/
|
*/
|
||||||
update: function() {
|
update: function() {
|
||||||
this.current.time = $.now();
|
this.current.time = $.now();
|
||||||
@ -229,11 +230,14 @@ $.Spring.prototype = {
|
|||||||
( this.target.time - this.start.time )
|
( this.target.time - this.start.time )
|
||||||
);
|
);
|
||||||
|
|
||||||
|
var oldValue = this.current.value;
|
||||||
if (this._exponential) {
|
if (this._exponential) {
|
||||||
this.current.value = Math.exp(currentValue);
|
this.current.value = Math.exp(currentValue);
|
||||||
} else {
|
} else {
|
||||||
this.current.value = currentValue;
|
this.current.value = currentValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return oldValue != this.current.value;
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -132,7 +132,7 @@ $.TiledImage = function( options ) {
|
|||||||
var fitBoundsPlacement = options.fitBoundsPlacement || OpenSeadragon.Placement.CENTER;
|
var fitBoundsPlacement = options.fitBoundsPlacement || OpenSeadragon.Placement.CENTER;
|
||||||
delete options.fitBoundsPlacement;
|
delete options.fitBoundsPlacement;
|
||||||
|
|
||||||
this._degrees = $.positiveModulo(options.degrees || 0, 360);
|
var degrees = options.degrees || 0;
|
||||||
delete options.degrees;
|
delete options.degrees;
|
||||||
|
|
||||||
$.extend( true, this, {
|
$.extend( true, this, {
|
||||||
@ -186,6 +186,12 @@ $.TiledImage = function( options ) {
|
|||||||
animationTime: this.animationTime
|
animationTime: this.animationTime
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this._degreesSpring = new $.Spring({
|
||||||
|
initial: degrees,
|
||||||
|
springStiffness: this.springStiffness,
|
||||||
|
animationTime: this.animationTime
|
||||||
|
});
|
||||||
|
|
||||||
this._updateForScale();
|
this._updateForScale();
|
||||||
|
|
||||||
if (fitBounds) {
|
if (fitBounds) {
|
||||||
@ -269,16 +275,12 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
|
|||||||
* @returns {Boolean} Whether the TiledImage animated.
|
* @returns {Boolean} Whether the TiledImage animated.
|
||||||
*/
|
*/
|
||||||
update: function() {
|
update: function() {
|
||||||
var oldX = this._xSpring.current.value;
|
var xUpdated = this._xSpring.update();
|
||||||
var oldY = this._ySpring.current.value;
|
var yUpdated = this._ySpring.update();
|
||||||
var oldScale = this._scaleSpring.current.value;
|
var scaleUpdated = this._scaleSpring.update();
|
||||||
|
var degreesUpdated = this._degreesSpring.update();
|
||||||
|
|
||||||
this._xSpring.update();
|
if (xUpdated || yUpdated || scaleUpdated || degreesUpdated) {
|
||||||
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._updateForScale();
|
||||||
this._needsDraw = true;
|
this._needsDraw = true;
|
||||||
return true;
|
return true;
|
||||||
@ -313,7 +315,7 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
|
|||||||
*/
|
*/
|
||||||
getBounds: function(current) {
|
getBounds: function(current) {
|
||||||
return this.getBoundsNoRotate(current)
|
return this.getBoundsNoRotate(current)
|
||||||
.rotate(this._degrees, this._getRotationPoint(current));
|
.rotate(this.getRotation(current), this._getRotationPoint(current));
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -362,7 +364,7 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
|
|||||||
clip.width,
|
clip.width,
|
||||||
clip.height);
|
clip.height);
|
||||||
}
|
}
|
||||||
return bounds.rotate(this._degrees, this._getRotationPoint(current));
|
return bounds.rotate(this.getRotation(current), this._getRotationPoint(current));
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -397,7 +399,7 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
|
|||||||
point = new $.Point(viewerX, viewerY);
|
point = new $.Point(viewerX, viewerY);
|
||||||
}
|
}
|
||||||
|
|
||||||
point = point.rotate(-this._degrees, this._getRotationPoint(current));
|
point = point.rotate(-this.getRotation(current), this._getRotationPoint(current));
|
||||||
return current ?
|
return current ?
|
||||||
this._viewportToImageDelta(
|
this._viewportToImageDelta(
|
||||||
point.x - this._xSpring.current.value,
|
point.x - this._xSpring.current.value,
|
||||||
@ -439,7 +441,7 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
|
|||||||
point.y += this._ySpring.target.value;
|
point.y += this._ySpring.target.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
return point.rotate(this._degrees, this._getRotationPoint(current));
|
return point.rotate(this.getRotation(current), this._getRotationPoint(current));
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -453,7 +455,7 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
|
|||||||
* @param {Boolean} [current=false] - Pass true to use the current location; false for target location.
|
* @param {Boolean} [current=false] - Pass true to use the current location; false for target location.
|
||||||
* @return {OpenSeadragon.Rect} A rect representing the coordinates in the viewport.
|
* @return {OpenSeadragon.Rect} A rect representing the coordinates in the viewport.
|
||||||
*/
|
*/
|
||||||
imageToViewportRectangle: function( imageX, imageY, pixelWidth, pixelHeight, current ) {
|
imageToViewportRectangle: function(imageX, imageY, pixelWidth, pixelHeight, current) {
|
||||||
var rect = imageX;
|
var rect = imageX;
|
||||||
if (rect instanceof $.Rect) {
|
if (rect instanceof $.Rect) {
|
||||||
//they passed a rect instead of individual components
|
//they passed a rect instead of individual components
|
||||||
@ -470,7 +472,7 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
|
|||||||
coordA.y,
|
coordA.y,
|
||||||
coordB.x,
|
coordB.x,
|
||||||
coordB.y,
|
coordB.y,
|
||||||
rect.degrees + this._degrees
|
rect.degrees + this.getRotation(current)
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -502,7 +504,7 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
|
|||||||
coordA.y,
|
coordA.y,
|
||||||
coordB.x,
|
coordB.x,
|
||||||
coordB.y,
|
coordB.y,
|
||||||
rect.degrees - this._degrees
|
rect.degrees - this.getRotation(current)
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -555,7 +557,7 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
|
|||||||
// coordinates (x in [0, 1] and y in [0, aspectRatio])
|
// coordinates (x in [0, 1] and y in [0, aspectRatio])
|
||||||
_viewportToTiledImageRectangle: function(rect) {
|
_viewportToTiledImageRectangle: function(rect) {
|
||||||
var scale = this._scaleSpring.current.value;
|
var scale = this._scaleSpring.current.value;
|
||||||
rect = rect.rotate(-this.getRotation(), this._getRotationPoint(true));
|
rect = rect.rotate(-this.getRotation(true), this._getRotationPoint(true));
|
||||||
return new $.Rect(
|
return new $.Rect(
|
||||||
(rect.x - this._xSpring.current.value) / scale,
|
(rect.x - this._xSpring.current.value) / scale,
|
||||||
(rect.y - this._ySpring.current.value) / scale,
|
(rect.y - this._ySpring.current.value) / scale,
|
||||||
@ -769,24 +771,33 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
|
|||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the current rotation of this tiled image in degrees.
|
* Get the rotation of this tiled image in degrees.
|
||||||
* @returns {Number} the current rotation of this tiled image in degrees.
|
* @param {Boolean} [current=false] True for current rotation, false for target.
|
||||||
|
* @returns {Number} the rotation of this tiled image in degrees.
|
||||||
*/
|
*/
|
||||||
getRotation: function() {
|
getRotation: function(current) {
|
||||||
return this._degrees;
|
return current ?
|
||||||
|
this._degreesSpring.current.value :
|
||||||
|
this._degreesSpring.target.value;
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the current rotation of this tiled image in degrees.
|
* Set the current rotation of this tiled image in degrees.
|
||||||
* @param {Number} degrees the rotation in degrees.
|
* @param {Number} degrees the rotation in degrees.
|
||||||
|
* @param {Boolean} [immediately=false] Whether to animate to the new angle
|
||||||
|
* or rotate immediately.
|
||||||
* @fires OpenSeadragon.TiledImage.event:bounds-change
|
* @fires OpenSeadragon.TiledImage.event:bounds-change
|
||||||
*/
|
*/
|
||||||
setRotation: function(degrees) {
|
setRotation: function(degrees, immediately) {
|
||||||
degrees = $.positiveModulo(degrees, 360);
|
if (this._degreesSpring.target.value === degrees &&
|
||||||
if (this._degrees === degrees) {
|
this._degreesSpring.isAtTargetValue()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this._degrees = degrees;
|
if (immediately) {
|
||||||
|
this._degreesSpring.resetTo(degrees);
|
||||||
|
} else {
|
||||||
|
this._degreesSpring.springTo(degrees);
|
||||||
|
}
|
||||||
this._needsDraw = true;
|
this._needsDraw = true;
|
||||||
this._raiseBoundsChange();
|
this._raiseBoundsChange();
|
||||||
},
|
},
|
||||||
@ -1701,11 +1712,11 @@ function drawTiles( tiledImage, lastDrawn ) {
|
|||||||
|
|
||||||
var zoom = tiledImage.viewport.getZoom(true);
|
var zoom = tiledImage.viewport.getZoom(true);
|
||||||
var imageZoom = tiledImage.viewportToImageZoom(zoom);
|
var imageZoom = tiledImage.viewportToImageZoom(zoom);
|
||||||
// TODO: support tile edge smoothing with tiled image rotation.
|
|
||||||
if (lastDrawn.length > 1 &&
|
if (lastDrawn.length > 1 &&
|
||||||
imageZoom > tiledImage.smoothTileEdgesMinZoom &&
|
imageZoom > tiledImage.smoothTileEdgesMinZoom &&
|
||||||
!tiledImage.iOSDevice &&
|
!tiledImage.iOSDevice &&
|
||||||
tiledImage.getRotation() === 0 &&
|
tiledImage.getRotation(true) % 360 === 0 && // TODO: support tile edge smoothing with tiled image rotation.
|
||||||
$.supportsCanvas) {
|
$.supportsCanvas) {
|
||||||
// When zoomed in a lot (>100%) the tile edges are visible.
|
// When zoomed in a lot (>100%) the tile edges are visible.
|
||||||
// So we have to composite them at ~100% and scale them up together.
|
// So we have to composite them at ~100% and scale them up together.
|
||||||
@ -1739,9 +1750,9 @@ function drawTiles( tiledImage, lastDrawn ) {
|
|||||||
useSketch: useSketch
|
useSketch: useSketch
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (tiledImage._degrees !== 0) {
|
if (tiledImage.getRotation(true) % 360 !== 0) {
|
||||||
tiledImage._drawer._offsetForRotation({
|
tiledImage._drawer._offsetForRotation({
|
||||||
degrees: tiledImage._degrees,
|
degrees: tiledImage.getRotation(true),
|
||||||
point: tiledImage.viewport.pixelFromPointNoRotate(
|
point: tiledImage.viewport.pixelFromPointNoRotate(
|
||||||
tiledImage._getRotationPoint(true), true),
|
tiledImage._getRotationPoint(true), true),
|
||||||
useSketch: useSketch
|
useSketch: useSketch
|
||||||
@ -1754,7 +1765,7 @@ function drawTiles( tiledImage, lastDrawn ) {
|
|||||||
tiledImage._drawer.saveContext(useSketch);
|
tiledImage._drawer.saveContext(useSketch);
|
||||||
|
|
||||||
var box = tiledImage.imageToViewportRectangle(tiledImage._clip, true);
|
var box = tiledImage.imageToViewportRectangle(tiledImage._clip, true);
|
||||||
box = box.rotate(-tiledImage._degrees, tiledImage._getRotationPoint());
|
box = box.rotate(-tiledImage.getRotation(true), tiledImage._getRotationPoint(true));
|
||||||
var clipRect = tiledImage._drawer.viewportToDrawerRectangle(box);
|
var clipRect = tiledImage._drawer.viewportToDrawerRectangle(box);
|
||||||
if (sketchScale) {
|
if (sketchScale) {
|
||||||
clipRect = clipRect.times(sketchScale);
|
clipRect = clipRect.times(sketchScale);
|
||||||
@ -1816,7 +1827,7 @@ function drawTiles( tiledImage, lastDrawn ) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!sketchScale) {
|
if (!sketchScale) {
|
||||||
if (tiledImage._degrees !== 0) {
|
if (tiledImage.getRotation(true) % 360 !== 0) {
|
||||||
tiledImage._drawer._restoreRotationChanges(useSketch);
|
tiledImage._drawer._restoreRotationChanges(useSketch);
|
||||||
}
|
}
|
||||||
if (tiledImage.viewport.degrees !== 0) {
|
if (tiledImage.viewport.degrees !== 0) {
|
||||||
@ -1832,9 +1843,9 @@ function drawTiles( tiledImage, lastDrawn ) {
|
|||||||
useSketch: false
|
useSketch: false
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (tiledImage._degrees !== 0) {
|
if (tiledImage.getRotation(true) % 360 !== 0) {
|
||||||
tiledImage._drawer._offsetForRotation({
|
tiledImage._drawer._offsetForRotation({
|
||||||
degrees: tiledImage._degrees,
|
degrees: tiledImage.getRotation(true),
|
||||||
point: tiledImage.viewport.pixelFromPointNoRotate(
|
point: tiledImage.viewport.pixelFromPointNoRotate(
|
||||||
tiledImage._getRotationPoint(true), true),
|
tiledImage._getRotationPoint(true), true),
|
||||||
useSketch: false
|
useSketch: false
|
||||||
@ -1849,7 +1860,7 @@ function drawTiles( tiledImage, lastDrawn ) {
|
|||||||
bounds: bounds
|
bounds: bounds
|
||||||
});
|
});
|
||||||
if (sketchScale) {
|
if (sketchScale) {
|
||||||
if (tiledImage._degrees !== 0) {
|
if (tiledImage.getRotation(true) % 360 !== 0) {
|
||||||
tiledImage._drawer._restoreRotationChanges(false);
|
tiledImage._drawer._restoreRotationChanges(false);
|
||||||
}
|
}
|
||||||
if (tiledImage.viewport.degrees !== 0) {
|
if (tiledImage.viewport.degrees !== 0) {
|
||||||
|
@ -319,10 +319,16 @@
|
|||||||
|
|
||||||
function testDefaultRotation() {
|
function testDefaultRotation() {
|
||||||
var image = viewer.world.getItemAt(0);
|
var image = viewer.world.getItemAt(0);
|
||||||
strictEqual(image.getRotation(), 0, 'image has default rotation');
|
strictEqual(image.getRotation(true), 0, 'image has default current rotation');
|
||||||
|
strictEqual(image.getRotation(false), 0, 'image has default target rotation');
|
||||||
|
|
||||||
image.setRotation(400);
|
image.setRotation(400);
|
||||||
strictEqual(image.getRotation(), 40, 'rotation is set correctly');
|
strictEqual(image.getRotation(true), 0, 'current rotation is not changed');
|
||||||
|
strictEqual(image.getRotation(false), 400, 'target rotation is set correctly');
|
||||||
|
|
||||||
|
image.setRotation(200, true);
|
||||||
|
strictEqual(image.getRotation(true), 200, 'current rotation is set correctly');
|
||||||
|
strictEqual(image.getRotation(false), 200, 'target rotation is set correctly');
|
||||||
|
|
||||||
viewer.addOnceHandler('open', testTileSourceRotation);
|
viewer.addOnceHandler('open', testTileSourceRotation);
|
||||||
viewer.open({
|
viewer.open({
|
||||||
@ -333,7 +339,8 @@
|
|||||||
|
|
||||||
function testTileSourceRotation() {
|
function testTileSourceRotation() {
|
||||||
var image = viewer.world.getItemAt(0);
|
var image = viewer.world.getItemAt(0);
|
||||||
strictEqual(image.getRotation(), 300, 'image has correct rotation');
|
strictEqual(image.getRotation(true), -60, 'image has correct current rotation');
|
||||||
|
strictEqual(image.getRotation(false), -60, 'image has correct target rotation');
|
||||||
start();
|
start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user