From d9ddc5f65d5b6397e914b264176fe4d3664e4db7 Mon Sep 17 00:00:00 2001 From: esmondb Date: Sat, 31 May 2014 08:30:25 +0100 Subject: [PATCH 01/27] Fix for IIPServer style urls when using DZI. --- src/dzitilesource.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/dzitilesource.js b/src/dzitilesource.js index daed278e..5ef2585e 100644 --- a/src/dzitilesource.js +++ b/src/dzitilesource.js @@ -138,7 +138,12 @@ $.extend( $.DziTileSource.prototype, $.TileSource.prototype, /** @lends OpenSead if (url && !options.tilesUrl) { options.tilesUrl = url.replace(/([^\/]+)\.(dzi|xml|js)(\?.*|$)/, '$1_files/'); - options.queryParams = url.match(/\?.*/); + + if (url.search(/\.(dzi|xml|js)\?/) != -1) { + options.queryParams = url.match(/\?.*/); + }else{ + options.queryParams = ''; + } } return options; From e967b3c7a3ba7ccf468387c674d0698e0ada8dff Mon Sep 17 00:00:00 2001 From: Ian Gilman Date: Mon, 2 Jun 2014 09:10:17 -0700 Subject: [PATCH 02/27] Changelog for #413 --- changelog.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/changelog.txt b/changelog.txt index bebc3829..47355b56 100644 --- a/changelog.txt +++ b/changelog.txt @@ -3,6 +3,8 @@ OPENSEADRAGON CHANGELOG 1.1.2: (in progress) +* Fix for IIPServer-style urls when using DZI (#413) + 1.1.1: * Fixed issue with dragging the navigator highlight on Webkit browsers (#395) From 02b606680de4f55f6d87595776a6a5545ef8133d Mon Sep 17 00:00:00 2001 From: Ian Gilman Date: Mon, 2 Jun 2014 11:02:22 -0700 Subject: [PATCH 03/27] Updated to latest npm packages --- Gruntfile.js | 19 ++++++++----------- package.json | 22 +++++++++++----------- src/openseadragon.js | 8 +++----- 3 files changed, 22 insertions(+), 27 deletions(-) diff --git a/Gruntfile.js b/Gruntfile.js index a90a0974..0cd48304 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -52,6 +52,11 @@ module.exports = function(grunt) { "src/viewport.js" ]; + // ---------- + grunt.event.once('git-describe', function (rev) { + grunt.config.set('gitInfo', rev); + }); + // ---------- // Project configuration. grunt.initConfig({ @@ -101,12 +106,8 @@ module.exports = function(grunt) { uglify: { options: { preserveComments: "some", - sourceMap: function (filename) { - return filename.replace(/\.js$/, '.js.map'); - }, - sourceMappingURL: function (filename) { - return filename.replace(/\.js$/, '.js.map').replace('build/openseadragon/', ''); - }, + sourceMap: true, + sourceMapName: 'build/openseadragon/openseadragon.min.js.map' }, openseadragon: { src: [ distribution ], @@ -161,11 +162,7 @@ module.exports = function(grunt) { afterconcat: [ distribution ] }, "git-describe": { - build: { - options: { - prop: "gitInfo" - } - } + build: {} } }); diff --git a/package.json b/package.json index aa123561..70ce5a73 100644 --- a/package.json +++ b/package.json @@ -3,17 +3,17 @@ "version": "1.1.1", "description": "Provides a smooth, zoomable user interface for HTML/Javascript.", "devDependencies": { - "grunt": "~0.4.1", - "grunt-contrib-compress": "~0.5.2", - "grunt-contrib-concat": "~0.3.0", - "grunt-contrib-jshint": "~0.7.2", - "grunt-contrib-uglify": "~0.2.7", - "grunt-contrib-qunit": "~0.3.0", - "grunt-contrib-connect": "~0.5.0", - "grunt-contrib-watch": "~0.5.3", - "grunt-contrib-clean": "~0.5.0", - "grunt-git-describe": "~2.0.0", - "grunt-text-replace": "~0.3.9" + "grunt": "^0.4.5", + "grunt-contrib-clean": "^0.5.0", + "grunt-text-replace": "^0.3.11", + "grunt-contrib-concat": "^0.4.0", + "grunt-git-describe": "^2.3.2", + "grunt-contrib-uglify": "^0.4.0", + "grunt-contrib-watch": "^0.6.1", + "grunt-contrib-qunit": "^0.5.1", + "grunt-contrib-jshint": "^0.10.0", + "grunt-contrib-compress": "^0.9.1", + "grunt-contrib-connect": "^0.7.1" }, "scripts": { "test": "grunt test" diff --git a/src/openseadragon.js b/src/openseadragon.js index 14ddd3d5..0c167934 100644 --- a/src/openseadragon.js +++ b/src/openseadragon.js @@ -656,14 +656,12 @@ window.OpenSeadragon = window.OpenSeadragon || function( options ){ * @property {Number} revision - The revision number. * @since 1.0.0 */ - /* jshint ignore:start */ $.version = { versionStr: '<%= osdVersion.versionStr %>', - major: <%= osdVersion.major %>, - minor: <%= osdVersion.minor %>, - revision: <%= osdVersion.revision %> + major: parseInt('<%= osdVersion.major %>', 10), + minor: parseInt('<%= osdVersion.minor %>', 10), + revision: parseInt('<%= osdVersion.revision %>', 10) }; - /* jshint ignore:end */ /** From 0164c3cc7cf0deb0434022ad409d2036616f722e Mon Sep 17 00:00:00 2001 From: Ian Gilman Date: Tue, 3 Jun 2014 09:09:43 -0700 Subject: [PATCH 04/27] Bumping node version for travis --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index b30fcb75..578f402c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,5 @@ language: node_js node_js: - - 0.8 + - 0.10 before_script: - npm install -g grunt-cli From eb58d3fd115929b183c7036ba3e54b26cc2c8de6 Mon Sep 17 00:00:00 2001 From: Ian Gilman Date: Thu, 5 Jun 2014 09:53:03 -0700 Subject: [PATCH 05/27] Fixed QUnit dependency --- package.json | 3 ++- test/test.html | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 70ce5a73..486d8743 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,8 @@ "grunt-contrib-qunit": "^0.5.1", "grunt-contrib-jshint": "^0.10.0", "grunt-contrib-compress": "^0.9.1", - "grunt-contrib-connect": "^0.7.1" + "grunt-contrib-connect": "^0.7.1", + "qunitjs": "^1.14.0" }, "scripts": { "test": "grunt test" diff --git a/test/test.html b/test/test.html index 64062197..592847bd 100644 --- a/test/test.html +++ b/test/test.html @@ -3,14 +3,14 @@ OpenSeadragon QUnit - +
- + From 59ab6562d3cdab5020ab5d00fd58f0635ca59283 Mon Sep 17 00:00:00 2001 From: esmondb Date: Sat, 14 Jun 2014 10:15:40 +0100 Subject: [PATCH 06/27] Removes unnecessary trailing commas which stops google's closure compiler. --- src/imageLoader.js | 2 +- src/mousetracker.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/imageLoader.js b/src/imageLoader.js index 2e810d38..4ada9832 100644 --- a/src/imageLoader.js +++ b/src/imageLoader.js @@ -47,7 +47,7 @@ function ImageJob ( options ) { $.extend( true, this, { timeout: $.DEFAULT_SETTINGS.timeout, - jobId: null, + jobId: null }, options ); /** diff --git a/src/mousetracker.js b/src/mousetracker.js index 03ed2b43..f92691c8 100644 --- a/src/mousetracker.js +++ b/src/mousetracker.js @@ -1773,7 +1773,7 @@ for ( i = 0; i < touchCount; i++ ) { gPoints.push( { id: event.changedTouches[ i ].identifier, - type: 'touch', + type: 'touch' } ); } @@ -1925,7 +1925,7 @@ gPoint = { id: event.pointerId, - type: getPointerType( event ), + type: getPointerType( event ) }; updatePointersCancel( tracker, event, [ gPoint ] ); From 764fa3e34aca8e8c69db05665987681a8495795d Mon Sep 17 00:00:00 2001 From: Henri Astre Date: Tue, 17 Jun 2014 17:26:10 -0700 Subject: [PATCH 07/27] Fix memory leak while destroying the viewer. --- src/drawer.js | 17 ++++++++- src/mousetracker.js | 3 ++ src/viewer.js | 9 ++++- test/demo/memory_check.html | 71 +++++++++++++++++++++++++++++++++++++ 4 files changed, 98 insertions(+), 2 deletions(-) create mode 100644 test/demo/memory_check.html diff --git a/src/drawer.js b/src/drawer.js index 54b07281..95da18ce 100644 --- a/src/drawer.js +++ b/src/drawer.js @@ -302,7 +302,22 @@ $.Drawer.prototype = /** @lends OpenSeadragon.Drawer.prototype */{ */ canRotate: function() { return this.useCanvas; - } + }, + + /** + * Destroy the drawer (unload current loaded tiles) + */ + destroy: function() { + + //unload current loaded tiles (=empty TILE_CACHE) + for (var i=0; i + + + OpenSeadragon Memory Check Demo + + + + +
+ Simple demo page to monitor OpenSeadragon Memory Usage. +
+ + + +
+ + + \ No newline at end of file From a563bdb65805730358eee5c7194ff4a9b46388eb Mon Sep 17 00:00:00 2001 From: Henri Astre Date: Wed, 18 Jun 2014 10:35:23 -0700 Subject: [PATCH 08/27] fix .close() called after .destroy() + spacing --- src/drawer.js | 31 ++++++++-------- src/mousetracker.js | 6 ++-- src/viewer.js | 26 +++++++++----- test/basic.js | 1 + test/demo/memory_check.html | 71 ------------------------------------- test/demo/memorycheck.html | 57 +++++++++++++++++++++++++++++ 6 files changed, 95 insertions(+), 97 deletions(-) delete mode 100644 test/demo/memory_check.html create mode 100644 test/demo/memorycheck.html diff --git a/src/drawer.js b/src/drawer.js index 95da18ce..10165ffb 100644 --- a/src/drawer.js +++ b/src/drawer.js @@ -303,21 +303,22 @@ $.Drawer.prototype = /** @lends OpenSeadragon.Drawer.prototype */{ canRotate: function() { return this.useCanvas; }, - - /** - * Destroy the drawer (unload current loaded tiles) - */ - destroy: function() { - - //unload current loaded tiles (=empty TILE_CACHE) - for (var i=0; i - - - OpenSeadragon Memory Check Demo - - - - -
- Simple demo page to monitor OpenSeadragon Memory Usage. -
- - - -
- - - \ No newline at end of file diff --git a/test/demo/memorycheck.html b/test/demo/memorycheck.html new file mode 100644 index 00000000..bebe80da --- /dev/null +++ b/test/demo/memorycheck.html @@ -0,0 +1,57 @@ + + + + OpenSeadragon Memory Check Demo + + + + +
+ Simple demo page to monitor OpenSeadragon Memory Usage. +
+ + + +
+ + + From 48aded3824d1745b0152c74045f9246890d1abbf Mon Sep 17 00:00:00 2001 From: Henri Astre Date: Wed, 18 Jun 2014 11:11:34 -0700 Subject: [PATCH 09/27] add fitBoundsWithConstraints() to the viewport. --- src/viewport.js | 125 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 123 insertions(+), 2 deletions(-) diff --git a/src/viewport.js b/src/viewport.js index aadb81e9..6fab78ad 100644 --- a/src/viewport.js +++ b/src/viewport.js @@ -471,8 +471,129 @@ $.Viewport.prototype = /** @lends OpenSeadragon.Viewport.prototype */{ return this.zoomTo( newZoom, referencePoint, immediately ); }, - - + + /** + * @function + * @param {OpenSeadragon.Rect} bounds + * @param {Boolean} immediately + * @return {OpenSeadragon.Viewport} Chainable. + */ + fitBoundsWithConstraints: function( bounds, immediately ) { + var aspect = this.getAspectRatio(), + center = bounds.getCenter(), + newBounds = new $.Rect( + bounds.x, + bounds.y, + bounds.width, + bounds.height + ), + oldBounds, + oldZoom, + newZoom, + referencePoint, + horizontalThreshold, + verticalThreshold, + left, + right, + top, + bottom, + dx = 0, + dy = 0, + newBoundsAspectRatio; + + if ( newBounds.getAspectRatio() >= aspect ) { + newBounds.height = bounds.width / aspect; + newBounds.y = center.y - newBounds.height / 2; + } else { + newBounds.width = bounds.height * aspect; + newBounds.x = center.x - newBounds.width / 2; + } + + newBoundsAspectRatio = newBounds.getAspectRatio(); + + this.panTo( this.getCenter( true ), true ); + this.zoomTo( this.getZoom( true ), null, true ); + + oldBounds = this.getBounds(); + oldZoom = this.getZoom(); + newZoom = 1.0 / newBounds.width; + + var newConstrainedZoom = Math.max( + Math.min(newZoom, this.getMaxZoom() ), + this.getMinZoom() + ); + + if (newZoom !== newConstrainedZoom) { + newZoom = newConstrainedZoom; + newBounds.width = 1.0 / newZoom; + newBounds.x = center.x - newBounds.width / 2; + newBounds.height = newBounds.width / newBoundsAspectRatio; + newBounds.y = center.y - newBounds.height / 2; + } + + horizontalThreshold = this.visibilityRatio * newBounds.width; + verticalThreshold = this.visibilityRatio * newBounds.height; + + left = newBounds.x + newBounds.width; + right = 1 - newBounds.x; + top = newBounds.y + newBounds.height; + bottom = this.contentAspectY - newBounds.y; + + if ( this.wrapHorizontal ) { + //do nothing + } else { + if ( left < horizontalThreshold ) { + dx = horizontalThreshold - left; + } + if ( right < horizontalThreshold ) { + dx = dx ? + ( dx + right - horizontalThreshold ) / 2 : + ( right - horizontalThreshold ); + } + } + + if ( this.wrapVertical ) { + //do nothing + } else { + if ( top < verticalThreshold ) { + dy = ( verticalThreshold - top ); + } + if ( bottom < verticalThreshold ) { + dy = dy ? + ( dy + bottom - verticalThreshold ) / 2 : + ( bottom - verticalThreshold ); + } + } + + if ( dx || dy ) { + newBounds.x += dx; + newBounds.y += dy; + if( newBounds.width > 1 ){ + newBounds.x = 0.5 - newBounds.width/2; + } + if( newBounds.height > this.contentAspectY ){ + newBounds.y = this.contentAspectY/2 - newBounds.height/2; + } + } + + if ( newZoom == oldZoom || newBounds.width == oldBounds.width ) { + return this.panTo( newBounds.getCenter(), immediately ); + } + + referencePoint = oldBounds.getTopLeft().times( + this.containerSize.x / oldBounds.width + ).minus( + newBounds.getTopLeft().times( + this.containerSize.x / newBounds.width + ) + ).divide( + this.containerSize.x / oldBounds.width - + this.containerSize.x / newBounds.width + ); + + return this.zoomTo( newZoom, referencePoint, immediately ); + }, + /** * @function * @param {Boolean} immediately From f86f9063fd32a4164169cb8ec4c7ab61a02f69fb Mon Sep 17 00:00:00 2001 From: Henri Astre Date: Wed, 18 Jun 2014 12:56:36 -0700 Subject: [PATCH 10/27] Improve comment for destroy() method. --- src/viewer.js | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/viewer.js b/src/viewer.js index cb8e295f..7ba1e7c0 100644 --- a/src/viewer.js +++ b/src/viewer.js @@ -578,8 +578,17 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype, /** - * Function to destroy the viewer and clean up everything created by - * OpenSeadragon. + * Function to destroy the viewer and clean up everything created by OpenSeadragon. + * + * Example: + * var viewer = OpenSeadragon({ + * [...] + * }); + * + * //when you are done with the viewer: + * viewer.destroy(); + * viewer = null; //important + * * @function */ destroy: function( ) { From d7e53af27be49ead570269320f1027f1d37a2f67 Mon Sep 17 00:00:00 2001 From: Ian Gilman Date: Thu, 19 Jun 2014 09:14:16 -0700 Subject: [PATCH 11/27] Changelog for #421 --- changelog.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/changelog.txt b/changelog.txt index 47355b56..f66a1eda 100644 --- a/changelog.txt +++ b/changelog.txt @@ -4,6 +4,7 @@ OPENSEADRAGON CHANGELOG 1.1.2: (in progress) * Fix for IIPServer-style urls when using DZI (#413) +* Fix memory leak while destroying the viewer (#421) 1.1.1: From e67f6b400326265eb45df02ff3d5f7c50724871e Mon Sep 17 00:00:00 2001 From: Henri Astre Date: Fri, 20 Jun 2014 13:44:59 -0700 Subject: [PATCH 12/27] First attempt at removing duplicated code I've created _applyBoundaryConstraints() and _fitBounds() to remove duplicated code. --- src/viewport.js | 275 ++++++++++++++++++++++-------------------------- 1 file changed, 123 insertions(+), 152 deletions(-) diff --git a/src/viewport.js b/src/viewport.js index 6fab78ad..ddc26f0e 100644 --- a/src/viewport.js +++ b/src/viewport.js @@ -319,41 +319,36 @@ $.Viewport.prototype = /** @lends OpenSeadragon.Viewport.prototype */{ return this.zoomSpring.target.value; } }, - + /** * @function - * @return {OpenSeadragon.Viewport} Chainable. - * @fires OpenSeadragon.Viewer.event:constrain - */ - applyConstraints: function( immediately ) { - var actualZoom = this.getZoom(), - constrainedZoom = Math.max( - Math.min( actualZoom, this.getMaxZoom() ), - this.getMinZoom() - ), - bounds, - horizontalThreshold, + * @param {OpenSeadragon.Rect} bounds + * @param {Boolean} immediately + * @return {OpenSeadragon.Rect} constrained bounds. + */ + _applyBoundaryConstraints: function( bounds, immediately ) { + var horizontalThreshold, verticalThreshold, left, right, top, bottom, dx = 0, - dy = 0; + dy = 0, + newBounds = new $.Rect( + bounds.x, + bounds.y, + bounds.width, + bounds.height + ); + + horizontalThreshold = this.visibilityRatio * newBounds.width; + verticalThreshold = this.visibilityRatio * newBounds.height; - if ( actualZoom != constrainedZoom ) { - this.zoomTo( constrainedZoom, this.zoomPoint, immediately ); - } - - bounds = this.getBounds(); - - horizontalThreshold = this.visibilityRatio * bounds.width; - verticalThreshold = this.visibilityRatio * bounds.height; - - left = bounds.x + bounds.width; - right = 1 - bounds.x; - top = bounds.y + bounds.height; - bottom = this.contentAspectY - bounds.y; + left = newBounds.x + newBounds.width; + right = 1 - newBounds.x; + top = newBounds.y + newBounds.height; + bottom = this.contentAspectY - newBounds.y; if ( this.wrapHorizontal ) { //do nothing @@ -382,15 +377,43 @@ $.Viewport.prototype = /** @lends OpenSeadragon.Viewport.prototype */{ } if ( dx || dy || immediately ) { - bounds.x += dx; - bounds.y += dy; - if( bounds.width > 1 ){ - bounds.x = 0.5 - bounds.width/2; + newBounds.x += dx; + newBounds.y += dy; + if( newBounds.width > 1 ){ + newBounds.x = 0.5 - newBounds.width/2; } - if( bounds.height > this.contentAspectY ){ - bounds.y = this.contentAspectY/2 - bounds.height/2; + if( newBounds.height > this.contentAspectY ){ + newBounds.y = this.contentAspectY/2 - newBounds.height/2; } - this.fitBounds( bounds, immediately ); + } + + return newBounds; + }, + + /** + * @function + * @return {OpenSeadragon.Viewport} Chainable. + * @fires OpenSeadragon.Viewer.event:constrain + */ + applyConstraints: function( immediately ) { + var actualZoom = this.getZoom(), + constrainedZoom = Math.max( + Math.min( actualZoom, this.getMaxZoom() ), + this.getMinZoom() + ), + bounds, + constrainedBounds; + + if ( actualZoom != constrainedZoom ) { + this.zoomTo( constrainedZoom, this.zoomPoint, immediately ); + } + + bounds = this.getBounds(); + + constrainedBounds = this._applyBoundaryConstraints( bounds, immediately ); + + if ( bounds.x !== constrainedBounds.x || bounds.y !== constrainedBounds.y || immediately ){ + this.fitBounds( constrainedBounds, immediately ); } if( this.viewer ){ @@ -419,66 +442,18 @@ $.Viewport.prototype = /** @lends OpenSeadragon.Viewport.prototype */{ ensureVisible: function( immediately ) { return this.applyConstraints( immediately ); }, - - /** - * @function - * @param {OpenSeadragon.Rect} bounds - * @param {Boolean} immediately - * @return {OpenSeadragon.Viewport} Chainable. - */ - fitBounds: function( bounds, immediately ) { - var aspect = this.getAspectRatio(), - center = bounds.getCenter(), - newBounds = new $.Rect( - bounds.x, - bounds.y, - bounds.width, - bounds.height - ), - oldBounds, - oldZoom, - newZoom, - referencePoint; - - if ( newBounds.getAspectRatio() >= aspect ) { - newBounds.height = bounds.width / aspect; - newBounds.y = center.y - newBounds.height / 2; - } else { - newBounds.width = bounds.height * aspect; - newBounds.x = center.x - newBounds.width / 2; - } - - this.panTo( this.getCenter( true ), true ); - this.zoomTo( this.getZoom( true ), null, true ); - - oldBounds = this.getBounds(); - oldZoom = this.getZoom(); - newZoom = 1.0 / newBounds.width; - if ( newZoom == oldZoom || newBounds.width == oldBounds.width ) { - return this.panTo( center, immediately ); - } - - referencePoint = oldBounds.getTopLeft().times( - this.containerSize.x / oldBounds.width - ).minus( - newBounds.getTopLeft().times( - this.containerSize.x / newBounds.width - ) - ).divide( - this.containerSize.x / oldBounds.width - - this.containerSize.x / newBounds.width - ); - - return this.zoomTo( newZoom, referencePoint, immediately ); - }, /** * @function * @param {OpenSeadragon.Rect} bounds - * @param {Boolean} immediately + * @param {Object} options (immediately=null, constraints=false) * @return {OpenSeadragon.Viewport} Chainable. */ - fitBoundsWithConstraints: function( bounds, immediately ) { + _fitBounds: function( bounds, options ) { + var newOptions = options || {}; + var immediately = newOptions.immediately || null; + var constraints = newOptions.constraints || false; + var aspect = this.getAspectRatio(), center = bounds.getCenter(), newBounds = new $.Rect( @@ -491,15 +466,8 @@ $.Viewport.prototype = /** @lends OpenSeadragon.Viewport.prototype */{ oldZoom, newZoom, referencePoint, - horizontalThreshold, - verticalThreshold, - left, - right, - top, - bottom, - dx = 0, - dy = 0, - newBoundsAspectRatio; + newBoundsAspectRatio, + newConstrainedZoom; if ( newBounds.getAspectRatio() >= aspect ) { newBounds.height = bounds.width / aspect; @@ -509,7 +477,9 @@ $.Viewport.prototype = /** @lends OpenSeadragon.Viewport.prototype */{ newBounds.x = center.x - newBounds.width / 2; } - newBoundsAspectRatio = newBounds.getAspectRatio(); + if ( constraints ) { + newBoundsAspectRatio = newBounds.getAspectRatio(); + } this.panTo( this.getCenter( true ), true ); this.zoomTo( this.getZoom( true ), null, true ); @@ -518,66 +488,41 @@ $.Viewport.prototype = /** @lends OpenSeadragon.Viewport.prototype */{ oldZoom = this.getZoom(); newZoom = 1.0 / newBounds.width; - var newConstrainedZoom = Math.max( - Math.min(newZoom, this.getMaxZoom() ), - this.getMinZoom() - ); - - if (newZoom !== newConstrainedZoom) { - newZoom = newConstrainedZoom; - newBounds.width = 1.0 / newZoom; - newBounds.x = center.x - newBounds.width / 2; - newBounds.height = newBounds.width / newBoundsAspectRatio; - newBounds.y = center.y - newBounds.height / 2; - } - - horizontalThreshold = this.visibilityRatio * newBounds.width; - verticalThreshold = this.visibilityRatio * newBounds.height; - - left = newBounds.x + newBounds.width; - right = 1 - newBounds.x; - top = newBounds.y + newBounds.height; - bottom = this.contentAspectY - newBounds.y; - - if ( this.wrapHorizontal ) { - //do nothing - } else { - if ( left < horizontalThreshold ) { - dx = horizontalThreshold - left; + if ( constraints ) { + newConstrainedZoom = Math.max( + Math.min(newZoom, this.getMaxZoom() ), + this.getMinZoom() + ); + + if (newZoom !== newConstrainedZoom) { + newZoom = newConstrainedZoom; + newBounds.width = 1.0 / newZoom; + newBounds.x = center.x - newBounds.width / 2; + newBounds.height = newBounds.width / newBoundsAspectRatio; + newBounds.y = center.y - newBounds.height / 2; } - if ( right < horizontalThreshold ) { - dx = dx ? - ( dx + right - horizontalThreshold ) / 2 : - ( right - horizontalThreshold ); - } - } - - if ( this.wrapVertical ) { - //do nothing - } else { - if ( top < verticalThreshold ) { - dy = ( verticalThreshold - top ); - } - if ( bottom < verticalThreshold ) { - dy = dy ? - ( dy + bottom - verticalThreshold ) / 2 : - ( bottom - verticalThreshold ); - } - } - - if ( dx || dy ) { - newBounds.x += dx; - newBounds.y += dy; - if( newBounds.width > 1 ){ - newBounds.x = 0.5 - newBounds.width/2; - } - if( newBounds.height > this.contentAspectY ){ - newBounds.y = this.contentAspectY/2 - newBounds.height/2; + + newBounds = this._applyBoundaryConstraints( newBounds, immediately ); + + if( this.viewer ){ + /** + * Raised when the viewport constraints are applied (see {@link OpenSeadragon.Viewport#applyConstraints}). + * + * @event constrain + * @memberof OpenSeadragon.Viewer + * @type {object} + * @property {OpenSeadragon.Viewer} eventSource - A reference to the Viewer which raised this event. + * @property {Boolean} immediately + * @property {?Object} userData - Arbitrary subscriber-defined object. + */ + this.viewer.raiseEvent( 'constrain', { + immediately: immediately + }); } } if ( newZoom == oldZoom || newBounds.width == oldBounds.width ) { - return this.panTo( newBounds.getCenter(), immediately ); + return this.panTo( constraints ? newBounds.getCenter() : center, immediately ); } referencePoint = oldBounds.getTopLeft().times( @@ -592,6 +537,32 @@ $.Viewport.prototype = /** @lends OpenSeadragon.Viewport.prototype */{ ); return this.zoomTo( newZoom, referencePoint, immediately ); + }, + + /** + * @function + * @param {OpenSeadragon.Rect} bounds + * @param {Boolean} immediately + * @return {OpenSeadragon.Viewport} Chainable. + */ + fitBounds: function( bounds, immediately ) { + return this._fitBounds( bounds, { + immediately: immediately, + constraints: false + } ); + }, + + /** + * @function + * @param {OpenSeadragon.Rect} bounds + * @param {Boolean} immediately + * @return {OpenSeadragon.Viewport} Chainable. + */ + fitBoundsWithConstraints: function( bounds, immediately ) { + return this._fitBounds( bounds, { + immediately: immediately, + constraints: true + } ); }, /** From e7d8cff10977d808e6ef5a5eacecfe86c17cf220 Mon Sep 17 00:00:00 2001 From: Henri Astre Date: Fri, 20 Jun 2014 16:18:04 -0700 Subject: [PATCH 13/27] adding demo to show benefit of fitBoundsWithConstraints --- test/demo/fitBounds.html | 113 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100644 test/demo/fitBounds.html diff --git a/test/demo/fitBounds.html b/test/demo/fitBounds.html new file mode 100644 index 00000000..60651bed --- /dev/null +++ b/test/demo/fitBounds.html @@ -0,0 +1,113 @@ + + + + OpenSeadragon Memory Check Demo + + + + +
+ Simple demo page to show 'viewport.fitBounds().applyConstraints()' issue. +
+ +
+
+ + + + + + + From 118c2b2c8735e277a0876f0f38fd683e78aa47e9 Mon Sep 17 00:00:00 2001 From: Henri Astre Date: Fri, 20 Jun 2014 17:53:07 -0700 Subject: [PATCH 14/27] hiding properly _ functions. --- src/viewport.js | 477 ++++++++++++++++++++++++------------------------ 1 file changed, 239 insertions(+), 238 deletions(-) diff --git a/src/viewport.js b/src/viewport.js index ddc26f0e..6f5ee841 100644 --- a/src/viewport.js +++ b/src/viewport.js @@ -46,7 +46,8 @@ $.Viewport = function( options ) { //backward compatibility for positional args while prefering more //idiomatic javascript options object as the only argument - var args = arguments; + var args = arguments, + that = this; if( args.length && args[ 0 ] instanceof $.Point ){ options = { containerSize: args[ 0 ], @@ -87,7 +88,244 @@ $.Viewport = function( options ) { degrees: $.DEFAULT_SETTINGS.degrees }, options ); + + /** + * @function + * @param {OpenSeadragon.Rect} bounds + * @param {Object} options (immediately=null, constraints=false) + * @return {OpenSeadragon.Viewport} Chainable. + */ + function fitBounds( bounds, options ) { + var newOptions = options || {}; + var immediately = newOptions.immediately || null; + var constraints = newOptions.constraints || false; + + var aspect = that.getAspectRatio(), + center = bounds.getCenter(), + newBounds = new $.Rect( + bounds.x, + bounds.y, + bounds.width, + bounds.height + ), + oldBounds, + oldZoom, + newZoom, + referencePoint, + newBoundsAspectRatio, + newConstrainedZoom; + + if ( newBounds.getAspectRatio() >= aspect ) { + newBounds.height = bounds.width / aspect; + newBounds.y = center.y - newBounds.height / 2; + } else { + newBounds.width = bounds.height * aspect; + newBounds.x = center.x - newBounds.width / 2; + } + + if ( constraints ) { + newBoundsAspectRatio = newBounds.getAspectRatio(); + } + + that.panTo( that.getCenter( true ), true ); + that.zoomTo( that.getZoom( true ), null, true ); + + oldBounds = that.getBounds(); + oldZoom = that.getZoom(); + newZoom = 1.0 / newBounds.width; + + if ( constraints ) { + newConstrainedZoom = Math.max( + Math.min(newZoom, that.getMaxZoom() ), + that.getMinZoom() + ); + + if (newZoom !== newConstrainedZoom) { + newZoom = newConstrainedZoom; + newBounds.width = 1.0 / newZoom; + newBounds.x = center.x - newBounds.width / 2; + newBounds.height = newBounds.width / newBoundsAspectRatio; + newBounds.y = center.y - newBounds.height / 2; + } + + newBounds = applyBoundaryConstraints( newBounds, immediately ); + + if( that.viewer ){ + /** + * Raised when the viewport constraints are applied (see {@link OpenSeadragon.Viewport#applyConstraints}). + * + * @event constrain + * @memberof OpenSeadragon.Viewer + * @type {object} + * @property {OpenSeadragon.Viewer} eventSource - A reference to the Viewer which raised this event. + * @property {Boolean} immediately + * @property {?Object} userData - Arbitrary subscriber-defined object. + */ + that.viewer.raiseEvent( 'constrain', { + immediately: immediately + }); + } + } + + if ( newZoom == oldZoom || newBounds.width == oldBounds.width ) { + return that.panTo( constraints ? newBounds.getCenter() : center, immediately ); + } + + referencePoint = oldBounds.getTopLeft().times( + that.containerSize.x / oldBounds.width + ).minus( + newBounds.getTopLeft().times( + that.containerSize.x / newBounds.width + ) + ).divide( + that.containerSize.x / oldBounds.width - + that.containerSize.x / newBounds.width + ); + + return that.zoomTo( newZoom, referencePoint, immediately ); + } + + /** + * @function + * @param {OpenSeadragon.Rect} bounds + * @param {Boolean} immediately + * @return {OpenSeadragon.Viewport} Chainable. + */ + this.fitBounds = function( bounds, immediately ) { + return fitBounds( bounds, { + immediately: immediately, + constraints: false + } ); + }; + + /** + * @function + * @param {OpenSeadragon.Rect} bounds + * @param {Boolean} immediately + * @return {OpenSeadragon.Viewport} Chainable. + */ + this.fitBoundsWithConstraints = function( bounds, immediately ) { + return fitBounds( bounds, { + immediately: immediately, + constraints: true + } ); + }; + /** + * @function + * @param {OpenSeadragon.Rect} bounds + * @param {Boolean} immediately + * @return {OpenSeadragon.Rect} constrained bounds. + */ + function applyBoundaryConstraints( bounds, immediately ) { + var horizontalThreshold, + verticalThreshold, + left, + right, + top, + bottom, + dx = 0, + dy = 0, + newBounds = new $.Rect( + bounds.x, + bounds.y, + bounds.width, + bounds.height + ); + + horizontalThreshold = that.visibilityRatio * newBounds.width; + verticalThreshold = that.visibilityRatio * newBounds.height; + + left = newBounds.x + newBounds.width; + right = 1 - newBounds.x; + top = newBounds.y + newBounds.height; + bottom = that.contentAspectY - newBounds.y; + + if ( that.wrapHorizontal ) { + //do nothing + } else { + if ( left < horizontalThreshold ) { + dx = horizontalThreshold - left; + } + if ( right < horizontalThreshold ) { + dx = dx ? + ( dx + right - horizontalThreshold ) / 2 : + ( right - horizontalThreshold ); + } + } + + if ( that.wrapVertical ) { + //do nothing + } else { + if ( top < verticalThreshold ) { + dy = ( verticalThreshold - top ); + } + if ( bottom < verticalThreshold ) { + dy = dy ? + ( dy + bottom - verticalThreshold ) / 2 : + ( bottom - verticalThreshold ); + } + } + + if ( dx || dy || immediately ) { + newBounds.x += dx; + newBounds.y += dy; + if( newBounds.width > 1 ){ + newBounds.x = 0.5 - newBounds.width/2; + } + if( newBounds.height > that.contentAspectY ){ + newBounds.y = that.contentAspectY/2 - newBounds.height/2; + } + } + + return newBounds; + } + + /** + * @function + * @return {OpenSeadragon.Viewport} Chainable. + * @fires OpenSeadragon.Viewer.event:constrain + */ + this.applyConstraints = function( immediately ) { + var actualZoom = this.getZoom(), + constrainedZoom = Math.max( + Math.min( actualZoom, this.getMaxZoom() ), + this.getMinZoom() + ), + bounds, + constrainedBounds; + + if ( actualZoom != constrainedZoom ) { + this.zoomTo( constrainedZoom, this.zoomPoint, immediately ); + } + + bounds = this.getBounds(); + + constrainedBounds = applyBoundaryConstraints( bounds, immediately ); + + if ( bounds.x !== constrainedBounds.x || bounds.y !== constrainedBounds.y || immediately ){ + this.fitBounds( constrainedBounds, immediately ); + } + + if( this.viewer ){ + /** + * Raised when the viewport constraints are applied (see {@link OpenSeadragon.Viewport#applyConstraints}). + * + * @event constrain + * @memberof OpenSeadragon.Viewer + * @type {object} + * @property {OpenSeadragon.Viewer} eventSource - A reference to the Viewer which raised this event. + * @property {Boolean} immediately + * @property {?Object} userData - Arbitrary subscriber-defined object. + */ + this.viewer.raiseEvent( 'constrain', { + immediately: immediately + }); + } + + return this; + }; + this.centerSpringX = new $.Spring({ initial: 0, springStiffness: this.springStiffness, @@ -319,121 +557,6 @@ $.Viewport.prototype = /** @lends OpenSeadragon.Viewport.prototype */{ return this.zoomSpring.target.value; } }, - - /** - * @function - * @param {OpenSeadragon.Rect} bounds - * @param {Boolean} immediately - * @return {OpenSeadragon.Rect} constrained bounds. - */ - _applyBoundaryConstraints: function( bounds, immediately ) { - var horizontalThreshold, - verticalThreshold, - left, - right, - top, - bottom, - dx = 0, - dy = 0, - newBounds = new $.Rect( - bounds.x, - bounds.y, - bounds.width, - bounds.height - ); - - horizontalThreshold = this.visibilityRatio * newBounds.width; - verticalThreshold = this.visibilityRatio * newBounds.height; - - left = newBounds.x + newBounds.width; - right = 1 - newBounds.x; - top = newBounds.y + newBounds.height; - bottom = this.contentAspectY - newBounds.y; - - if ( this.wrapHorizontal ) { - //do nothing - } else { - if ( left < horizontalThreshold ) { - dx = horizontalThreshold - left; - } - if ( right < horizontalThreshold ) { - dx = dx ? - ( dx + right - horizontalThreshold ) / 2 : - ( right - horizontalThreshold ); - } - } - - if ( this.wrapVertical ) { - //do nothing - } else { - if ( top < verticalThreshold ) { - dy = ( verticalThreshold - top ); - } - if ( bottom < verticalThreshold ) { - dy = dy ? - ( dy + bottom - verticalThreshold ) / 2 : - ( bottom - verticalThreshold ); - } - } - - if ( dx || dy || immediately ) { - newBounds.x += dx; - newBounds.y += dy; - if( newBounds.width > 1 ){ - newBounds.x = 0.5 - newBounds.width/2; - } - if( newBounds.height > this.contentAspectY ){ - newBounds.y = this.contentAspectY/2 - newBounds.height/2; - } - } - - return newBounds; - }, - - /** - * @function - * @return {OpenSeadragon.Viewport} Chainable. - * @fires OpenSeadragon.Viewer.event:constrain - */ - applyConstraints: function( immediately ) { - var actualZoom = this.getZoom(), - constrainedZoom = Math.max( - Math.min( actualZoom, this.getMaxZoom() ), - this.getMinZoom() - ), - bounds, - constrainedBounds; - - if ( actualZoom != constrainedZoom ) { - this.zoomTo( constrainedZoom, this.zoomPoint, immediately ); - } - - bounds = this.getBounds(); - - constrainedBounds = this._applyBoundaryConstraints( bounds, immediately ); - - if ( bounds.x !== constrainedBounds.x || bounds.y !== constrainedBounds.y || immediately ){ - this.fitBounds( constrainedBounds, immediately ); - } - - if( this.viewer ){ - /** - * Raised when the viewport constraints are applied (see {@link OpenSeadragon.Viewport#applyConstraints}). - * - * @event constrain - * @memberof OpenSeadragon.Viewer - * @type {object} - * @property {OpenSeadragon.Viewer} eventSource - A reference to the Viewer which raised this event. - * @property {Boolean} immediately - * @property {?Object} userData - Arbitrary subscriber-defined object. - */ - this.viewer.raiseEvent( 'constrain', { - immediately: immediately - }); - } - - return this; - }, /** * @function @@ -443,128 +566,6 @@ $.Viewport.prototype = /** @lends OpenSeadragon.Viewport.prototype */{ return this.applyConstraints( immediately ); }, - /** - * @function - * @param {OpenSeadragon.Rect} bounds - * @param {Object} options (immediately=null, constraints=false) - * @return {OpenSeadragon.Viewport} Chainable. - */ - _fitBounds: function( bounds, options ) { - var newOptions = options || {}; - var immediately = newOptions.immediately || null; - var constraints = newOptions.constraints || false; - - var aspect = this.getAspectRatio(), - center = bounds.getCenter(), - newBounds = new $.Rect( - bounds.x, - bounds.y, - bounds.width, - bounds.height - ), - oldBounds, - oldZoom, - newZoom, - referencePoint, - newBoundsAspectRatio, - newConstrainedZoom; - - if ( newBounds.getAspectRatio() >= aspect ) { - newBounds.height = bounds.width / aspect; - newBounds.y = center.y - newBounds.height / 2; - } else { - newBounds.width = bounds.height * aspect; - newBounds.x = center.x - newBounds.width / 2; - } - - if ( constraints ) { - newBoundsAspectRatio = newBounds.getAspectRatio(); - } - - this.panTo( this.getCenter( true ), true ); - this.zoomTo( this.getZoom( true ), null, true ); - - oldBounds = this.getBounds(); - oldZoom = this.getZoom(); - newZoom = 1.0 / newBounds.width; - - if ( constraints ) { - newConstrainedZoom = Math.max( - Math.min(newZoom, this.getMaxZoom() ), - this.getMinZoom() - ); - - if (newZoom !== newConstrainedZoom) { - newZoom = newConstrainedZoom; - newBounds.width = 1.0 / newZoom; - newBounds.x = center.x - newBounds.width / 2; - newBounds.height = newBounds.width / newBoundsAspectRatio; - newBounds.y = center.y - newBounds.height / 2; - } - - newBounds = this._applyBoundaryConstraints( newBounds, immediately ); - - if( this.viewer ){ - /** - * Raised when the viewport constraints are applied (see {@link OpenSeadragon.Viewport#applyConstraints}). - * - * @event constrain - * @memberof OpenSeadragon.Viewer - * @type {object} - * @property {OpenSeadragon.Viewer} eventSource - A reference to the Viewer which raised this event. - * @property {Boolean} immediately - * @property {?Object} userData - Arbitrary subscriber-defined object. - */ - this.viewer.raiseEvent( 'constrain', { - immediately: immediately - }); - } - } - - if ( newZoom == oldZoom || newBounds.width == oldBounds.width ) { - return this.panTo( constraints ? newBounds.getCenter() : center, immediately ); - } - - referencePoint = oldBounds.getTopLeft().times( - this.containerSize.x / oldBounds.width - ).minus( - newBounds.getTopLeft().times( - this.containerSize.x / newBounds.width - ) - ).divide( - this.containerSize.x / oldBounds.width - - this.containerSize.x / newBounds.width - ); - - return this.zoomTo( newZoom, referencePoint, immediately ); - }, - - /** - * @function - * @param {OpenSeadragon.Rect} bounds - * @param {Boolean} immediately - * @return {OpenSeadragon.Viewport} Chainable. - */ - fitBounds: function( bounds, immediately ) { - return this._fitBounds( bounds, { - immediately: immediately, - constraints: false - } ); - }, - - /** - * @function - * @param {OpenSeadragon.Rect} bounds - * @param {Boolean} immediately - * @return {OpenSeadragon.Viewport} Chainable. - */ - fitBoundsWithConstraints: function( bounds, immediately ) { - return this._fitBounds( bounds, { - immediately: immediately, - constraints: true - } ); - }, - /** * @function * @param {Boolean} immediately From 9e6c46d4846b41e51f0769f4bd59477af183d880 Mon Sep 17 00:00:00 2001 From: Henri Astre Date: Mon, 23 Jun 2014 15:40:36 -0700 Subject: [PATCH 15/27] Revert "hiding properly _ functions." This reverts commit 118c2b2c8735e277a0876f0f38fd683e78aa47e9. --- src/viewport.js | 477 ++++++++++++++++++++++++------------------------ 1 file changed, 238 insertions(+), 239 deletions(-) diff --git a/src/viewport.js b/src/viewport.js index 6f5ee841..ddc26f0e 100644 --- a/src/viewport.js +++ b/src/viewport.js @@ -46,8 +46,7 @@ $.Viewport = function( options ) { //backward compatibility for positional args while prefering more //idiomatic javascript options object as the only argument - var args = arguments, - that = this; + var args = arguments; if( args.length && args[ 0 ] instanceof $.Point ){ options = { containerSize: args[ 0 ], @@ -88,244 +87,7 @@ $.Viewport = function( options ) { degrees: $.DEFAULT_SETTINGS.degrees }, options ); - - /** - * @function - * @param {OpenSeadragon.Rect} bounds - * @param {Object} options (immediately=null, constraints=false) - * @return {OpenSeadragon.Viewport} Chainable. - */ - function fitBounds( bounds, options ) { - var newOptions = options || {}; - var immediately = newOptions.immediately || null; - var constraints = newOptions.constraints || false; - - var aspect = that.getAspectRatio(), - center = bounds.getCenter(), - newBounds = new $.Rect( - bounds.x, - bounds.y, - bounds.width, - bounds.height - ), - oldBounds, - oldZoom, - newZoom, - referencePoint, - newBoundsAspectRatio, - newConstrainedZoom; - - if ( newBounds.getAspectRatio() >= aspect ) { - newBounds.height = bounds.width / aspect; - newBounds.y = center.y - newBounds.height / 2; - } else { - newBounds.width = bounds.height * aspect; - newBounds.x = center.x - newBounds.width / 2; - } - - if ( constraints ) { - newBoundsAspectRatio = newBounds.getAspectRatio(); - } - - that.panTo( that.getCenter( true ), true ); - that.zoomTo( that.getZoom( true ), null, true ); - - oldBounds = that.getBounds(); - oldZoom = that.getZoom(); - newZoom = 1.0 / newBounds.width; - - if ( constraints ) { - newConstrainedZoom = Math.max( - Math.min(newZoom, that.getMaxZoom() ), - that.getMinZoom() - ); - - if (newZoom !== newConstrainedZoom) { - newZoom = newConstrainedZoom; - newBounds.width = 1.0 / newZoom; - newBounds.x = center.x - newBounds.width / 2; - newBounds.height = newBounds.width / newBoundsAspectRatio; - newBounds.y = center.y - newBounds.height / 2; - } - - newBounds = applyBoundaryConstraints( newBounds, immediately ); - - if( that.viewer ){ - /** - * Raised when the viewport constraints are applied (see {@link OpenSeadragon.Viewport#applyConstraints}). - * - * @event constrain - * @memberof OpenSeadragon.Viewer - * @type {object} - * @property {OpenSeadragon.Viewer} eventSource - A reference to the Viewer which raised this event. - * @property {Boolean} immediately - * @property {?Object} userData - Arbitrary subscriber-defined object. - */ - that.viewer.raiseEvent( 'constrain', { - immediately: immediately - }); - } - } - - if ( newZoom == oldZoom || newBounds.width == oldBounds.width ) { - return that.panTo( constraints ? newBounds.getCenter() : center, immediately ); - } - - referencePoint = oldBounds.getTopLeft().times( - that.containerSize.x / oldBounds.width - ).minus( - newBounds.getTopLeft().times( - that.containerSize.x / newBounds.width - ) - ).divide( - that.containerSize.x / oldBounds.width - - that.containerSize.x / newBounds.width - ); - - return that.zoomTo( newZoom, referencePoint, immediately ); - } - - /** - * @function - * @param {OpenSeadragon.Rect} bounds - * @param {Boolean} immediately - * @return {OpenSeadragon.Viewport} Chainable. - */ - this.fitBounds = function( bounds, immediately ) { - return fitBounds( bounds, { - immediately: immediately, - constraints: false - } ); - }; - - /** - * @function - * @param {OpenSeadragon.Rect} bounds - * @param {Boolean} immediately - * @return {OpenSeadragon.Viewport} Chainable. - */ - this.fitBoundsWithConstraints = function( bounds, immediately ) { - return fitBounds( bounds, { - immediately: immediately, - constraints: true - } ); - }; - /** - * @function - * @param {OpenSeadragon.Rect} bounds - * @param {Boolean} immediately - * @return {OpenSeadragon.Rect} constrained bounds. - */ - function applyBoundaryConstraints( bounds, immediately ) { - var horizontalThreshold, - verticalThreshold, - left, - right, - top, - bottom, - dx = 0, - dy = 0, - newBounds = new $.Rect( - bounds.x, - bounds.y, - bounds.width, - bounds.height - ); - - horizontalThreshold = that.visibilityRatio * newBounds.width; - verticalThreshold = that.visibilityRatio * newBounds.height; - - left = newBounds.x + newBounds.width; - right = 1 - newBounds.x; - top = newBounds.y + newBounds.height; - bottom = that.contentAspectY - newBounds.y; - - if ( that.wrapHorizontal ) { - //do nothing - } else { - if ( left < horizontalThreshold ) { - dx = horizontalThreshold - left; - } - if ( right < horizontalThreshold ) { - dx = dx ? - ( dx + right - horizontalThreshold ) / 2 : - ( right - horizontalThreshold ); - } - } - - if ( that.wrapVertical ) { - //do nothing - } else { - if ( top < verticalThreshold ) { - dy = ( verticalThreshold - top ); - } - if ( bottom < verticalThreshold ) { - dy = dy ? - ( dy + bottom - verticalThreshold ) / 2 : - ( bottom - verticalThreshold ); - } - } - - if ( dx || dy || immediately ) { - newBounds.x += dx; - newBounds.y += dy; - if( newBounds.width > 1 ){ - newBounds.x = 0.5 - newBounds.width/2; - } - if( newBounds.height > that.contentAspectY ){ - newBounds.y = that.contentAspectY/2 - newBounds.height/2; - } - } - - return newBounds; - } - - /** - * @function - * @return {OpenSeadragon.Viewport} Chainable. - * @fires OpenSeadragon.Viewer.event:constrain - */ - this.applyConstraints = function( immediately ) { - var actualZoom = this.getZoom(), - constrainedZoom = Math.max( - Math.min( actualZoom, this.getMaxZoom() ), - this.getMinZoom() - ), - bounds, - constrainedBounds; - - if ( actualZoom != constrainedZoom ) { - this.zoomTo( constrainedZoom, this.zoomPoint, immediately ); - } - - bounds = this.getBounds(); - - constrainedBounds = applyBoundaryConstraints( bounds, immediately ); - - if ( bounds.x !== constrainedBounds.x || bounds.y !== constrainedBounds.y || immediately ){ - this.fitBounds( constrainedBounds, immediately ); - } - - if( this.viewer ){ - /** - * Raised when the viewport constraints are applied (see {@link OpenSeadragon.Viewport#applyConstraints}). - * - * @event constrain - * @memberof OpenSeadragon.Viewer - * @type {object} - * @property {OpenSeadragon.Viewer} eventSource - A reference to the Viewer which raised this event. - * @property {Boolean} immediately - * @property {?Object} userData - Arbitrary subscriber-defined object. - */ - this.viewer.raiseEvent( 'constrain', { - immediately: immediately - }); - } - - return this; - }; - this.centerSpringX = new $.Spring({ initial: 0, springStiffness: this.springStiffness, @@ -557,6 +319,121 @@ $.Viewport.prototype = /** @lends OpenSeadragon.Viewport.prototype */{ return this.zoomSpring.target.value; } }, + + /** + * @function + * @param {OpenSeadragon.Rect} bounds + * @param {Boolean} immediately + * @return {OpenSeadragon.Rect} constrained bounds. + */ + _applyBoundaryConstraints: function( bounds, immediately ) { + var horizontalThreshold, + verticalThreshold, + left, + right, + top, + bottom, + dx = 0, + dy = 0, + newBounds = new $.Rect( + bounds.x, + bounds.y, + bounds.width, + bounds.height + ); + + horizontalThreshold = this.visibilityRatio * newBounds.width; + verticalThreshold = this.visibilityRatio * newBounds.height; + + left = newBounds.x + newBounds.width; + right = 1 - newBounds.x; + top = newBounds.y + newBounds.height; + bottom = this.contentAspectY - newBounds.y; + + if ( this.wrapHorizontal ) { + //do nothing + } else { + if ( left < horizontalThreshold ) { + dx = horizontalThreshold - left; + } + if ( right < horizontalThreshold ) { + dx = dx ? + ( dx + right - horizontalThreshold ) / 2 : + ( right - horizontalThreshold ); + } + } + + if ( this.wrapVertical ) { + //do nothing + } else { + if ( top < verticalThreshold ) { + dy = ( verticalThreshold - top ); + } + if ( bottom < verticalThreshold ) { + dy = dy ? + ( dy + bottom - verticalThreshold ) / 2 : + ( bottom - verticalThreshold ); + } + } + + if ( dx || dy || immediately ) { + newBounds.x += dx; + newBounds.y += dy; + if( newBounds.width > 1 ){ + newBounds.x = 0.5 - newBounds.width/2; + } + if( newBounds.height > this.contentAspectY ){ + newBounds.y = this.contentAspectY/2 - newBounds.height/2; + } + } + + return newBounds; + }, + + /** + * @function + * @return {OpenSeadragon.Viewport} Chainable. + * @fires OpenSeadragon.Viewer.event:constrain + */ + applyConstraints: function( immediately ) { + var actualZoom = this.getZoom(), + constrainedZoom = Math.max( + Math.min( actualZoom, this.getMaxZoom() ), + this.getMinZoom() + ), + bounds, + constrainedBounds; + + if ( actualZoom != constrainedZoom ) { + this.zoomTo( constrainedZoom, this.zoomPoint, immediately ); + } + + bounds = this.getBounds(); + + constrainedBounds = this._applyBoundaryConstraints( bounds, immediately ); + + if ( bounds.x !== constrainedBounds.x || bounds.y !== constrainedBounds.y || immediately ){ + this.fitBounds( constrainedBounds, immediately ); + } + + if( this.viewer ){ + /** + * Raised when the viewport constraints are applied (see {@link OpenSeadragon.Viewport#applyConstraints}). + * + * @event constrain + * @memberof OpenSeadragon.Viewer + * @type {object} + * @property {OpenSeadragon.Viewer} eventSource - A reference to the Viewer which raised this event. + * @property {Boolean} immediately + * @property {?Object} userData - Arbitrary subscriber-defined object. + */ + this.viewer.raiseEvent( 'constrain', { + immediately: immediately + }); + } + + return this; + }, /** * @function @@ -566,6 +443,128 @@ $.Viewport.prototype = /** @lends OpenSeadragon.Viewport.prototype */{ return this.applyConstraints( immediately ); }, + /** + * @function + * @param {OpenSeadragon.Rect} bounds + * @param {Object} options (immediately=null, constraints=false) + * @return {OpenSeadragon.Viewport} Chainable. + */ + _fitBounds: function( bounds, options ) { + var newOptions = options || {}; + var immediately = newOptions.immediately || null; + var constraints = newOptions.constraints || false; + + var aspect = this.getAspectRatio(), + center = bounds.getCenter(), + newBounds = new $.Rect( + bounds.x, + bounds.y, + bounds.width, + bounds.height + ), + oldBounds, + oldZoom, + newZoom, + referencePoint, + newBoundsAspectRatio, + newConstrainedZoom; + + if ( newBounds.getAspectRatio() >= aspect ) { + newBounds.height = bounds.width / aspect; + newBounds.y = center.y - newBounds.height / 2; + } else { + newBounds.width = bounds.height * aspect; + newBounds.x = center.x - newBounds.width / 2; + } + + if ( constraints ) { + newBoundsAspectRatio = newBounds.getAspectRatio(); + } + + this.panTo( this.getCenter( true ), true ); + this.zoomTo( this.getZoom( true ), null, true ); + + oldBounds = this.getBounds(); + oldZoom = this.getZoom(); + newZoom = 1.0 / newBounds.width; + + if ( constraints ) { + newConstrainedZoom = Math.max( + Math.min(newZoom, this.getMaxZoom() ), + this.getMinZoom() + ); + + if (newZoom !== newConstrainedZoom) { + newZoom = newConstrainedZoom; + newBounds.width = 1.0 / newZoom; + newBounds.x = center.x - newBounds.width / 2; + newBounds.height = newBounds.width / newBoundsAspectRatio; + newBounds.y = center.y - newBounds.height / 2; + } + + newBounds = this._applyBoundaryConstraints( newBounds, immediately ); + + if( this.viewer ){ + /** + * Raised when the viewport constraints are applied (see {@link OpenSeadragon.Viewport#applyConstraints}). + * + * @event constrain + * @memberof OpenSeadragon.Viewer + * @type {object} + * @property {OpenSeadragon.Viewer} eventSource - A reference to the Viewer which raised this event. + * @property {Boolean} immediately + * @property {?Object} userData - Arbitrary subscriber-defined object. + */ + this.viewer.raiseEvent( 'constrain', { + immediately: immediately + }); + } + } + + if ( newZoom == oldZoom || newBounds.width == oldBounds.width ) { + return this.panTo( constraints ? newBounds.getCenter() : center, immediately ); + } + + referencePoint = oldBounds.getTopLeft().times( + this.containerSize.x / oldBounds.width + ).minus( + newBounds.getTopLeft().times( + this.containerSize.x / newBounds.width + ) + ).divide( + this.containerSize.x / oldBounds.width - + this.containerSize.x / newBounds.width + ); + + return this.zoomTo( newZoom, referencePoint, immediately ); + }, + + /** + * @function + * @param {OpenSeadragon.Rect} bounds + * @param {Boolean} immediately + * @return {OpenSeadragon.Viewport} Chainable. + */ + fitBounds: function( bounds, immediately ) { + return this._fitBounds( bounds, { + immediately: immediately, + constraints: false + } ); + }, + + /** + * @function + * @param {OpenSeadragon.Rect} bounds + * @param {Boolean} immediately + * @return {OpenSeadragon.Viewport} Chainable. + */ + fitBoundsWithConstraints: function( bounds, immediately ) { + return this._fitBounds( bounds, { + immediately: immediately, + constraints: true + } ); + }, + /** * @function * @param {Boolean} immediately From 318071d3cebfcbe5ff9cdc8d37cb28c30344c812 Mon Sep 17 00:00:00 2001 From: Henri Astre Date: Mon, 23 Jun 2014 16:10:01 -0700 Subject: [PATCH 16/27] Cleanup for PR comments - raise 'constrain' event inside applyBoundaryConstraints - fix demo title/filename - various fixes (default immediately to false + add private for documentation) --- src/viewport.js | 60 +++++++++++++++------------------------- test/demo/fitBounds.html | 2 +- 2 files changed, 24 insertions(+), 38 deletions(-) diff --git a/src/viewport.js b/src/viewport.js index ddc26f0e..7bceb9d8 100644 --- a/src/viewport.js +++ b/src/viewport.js @@ -322,6 +322,7 @@ $.Viewport.prototype = /** @lends OpenSeadragon.Viewport.prototype */{ /** * @function + * @private * @param {OpenSeadragon.Rect} bounds * @param {Boolean} immediately * @return {OpenSeadragon.Rect} constrained bounds. @@ -387,6 +388,22 @@ $.Viewport.prototype = /** @lends OpenSeadragon.Viewport.prototype */{ } } + if( this.viewer ){ + /** + * Raised when the viewport constraints are applied (see {@link OpenSeadragon.Viewport#applyConstraints}). + * + * @event constrain + * @memberof OpenSeadragon.Viewer + * @type {object} + * @property {OpenSeadragon.Viewer} eventSource - A reference to the Viewer which raised this event. + * @property {Boolean} immediately + * @property {?Object} userData - Arbitrary subscriber-defined object. + */ + this.viewer.raiseEvent( 'constrain', { + immediately: immediately + }); + } + return newBounds; }, @@ -415,23 +432,7 @@ $.Viewport.prototype = /** @lends OpenSeadragon.Viewport.prototype */{ if ( bounds.x !== constrainedBounds.x || bounds.y !== constrainedBounds.y || immediately ){ this.fitBounds( constrainedBounds, immediately ); } - - if( this.viewer ){ - /** - * Raised when the viewport constraints are applied (see {@link OpenSeadragon.Viewport#applyConstraints}). - * - * @event constrain - * @memberof OpenSeadragon.Viewer - * @type {object} - * @property {OpenSeadragon.Viewer} eventSource - A reference to the Viewer which raised this event. - * @property {Boolean} immediately - * @property {?Object} userData - Arbitrary subscriber-defined object. - */ - this.viewer.raiseEvent( 'constrain', { - immediately: immediately - }); - } - + return this; }, @@ -445,14 +446,15 @@ $.Viewport.prototype = /** @lends OpenSeadragon.Viewport.prototype */{ /** * @function + * @private * @param {OpenSeadragon.Rect} bounds - * @param {Object} options (immediately=null, constraints=false) + * @param {Object} options (immediately=false, constraints=false) * @return {OpenSeadragon.Viewport} Chainable. */ _fitBounds: function( bounds, options ) { - var newOptions = options || {}; - var immediately = newOptions.immediately || null; - var constraints = newOptions.constraints || false; + options = options || {}; + var immediately = options.immediately || false; + var constraints = options.constraints || false; var aspect = this.getAspectRatio(), center = bounds.getCenter(), @@ -503,22 +505,6 @@ $.Viewport.prototype = /** @lends OpenSeadragon.Viewport.prototype */{ } newBounds = this._applyBoundaryConstraints( newBounds, immediately ); - - if( this.viewer ){ - /** - * Raised when the viewport constraints are applied (see {@link OpenSeadragon.Viewport#applyConstraints}). - * - * @event constrain - * @memberof OpenSeadragon.Viewer - * @type {object} - * @property {OpenSeadragon.Viewer} eventSource - A reference to the Viewer which raised this event. - * @property {Boolean} immediately - * @property {?Object} userData - Arbitrary subscriber-defined object. - */ - this.viewer.raiseEvent( 'constrain', { - immediately: immediately - }); - } } if ( newZoom == oldZoom || newBounds.width == oldBounds.width ) { diff --git a/test/demo/fitBounds.html b/test/demo/fitBounds.html index 60651bed..c0317c98 100644 --- a/test/demo/fitBounds.html +++ b/test/demo/fitBounds.html @@ -1,7 +1,7 @@ - OpenSeadragon Memory Check Demo + OpenSeadragon fitBoundsWithConstraints() Demo