From 19ade7d76d43ef991a11079c1c7bf9c29565dcef Mon Sep 17 00:00:00 2001 From: Ian Gilman Date: Wed, 11 Mar 2015 15:41:36 -0700 Subject: [PATCH] Improved zoom and pan constraints --- src/viewport.js | 4 +- test/demo/m2/js/main.js | 84 ++++++++++++++++++++++++++++++----------- test/demo/m2/js/page.js | 25 ++++++++++++ 3 files changed, 89 insertions(+), 24 deletions(-) diff --git a/src/viewport.js b/src/viewport.js index b6b57e27..ff91ad29 100644 --- a/src/viewport.js +++ b/src/viewport.js @@ -596,8 +596,8 @@ $.Viewport.prototype = /** @lends OpenSeadragon.Viewport.prototype */{ return this.zoomTo(newZoom, null, true); } - if (Math.abs(newZoom - oldZoom) < 0.00000000001 || - Math.abs(newBounds.width - oldBounds.width) < 0.00000000001) { + if (Math.abs(newZoom - oldZoom) < 0.00000001 || + Math.abs(newBounds.width - oldBounds.width) < 0.00000001) { return this.panTo( center, immediately ); } diff --git a/test/demo/m2/js/main.js b/test/demo/m2/js/main.js index 20c0cbf1..75337fdb 100644 --- a/test/demo/m2/js/main.js +++ b/test/demo/m2/js/main.js @@ -57,7 +57,11 @@ } }); - this.viewer.addHandler('viewport-change', function(event) { + this.viewer.addHandler('zoom', function(event) { + self.applyConstraints(); + }); + + this.viewer.addHandler('pan', function(event) { self.applyConstraints(); }); @@ -291,33 +295,69 @@ return; } - if (this.panBounds) { - var center = this.viewer.viewport.getCenter(true); - var viewBounds = this.viewer.viewport.getBounds(true); - var bounds = this.panBounds.clone(); - var left = bounds.x + (viewBounds.width / 2); - var top = bounds.y + (viewBounds.height / 2); - var right = (bounds.x + bounds.width) - (viewBounds.width / 2); - var bottom = (bounds.y + bounds.height) - (viewBounds.height / 2); + if (this.panBounds && !this.inZoomConstraints) { + var changed = false; + var viewBounds = this.viewer.viewport.getBounds(); + var panBounds = this.panBounds.clone(); - var x; - if (left <= right) { - x = Math.max(left, Math.min(right, center.x)); - } else { - x = bounds.x + (bounds.width / 2); + if (viewBounds.x < panBounds.x - 0.00001) { + viewBounds.x = panBounds.x; + changed = true; } - var y; - if (top <= bottom) { - y = Math.max(top, Math.min(bottom, center.y)); - } else { - y = bounds.y + (bounds.height / 2); + if (viewBounds.y < panBounds.y - 0.00001) { + viewBounds.y = panBounds.y; + changed = true; } - if (x !== center.x || y !== center.y) { - this.viewer.viewport.centerSpringX.current.value = x; - this.viewer.viewport.centerSpringY.current.value = y; + if (viewBounds.width > panBounds.width + 0.00001) { + viewBounds.width = panBounds.width; + changed = true; } + + if (viewBounds.height > panBounds.height + 0.00001) { + viewBounds.height = panBounds.height; + changed = true; + } + + if (viewBounds.x + viewBounds.width > panBounds.x + panBounds.width + 0.00001) { + viewBounds.x = (panBounds.x + panBounds.width) - viewBounds.width; + changed = true; + } + + if (viewBounds.y + viewBounds.height > panBounds.y + panBounds.height + 0.00001) { + viewBounds.y = (panBounds.y + panBounds.height) - viewBounds.height; + changed = true; + } + + if (changed) { + this.inZoomConstraints = true; + this.viewer.viewport.fitBounds(viewBounds); + this.inZoomConstraints = false; + } + } + + var zoom = this.viewer.viewport.getZoom(); + var maxZoom = 2; + + var zoomPoint = this.viewer.viewport.zoomPoint || this.viewer.viewport.getCenter(); + var info = this.hitTest(zoomPoint); + if (info) { + var page = this.pages[info.index]; + var tiledImage = page.hitTest(zoomPoint); + if (tiledImage) { + maxZoom = this.viewer.maxZoomLevel; + if (!maxZoom) { + var imageWidth = tiledImage.getContentSize().x; + var viewerWidth = this.$el.width(); + maxZoom = imageWidth * this.viewer.maxZoomPixelRatio / viewerWidth; + maxZoom /= tiledImage.getBounds().width; + } + } + } + + if (zoom > maxZoom) { + this.viewer.viewport.zoomSpring.target.value = maxZoom; } }, diff --git a/test/demo/m2/js/page.js b/test/demo/m2/js/page.js index a8654fd0..736cb2f1 100644 --- a/test/demo/m2/js/page.js +++ b/test/demo/m2/js/page.js @@ -105,6 +105,31 @@ }); }, + // ---------- + hitTest: function(pos) { + if (!this.details) { + return this.main.tiledImage; + } + + var count = this.details.length; + var detail, box; + + for (var i = 0; i < count; i++) { + detail = this.details[i]; + if (!detail.tiledImage) { + continue; + } + + box = detail.tiledImage.getBounds(); + if (pos.x > box.x && pos.y > box.y && pos.x < box.x + box.width && + pos.y < box.y + box.height) { + return detail.tiledImage; + } + } + + return this.main.tiledImage; + }, + // ---------- getBounds: function() { return this.bounds.clone();