diff --git a/src/drawer.js b/src/drawer.js index 30d7fcf2..e316704a 100644 --- a/src/drawer.js +++ b/src/drawer.js @@ -547,8 +547,8 @@ $.Drawer.prototype = { context.strokeStyle = this.debugGridColor[colorIndex]; context.fillStyle = this.debugGridColor[colorIndex]; - if ( this.viewport.degrees !== 0 ) { - this._offsetForRotation({degrees: this.viewport.degrees}); + if (this.viewport.getRotation(true) % 360 !== 0 ) { + this._offsetForRotation({degrees: this.viewport.getRotation(true)}); } if (tiledImage.getRotation(true) % 360 !== 0) { this._offsetForRotation({ @@ -557,10 +557,11 @@ $.Drawer.prototype = { tiledImage._getRotationPoint(true), true) }); } - if (tiledImage.viewport.degrees === 0 && tiledImage.getRotation(true) % 360 === 0){ - if(tiledImage._drawer.viewer.viewport.getFlip()) { - tiledImage._drawer._flip(); - } + if (tiledImage.viewport.getRotation(true) % 360 === 0 && + tiledImage.getRotation(true) % 360 === 0) { + if(tiledImage._drawer.viewer.viewport.getFlip()) { + tiledImage._drawer._flip(); + } } context.strokeRect( @@ -575,7 +576,7 @@ $.Drawer.prototype = { // Rotate the text the right way around. context.translate( tileCenterX, tileCenterY ); - context.rotate( Math.PI / 180 * -this.viewport.degrees ); + context.rotate( Math.PI / 180 * -this.viewport.getRotation(true) ); context.translate( -tileCenterX, -tileCenterY ); if( tile.x === 0 && tile.y === 0 ){ @@ -621,17 +622,18 @@ $.Drawer.prototype = { (tile.position.y + 70) * $.pixelDensityRatio ); - if ( this.viewport.degrees !== 0 ) { + if (this.viewport.getRotation(true) % 360 !== 0 ) { this._restoreRotationChanges(); } if (tiledImage.getRotation(true) % 360 !== 0) { this._restoreRotationChanges(); } - if (tiledImage.viewport.degrees === 0 && tiledImage.getRotation(true) % 360 === 0){ - if(tiledImage._drawer.viewer.viewport.getFlip()) { - tiledImage._drawer._flip(); - } + if (tiledImage.viewport.getRotation(true) % 360 === 0 && + tiledImage.getRotation(true) % 360 === 0) { + if(tiledImage._drawer.viewer.viewport.getFlip()) { + tiledImage._drawer._flip(); + } } context.restore(); diff --git a/src/overlay.js b/src/overlay.js index 9fd1532c..18ceca02 100644 --- a/src/overlay.js +++ b/src/overlay.js @@ -299,18 +299,18 @@ this.adjust(position, size); var rotate = 0; - if (viewport.degrees && + if (viewport.getRotation(true) && this.rotationMode !== $.OverlayRotationMode.NO_ROTATION) { // BOUNDING_BOX is only valid if both directions get scaled. // Get replaced by EXACT otherwise. if (this.rotationMode === $.OverlayRotationMode.BOUNDING_BOX && this.width !== null && this.height !== null) { var rect = new $.Rect(position.x, position.y, size.x, size.y); - var boundingBox = this._getBoundingBox(rect, viewport.degrees); + var boundingBox = this._getBoundingBox(rect, viewport.getRotation(true)); position = boundingBox.getTopLeft(); size = boundingBox.getSize(); } else { - rotate = viewport.degrees; + rotate = viewport.getRotation(true); } } @@ -447,7 +447,7 @@ // private _adjustBoundsForRotation: function(viewport, bounds) { if (!viewport || - viewport.degrees === 0 || + viewport.getRotation(true) === 0 || this.rotationMode === $.OverlayRotationMode.EXACT) { return bounds; } @@ -467,7 +467,7 @@ } // NO_ROTATION case - return bounds.rotate(-viewport.degrees, + return bounds.rotate(-viewport.getRotation(true), this._getPlacementPoint(bounds)); } }; diff --git a/src/tiledimage.js b/src/tiledimage.js index 80204328..a8692d77 100644 --- a/src/tiledimage.js +++ b/src/tiledimage.js @@ -2076,9 +2076,10 @@ function drawTiles( tiledImage, lastDrawn ) { .getIntegerBoundingBox(); if(tiledImage._drawer.viewer.viewport.getFlip()) { - if (tiledImage.viewport.degrees !== 0 || tiledImage.getRotation(true) % 360 !== 0){ - bounds.x = tiledImage._drawer.viewer.container.clientWidth - (bounds.x + bounds.width); - } + if (tiledImage.viewport.getRotation(true) % 360 !== 0 || + tiledImage.getRotation(true) % 360 !== 0) { + bounds.x = tiledImage._drawer.viewer.container.clientWidth - (bounds.x + bounds.width); + } } bounds = bounds.times($.pixelDensityRatio); @@ -2089,9 +2090,9 @@ function drawTiles( tiledImage, lastDrawn ) { // When scaling, we must rotate only when blending the sketch canvas to // avoid interpolation if (!sketchScale) { - if (tiledImage.viewport.degrees !== 0) { + if (tiledImage.viewport.getRotation(true) % 360 !== 0) { tiledImage._drawer._offsetForRotation({ - degrees: tiledImage.viewport.degrees, + degrees: tiledImage.viewport.getRotation(true), useSketch: useSketch }); } @@ -2104,10 +2105,11 @@ function drawTiles( tiledImage, lastDrawn ) { }); } - if (tiledImage.viewport.degrees === 0 && tiledImage.getRotation(true) % 360 === 0){ - if(tiledImage._drawer.viewer.viewport.getFlip()) { - tiledImage._drawer._flip(); - } + if (tiledImage.viewport.getRotation(true) === 0 && + tiledImage.getRotation(true) % 360 === 0) { + if(tiledImage._drawer.viewer.viewport.getFlip()) { + tiledImage._drawer._flip(); + } } } @@ -2214,16 +2216,16 @@ function drawTiles( tiledImage, lastDrawn ) { if (tiledImage.getRotation(true) % 360 !== 0) { tiledImage._drawer._restoreRotationChanges(useSketch); } - if (tiledImage.viewport.degrees !== 0) { + if (tiledImage.viewport.getRotation(true) % 360 !== 0) { tiledImage._drawer._restoreRotationChanges(useSketch); } } if (useSketch) { if (sketchScale) { - if (tiledImage.viewport.degrees !== 0) { + if (tiledImage.viewport.getRotation(true) % 360 !== 0) { tiledImage._drawer._offsetForRotation({ - degrees: tiledImage.viewport.degrees, + degrees: tiledImage.viewport.getRotation(true), useSketch: false }); } @@ -2247,18 +2249,19 @@ function drawTiles( tiledImage, lastDrawn ) { if (tiledImage.getRotation(true) % 360 !== 0) { tiledImage._drawer._restoreRotationChanges(false); } - if (tiledImage.viewport.degrees !== 0) { + if (tiledImage.viewport.getRotation(true) % 360 !== 0) { tiledImage._drawer._restoreRotationChanges(false); } } } if (!sketchScale) { - if (tiledImage.viewport.degrees === 0 && tiledImage.getRotation(true) % 360 === 0){ - if(tiledImage._drawer.viewer.viewport.getFlip()) { - tiledImage._drawer._flip(); + if (tiledImage.viewport.getRotation(true) % 360 === 0 && + tiledImage.getRotation(true) % 360 === 0) { + if(tiledImage._drawer.viewer.viewport.getFlip()) { + tiledImage._drawer._flip(); + } } - } } drawDebugInfo( tiledImage, lastDrawn ); diff --git a/src/viewer.js b/src/viewer.js index 8d7be6ae..a138e2de 100644 --- a/src/viewer.js +++ b/src/viewer.js @@ -2810,18 +2810,18 @@ function onCanvasKeyPress( event ) { break; case 114: //r - clockwise rotation if(this.viewport.flipped){ - this.viewport.setRotation($.positiveModulo(this.viewport.degrees - this.rotationIncrement, 360)); + this.viewport.setRotation($.positiveModulo(this.viewport.getRotation() - this.rotationIncrement, 360)); } else{ - this.viewport.setRotation($.positiveModulo(this.viewport.degrees + this.rotationIncrement, 360)); + this.viewport.setRotation($.positiveModulo(this.viewport.getRotation() + this.rotationIncrement, 360)); } this.viewport.applyConstraints(); event.preventDefault = true; break; case 82: //R - counterclockwise rotation if(this.viewport.flipped){ - this.viewport.setRotation($.positiveModulo(this.viewport.degrees + this.rotationIncrement, 360)); + this.viewport.setRotation($.positiveModulo(this.viewport.getRotation() + this.rotationIncrement, 360)); } else{ - this.viewport.setRotation($.positiveModulo(this.viewport.degrees - this.rotationIncrement, 360)); + this.viewport.setRotation($.positiveModulo(this.viewport.getRotation() - this.rotationIncrement, 360)); } this.viewport.applyConstraints(); event.preventDefault = true; diff --git a/src/viewport.js b/src/viewport.js index be350af9..028c5916 100644 --- a/src/viewport.js +++ b/src/viewport.js @@ -133,9 +133,16 @@ $.Viewport = function( options ) { animationTime: this.animationTime }); + this.degreesSpring = new $.Spring({ + initial: 0, + springStiffness: this.springStiffness, + animationTime: this.animationTime + }); + this._oldCenterX = this.centerSpringX.current.value; this._oldCenterY = this.centerSpringY.current.value; this._oldZoom = this.zoomSpring.current.value; + this._oldDegree = this.degreesSpring.current.value; this._setContentBounds(new $.Rect(0, 0, 1, 1), 1); @@ -184,7 +191,7 @@ $.Viewport.prototype = { this._contentSizeNoRotate = this._contentBoundsNoRotate.getSize().times( contentFactor); - this._contentBounds = bounds.rotate(this.degrees).getBoundingBox(); + this._contentBounds = bounds.rotate(this.getRotation(true)).getBoundingBox(); this._contentSize = this._contentBounds.getSize().times(contentFactor); this._contentAspectRatio = this._contentSize.x / this._contentSize.y; @@ -367,7 +374,7 @@ $.Viewport.prototype = { * @returns {OpenSeadragon.Rect} The location you are zoomed/panned to, in viewport coordinates. */ getBounds: function(current) { - return this.getBoundsNoRotate(current).rotate(-this.getRotation()); + return this.getBoundsNoRotate(current).rotate(-this.getRotation(current)); }, /** @@ -399,7 +406,7 @@ $.Viewport.prototype = { */ getBoundsWithMargins: function(current) { return this.getBoundsNoRotateWithMargins(current).rotate( - -this.getRotation(), this.getCenter(current)); + -this.getRotation(current), this.getCenter(current)); }, /** @@ -585,7 +592,7 @@ $.Viewport.prototype = { bounds.y !== constrainedBounds.y || immediately) { this.fitBounds( - constrainedBounds.rotate(-this.getRotation()), + constrainedBounds.rotate(-this.getRotation(true)), immediately); } return this; @@ -878,13 +885,27 @@ $.Viewport.prototype = { * Rotates this viewport to the angle specified. * @function * @param {Number} degrees The degrees to set the rotation to. + * @param {Boolean} [immediately=false] Whether to animate to the new angle + * or rotate immediately. * @return {OpenSeadragon.Viewport} Chainable. */ - setRotation: function(degrees) { + setRotation: function(degrees, immediately) { if (!this.viewer || !this.viewer.drawer.canRotate()) { return this; } - this.degrees = $.positiveModulo(degrees, 360); + + if (this.degreesSpring.target.value === degrees && + this.degreesSpring.isAtTargetValue()) { + return this; + } + if (immediately) { + this.degreesSpring.resetTo(degrees); + } else { + this.degreesSpring.springTo(degrees); + } + + this.degrees = $.positiveModulo(this.degreesSpring.target.value, 360); + this._setContentBounds( this.viewer.world.getHomeBounds(), this.viewer.world.getContentFactor()); @@ -907,10 +928,13 @@ $.Viewport.prototype = { /** * Gets the current rotation in degrees. * @function + * @param {Boolean} [current=false] True for current rotation, false for target. * @return {Number} The current rotation in degrees. */ - getRotation: function() { - return this.degrees; + getRotation: function(current) { + return current ? + this.degreesSpring.current.value : + this.degreesSpring.target.value; }, /** @@ -978,13 +1002,18 @@ $.Viewport.prototype = { this.centerSpringX.update(); this.centerSpringY.update(); + this.degreesSpring.update(); + var changed = this.centerSpringX.current.value !== this._oldCenterX || this.centerSpringY.current.value !== this._oldCenterY || - this.zoomSpring.current.value !== this._oldZoom; + this.zoomSpring.current.value !== this._oldZoom || + this.degreesSpring.current.value !== this._oldDegree; + this._oldCenterX = this.centerSpringX.current.value; this._oldCenterY = this.centerSpringY.current.value; this._oldZoom = this.zoomSpring.current.value; + this._oldDegree = this.degreesSpring.current.value; return changed; }, @@ -1035,7 +1064,7 @@ $.Viewport.prototype = { */ deltaPixelsFromPoints: function(deltaPoints, current) { return this.deltaPixelsFromPointsNoRotate( - deltaPoints.rotate(this.getRotation()), + deltaPoints.rotate(this.getRotation(current)), current); }, @@ -1064,7 +1093,7 @@ $.Viewport.prototype = { */ deltaPointsFromPixels: function(deltaPixels, current) { return this.deltaPointsFromPixelsNoRotate(deltaPixels, current) - .rotate(-this.getRotation()); + .rotate(-this.getRotation(current)); }, /** @@ -1106,7 +1135,7 @@ $.Viewport.prototype = { // private _pixelFromPoint: function(point, bounds) { return this._pixelFromPointNoRotate( - point.rotate(this.getRotation(), this.getCenter(true)), + point.rotate(this.getRotation(true), this.getCenter(true)), bounds); }, @@ -1139,8 +1168,8 @@ $.Viewport.prototype = { */ pointFromPixel: function(pixel, current) { return this.pointFromPixelNoRotate(pixel, current).rotate( - -this.getRotation(), - this.getCenter(true) + -this.getRotation(current), + this.getCenter(current) ); },