diff --git a/src/navigator.js b/src/navigator.js index 24d35a3d..d07a2bba 100644 --- a/src/navigator.js +++ b/src/navigator.js @@ -50,6 +50,7 @@ $.Navigator = function( options ){ var viewer = options.viewer, + _this = this, viewerSize, navigatorSize, unneededElement; @@ -161,6 +162,11 @@ $.Navigator = function( options ){ style.cursor = 'default'; }( this.displayRegion.style, this.borderWidth )); + this.displayRegionContainer = $.makeNeutralElement("div"); + this.displayRegionContainer.id = this.element.id + '-displayregioncontainer'; + this.displayRegionContainer.className = "displayregioncontainer"; + this.displayRegionContainer.style.width = "100%"; + this.displayRegionContainer.style.height = "100%"; this.element.innerTracker = new $.MouseTracker({ element: this.element, @@ -203,12 +209,22 @@ $.Navigator = function( options ){ $.Viewer.apply( this, [ options ] ); - this.element.getElementsByTagName( 'div' )[0].appendChild( this.displayRegion ); + this.displayRegionContainer.appendChild(this.displayRegion); + this.element.getElementsByTagName('div')[0].appendChild(this.displayRegionContainer); unneededElement = this.element.getElementsByTagName('textarea')[0]; if (unneededElement) { unneededElement.parentNode.removeChild(unneededElement); } + if (options.navigatorRotate) + { + options.viewer.addHandler("rotate", function (args) { + _setTransformRotate(_this.displayRegionContainer, args.degrees); + _setTransformRotate(_this.displayRegion, -args.degrees); + _this.viewport.setRotation(args.degrees); + }); + + } }; $.extend( $.Navigator.prototype, $.EventSource.prototype, $.Viewer.prototype, /** @lends OpenSeadragon.Navigator.prototype */{ @@ -225,7 +241,7 @@ $.extend( $.Navigator.prototype, $.EventSource.prototype, $.Viewer.prototype, /* (this.container.clientHeight === 0 ? 1 : this.container.clientHeight) ); if ( !containerSize.equals( this.oldContainerSize ) ) { - var oldBounds = this.viewport.getBounds(); + var oldBounds = this.viewport.getBounds().rotate(this.viewport.degrees); var oldCenter = this.viewport.getCenter(); this.viewport.resize( containerSize, true ); var imageHeight = 1 / this.source.aspectRatio; @@ -318,7 +334,7 @@ $.extend( $.Navigator.prototype, $.EventSource.prototype, $.Viewer.prototype, /* */ function onCanvasClick( event ) { if ( event.quick && this.viewer.viewport ) { - this.viewer.viewport.panTo( this.viewport.pointFromPixel( event.position ) ); + this.viewer.viewport.panTo( this.viewport.pointFromPixel( event.position ).rotate( -this.viewer.viewport.degrees, this.viewer.viewport.getHomeBounds().getCenter() ) ); this.viewer.viewport.applyConstraints(); } } @@ -390,5 +406,18 @@ function onCanvasScroll( event ) { return false; } +/** + * @function + * @private + * @param {Object} element + * @param {Number} degrees + */ +function _setTransformRotate (element, degrees) { + element.style.webkitTransform = "rotate(" + degrees + "deg)"; + element.style.mozTransform = "rotate(" + degrees + "deg)"; + element.style.msTransform = "rotate(" + degrees + "deg)"; + element.style.oTransform = "rotate(" + degrees + "deg)"; + element.style.transform = "rotate(" + degrees + "deg)"; +} }( OpenSeadragon )); diff --git a/src/openseadragon.js b/src/openseadragon.js index 5bccc84b..a74bbfcc 100644 --- a/src/openseadragon.js +++ b/src/openseadragon.js @@ -378,6 +378,9 @@ * Set to false to prevent polling for navigator size changes. Useful for providing custom resize behavior. * Setting to false can also improve performance when the navigator is configured to a fixed size. * + * @property {Boolean} [navigatorRotate=true] + * If true, the navigator will be rotated together with the viewer. + * * @property {Number} [controlsFadeDelay=2000] * The number of milliseconds to wait once the user has stopped interacting * with the interface before begining to fade the controls. Assumes @@ -955,6 +958,7 @@ window.OpenSeadragon = window.OpenSeadragon || function( options ){ navigatorHeight: null, navigatorWidth: null, navigatorAutoResize: true, + navigatorRotate: true, // INITIAL ROTATION degrees: 0, diff --git a/src/viewer.js b/src/viewer.js index 9f420ffd..5435b3a0 100644 --- a/src/viewer.js +++ b/src/viewer.js @@ -1957,7 +1957,8 @@ function openTileSource( viewer, source ) { minZoomLevel: _this.minZoomLevel, maxZoomLevel: _this.maxZoomLevel, viewer: _this, - degrees: _this.degrees + degrees: _this.degrees, + navigatorRotate: _this.navigatorRotate }); } @@ -2024,7 +2025,8 @@ function openTileSource( viewer, source ) { tileSources: source, tileHost: _this.tileHost, prefixUrl: _this.prefixUrl, - viewer: _this + viewer: _this, + navigatorRotate: _this.navigatorRotate }); } } diff --git a/src/viewport.js b/src/viewport.js index 38ecfa27..e1231500 100644 --- a/src/viewport.js +++ b/src/viewport.js @@ -732,6 +732,20 @@ $.Viewport.prototype = /** @lends OpenSeadragon.Viewport.prototype */{ this.degrees = degrees; this.viewer.forceRedraw(); + /** + * Raised when rotation has been changed. + * + * @event update-viewport + * @memberof OpenSeadragon.Viewer + * @type {object} + * @property {OpenSeadragon.Viewer} eventSource - A reference to the Viewer which raised the event. + * @property {Number} degrees - The number of degrees the rotation was set to. + * @property {?Object} userData - Arbitrary subscriber-defined object. + */ + if (this.viewer !== null) + { + this.viewer.raiseEvent('rotate', {"degrees": degrees}); + } return this; },