From 5542ead48b5a5daf64839af384a5656a0ac0fa7b Mon Sep 17 00:00:00 2001 From: Lutz Helm Date: Tue, 19 Sep 2023 09:55:53 +0200 Subject: [PATCH 1/8] Fix #2415, order IIIF sizes on tile source init --- src/iiiftilesource.js | 3 +++ test/modules/iiif.js | 20 ++++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/src/iiiftilesource.js b/src/iiiftilesource.js index 6db4e321..1105ea51 100644 --- a/src/iiiftilesource.js +++ b/src/iiiftilesource.js @@ -269,6 +269,9 @@ $.extend( $.IIIFTileSource.prototype, $.TileSource.prototype, /** @lends OpenSea } } } + data.sizes = data.sizes && data.sizes.sort( + ( size1, size2 ) => size1.width - size2.width + ); return data; } }, diff --git a/test/modules/iiif.js b/test/modules/iiif.js index cc5035b7..b230150a 100644 --- a/test/modules/iiif.js +++ b/test/modules/iiif.js @@ -141,6 +141,21 @@ "width": 2000, "height": 1000, "profile": "level1" + }, + infoJson3DescendingSizeOrder = { + "@context": "http://iiif.io/api/image/3/context.json", + "id": id, + "width": 2000, + "height": 1000, + "tiles": [ + { "width": 512, "scaleFactors": [ 1, 2, 4 ] } + ], + "sizes": [ + { width: 2000, height: 1000 }, + { width: 1000, height: 500 }, + { width: 500, height: 250 } + ], + "profile": "level1", }; QUnit.module('IIIF'); @@ -246,6 +261,11 @@ assert.equal(source3Level1.getTileUrl(8, 3, 0), "http://example.com/identifier/1536,0,464,512/464,512/0/default.jpg"); assert.equal(source3Level1.getTileUrl(8, 0, 1), "http://example.com/identifier/0,512,512,488/512,488/0/default.jpg"); assert.equal(source3Level1.getTileUrl(8, 3, 1), "http://example.com/identifier/1536,512,464,488/464,488/0/default.jpg"); + + var source3DescendingSizeOrder = getSource(infoJson3DescendingSizeOrder); + assert.equal(source3DescendingSizeOrder.getTileUrl(0, 0, 0), "http://example.com/identifier/full/500,250/0/default.jpg"); + assert.equal(source3DescendingSizeOrder.getTileUrl(1, 1, 0), "http://example.com/identifier/1024,0,976,1000/488,500/0/default.jpg"); + assert.equal(source3DescendingSizeOrder.getTileUrl(2, 0, 0), "http://example.com/identifier/0,0,512,512/512,512/0/default.jpg"); }); })(); From b92a428e88730546058bf9890aa44061ca370eb5 Mon Sep 17 00:00:00 2001 From: Lutz Helm Date: Tue, 10 Oct 2023 14:02:44 +0200 Subject: [PATCH 2/8] Sort levelSizes instead of sizes --- src/iiiftilesource.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/iiiftilesource.js b/src/iiiftilesource.js index 1105ea51..54ec073f 100644 --- a/src/iiiftilesource.js +++ b/src/iiiftilesource.js @@ -145,7 +145,7 @@ $.IIIFTileSource = function( options ){ if( this.sizes ) { var sizeLength = this.sizes.length; if ( (sizeLength === options.maxLevel) || (sizeLength === options.maxLevel + 1) ) { - this.levelSizes = this.sizes; + this.levelSizes = this.sizes.slice().sort(( size1, size2 ) => size1.width - size2.width); // Need to take into account that the list may or may not include the full resolution size if( sizeLength === options.maxLevel ) { this.levelSizes.push( {width: this.width, height: this.height} ); @@ -269,9 +269,6 @@ $.extend( $.IIIFTileSource.prototype, $.TileSource.prototype, /** @lends OpenSea } } } - data.sizes = data.sizes && data.sizes.sort( - ( size1, size2 ) => size1.width - size2.width - ); return data; } }, From 5272cf092cc2bc3a9d875935a6f0caa44941328e Mon Sep 17 00:00:00 2001 From: Lutz Helm Date: Tue, 10 Oct 2023 14:04:31 +0200 Subject: [PATCH 3/8] Ensure descending size order also works for level 0 --- test/modules/iiif.js | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/test/modules/iiif.js b/test/modules/iiif.js index b230150a..e64e34a9 100644 --- a/test/modules/iiif.js +++ b/test/modules/iiif.js @@ -107,6 +107,21 @@ ], "profile": "level0" }, + infoJson3level0WithTiles = { + "@context": "http://iiif.io/api/image/3/context.json", + "id": id, + "width": 2000, + "height": 1000, + "tiles": [ + { "width": 256, "scaleFactors": [ 2, 4, 1 ] } + ], + "sizes": [ + { width: 2000, height: 1000 }, + { width: 1000, height: 500 }, + { width: 500, height: 250 } + ], + "profile": "level0" + }, infoJson3level0ContextExtension = { "@context": [ "http://iiif.io/api/image/3/context.json", @@ -253,6 +268,11 @@ assert.equal(source2Level0.getTileUrl(0, 0, 0), "http://example.com/identifier/full/1000,/0/default.jpg"); assert.equal(source2Level0.getTileUrl(1, 0, 0), "http://example.com/identifier/full/2000,/0/default.jpg"); + var source3Level0WithTiles = getSource(infoJson3level0WithTiles); + assert.equal(source3Level0WithTiles.getTileUrl(0, 0, 0), "http://example.com/identifier/0,0,1024,1000/256,250/0/default.jpg"); + assert.equal(source3Level0WithTiles.getTileUrl(1, 1, 0), "http://example.com/identifier/512,0,512,512/256,256/0/default.jpg"); + assert.equal(source3Level0WithTiles.getTileUrl(2, 0, 0), "http://example.com/identifier/0,0,256,256/256,256/0/default.jpg"); + var source3Level1 = getSource(infoJson3level1); assert.equal(source3Level1.getTileUrl(0, 0, 0), "http://example.com/identifier/full/8,4/0/default.jpg"); assert.equal(source3Level1.getTileUrl(7, 0, 0), "http://example.com/identifier/0,0,1024,1000/512,500/0/default.jpg"); From 810987210c069876d2ba98a603086affc3244710 Mon Sep 17 00:00:00 2001 From: Christophe Avenel Date: Wed, 25 Oct 2023 09:26:48 +0200 Subject: [PATCH 4/8] Fix zoom out when wheel event.deltaY is zero Don't apply zoom in or zoom out when deltaY is zero on wheel events. Should fix https://github.com/openseadragon/openseadragon/issues/947 and not make OpenSeadragon zoom out when scrolling horizontally on a touchpad --- src/mousetracker.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mousetracker.js b/src/mousetracker.js index 20200b31..57d89d5b 100644 --- a/src/mousetracker.js +++ b/src/mousetracker.js @@ -2070,7 +2070,7 @@ // y-index scrolling. // event.deltaMode: 0=pixel, 1=line, 2=page // TODO: Deltas in pixel mode should be accumulated then a scroll value computed after $.DEFAULT_SETTINGS.pixelsPerWheelLine threshold reached - nDelta = event.deltaY < 0 ? 1 : -1; + nDelta = event.deltaY ? (event.deltaY < 0 ? 1 : -1) : 0; eventInfo = { originalEvent: event, From e836ffcc61b50c5142c237f3a5522797929c1eaa Mon Sep 17 00:00:00 2001 From: Christophe Avenel Date: Tue, 31 Oct 2023 15:38:38 +0100 Subject: [PATCH 5/8] Add debounce of pan events Group pan events together if needed, in order to avoid lag if drawing of layers takes more time than it should. --- src/openseadragon.js | 4 ++++ src/viewer.js | 47 ++++++++++++++++++++++++++++++++++---------- 2 files changed, 41 insertions(+), 10 deletions(-) diff --git a/src/openseadragon.js b/src/openseadragon.js index 2cb2ac0d..746d1291 100644 --- a/src/openseadragon.js +++ b/src/openseadragon.js @@ -141,6 +141,9 @@ * DEPRECATED. A relative path to load a DZI file from the server. * Prefer the newer Options.tileSources. * + * @property {Boolean} [debouncePanEvents=false] + * Group multiple move events into one event. This is useful for debouncing. + * * @property {String} [prefixUrl='/images/'] * Prepends the prefixUrl to navImages paths, which is very useful * since the default paths are rarely useful for production @@ -1370,6 +1373,7 @@ function OpenSeadragon( options ){ useCanvas: true, // Use canvas element for drawing if available tileRetryMax: 0, tileRetryDelay: 2500, + debouncePanEvents: false, //INTERFACE RESOURCE SETTINGS prefixUrl: "/images/", diff --git a/src/viewer.js b/src/viewer.js index d82a2d77..f76f7524 100644 --- a/src/viewer.js +++ b/src/viewer.js @@ -3097,28 +3097,55 @@ function onCanvasDrag( event ) { * @property {?Object} userData - Arbitrary subscriber-defined object. */ this.raiseEvent( 'canvas-drag', canvasDragEventArgs); - - gestureSettings = this.gestureSettingsByDeviceType( event.pointerType ); + if (this.debouncePanEvents) { + if (!this.dragEventCombined) { + this.dragEventCombined = canvasDragEventArgs; + this.dragEventCombined.timeStamp = canvasDragEventArgs.originalEvent.timeStamp; + } + else { + this.dragEventCombined.delta = this.dragEventCombined.delta.plus(canvasDragEventArgs.delta); + } + if (this.dragEventCombined.timeout) { + clearTimeout(this.dragEventCombined.timeout); + this.dragEventCombined.timeout = null; + } + if (canvasDragEventArgs.originalEvent.timeStamp - this.dragEventCombined.timeStamp > this.debouncePanEvents) { + canvasDragEventArgs = this.dragEventCombined; + this.dragEventCombined = null; + } + else { + this.dragEventCombined.timeout = setTimeout(function () { + // call onCanvasDrag with en event with delta.x and delat.y = 0 + let newEvent = event; + newEvent.delta.x = 0; + newEvent.delta.y = 0; + this.dragEventCombined.timeStamp -= this.debouncePanEvents; + onCanvasDrag.call(this, newEvent); + }.bind(this), this.debouncePanEvents / 5); + return; + } + } + gestureSettings = this.gestureSettingsByDeviceType( canvasDragEventArgs.pointerType ); if(!canvasDragEventArgs.preventDefaultAction && this.viewport){ if (gestureSettings.dblClickDragToZoom && THIS[ this.hash ].draggingToZoom){ - var factor = Math.pow( this.zoomPerDblClickDrag, event.delta.y / 50); + var factor = Math.pow( this.zoomPerDblClickDrag, canvasDragEventArgs.delta.y / 50); this.viewport.zoomBy(factor); } else if (gestureSettings.dragToPan && !THIS[ this.hash ].draggingToZoom) { if( !this.panHorizontal ){ - event.delta.x = 0; + canvasDragEventArgs.delta.x = 0; } if( !this.panVertical ){ - event.delta.y = 0; + canvasDragEventArgs.delta.y = 0; } if(this.viewport.flipped){ - event.delta.x = -event.delta.x; + canvasDragEventArgs.delta.x = -canvasDragEventArgs.delta.x; } if( this.constrainDuringPan ){ - var delta = this.viewport.deltaPointsFromPixels( event.delta.negate() ); + var delta = this.viewport.deltaPointsFromPixels( canvasDragEventArgs.delta.negate() ); this.viewport.centerSpringX.target.value += delta.x; this.viewport.centerSpringY.target.value += delta.y; @@ -3129,14 +3156,14 @@ function onCanvasDrag( event ) { this.viewport.centerSpringY.target.value -= delta.y; if (constrainedBounds.xConstrained) { - event.delta.x = 0; + canvasDragEventArgs.delta.x = 0; } if (constrainedBounds.yConstrained) { - event.delta.y = 0; + canvasDragEventArgs.delta.y = 0; } } - this.viewport.panBy( this.viewport.deltaPointsFromPixels( event.delta.negate() ), gestureSettings.flickEnabled && !this.constrainDuringPan); + this.viewport.panBy( this.viewport.deltaPointsFromPixels( canvasDragEventArgs.delta.negate() ), gestureSettings.flickEnabled && !this.constrainDuringPan); } } From 89ae9c1376ebb86142283472bd4be8bcc102fd11 Mon Sep 17 00:00:00 2001 From: Ian Gilman Date: Mon, 6 Nov 2023 09:32:00 -0800 Subject: [PATCH 6/8] Changelog for #2416 --- changelog.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/changelog.txt b/changelog.txt index 863a5d4e..11619fc1 100644 --- a/changelog.txt +++ b/changelog.txt @@ -10,6 +10,7 @@ OPENSEADRAGON CHANGELOG * Test improvements (#2382 @AndrewADev) * MouseTracker options documentation fixes (#2389 @msalsbery) * Fixed: Sometimes if the viewport was flipped and the user zoomed in far enough, it would flip back (#2364 @SebDelile) +* Fixed: Strange behavior if IIIF sizes were not in ascending order (#2416 @lutzhelm) 4.1.0: From c1038af37d11ca2811aab4bf3869499ddfdc2e41 Mon Sep 17 00:00:00 2001 From: Christophe Avenel Date: Wed, 8 Nov 2023 18:52:05 +0100 Subject: [PATCH 7/8] Revert "Add debounce of pan events" This reverts commit e836ffcc61b50c5142c237f3a5522797929c1eaa. --- src/openseadragon.js | 4 ---- src/viewer.js | 47 ++++++++++---------------------------------- 2 files changed, 10 insertions(+), 41 deletions(-) diff --git a/src/openseadragon.js b/src/openseadragon.js index 746d1291..2cb2ac0d 100644 --- a/src/openseadragon.js +++ b/src/openseadragon.js @@ -141,9 +141,6 @@ * DEPRECATED. A relative path to load a DZI file from the server. * Prefer the newer Options.tileSources. * - * @property {Boolean} [debouncePanEvents=false] - * Group multiple move events into one event. This is useful for debouncing. - * * @property {String} [prefixUrl='/images/'] * Prepends the prefixUrl to navImages paths, which is very useful * since the default paths are rarely useful for production @@ -1373,7 +1370,6 @@ function OpenSeadragon( options ){ useCanvas: true, // Use canvas element for drawing if available tileRetryMax: 0, tileRetryDelay: 2500, - debouncePanEvents: false, //INTERFACE RESOURCE SETTINGS prefixUrl: "/images/", diff --git a/src/viewer.js b/src/viewer.js index f76f7524..d82a2d77 100644 --- a/src/viewer.js +++ b/src/viewer.js @@ -3097,55 +3097,28 @@ function onCanvasDrag( event ) { * @property {?Object} userData - Arbitrary subscriber-defined object. */ this.raiseEvent( 'canvas-drag', canvasDragEventArgs); - if (this.debouncePanEvents) { - if (!this.dragEventCombined) { - this.dragEventCombined = canvasDragEventArgs; - this.dragEventCombined.timeStamp = canvasDragEventArgs.originalEvent.timeStamp; - } - else { - this.dragEventCombined.delta = this.dragEventCombined.delta.plus(canvasDragEventArgs.delta); - } - if (this.dragEventCombined.timeout) { - clearTimeout(this.dragEventCombined.timeout); - this.dragEventCombined.timeout = null; - } - if (canvasDragEventArgs.originalEvent.timeStamp - this.dragEventCombined.timeStamp > this.debouncePanEvents) { - canvasDragEventArgs = this.dragEventCombined; - this.dragEventCombined = null; - } - else { - this.dragEventCombined.timeout = setTimeout(function () { - // call onCanvasDrag with en event with delta.x and delat.y = 0 - let newEvent = event; - newEvent.delta.x = 0; - newEvent.delta.y = 0; - this.dragEventCombined.timeStamp -= this.debouncePanEvents; - onCanvasDrag.call(this, newEvent); - }.bind(this), this.debouncePanEvents / 5); - return; - } - } - gestureSettings = this.gestureSettingsByDeviceType( canvasDragEventArgs.pointerType ); + + gestureSettings = this.gestureSettingsByDeviceType( event.pointerType ); if(!canvasDragEventArgs.preventDefaultAction && this.viewport){ if (gestureSettings.dblClickDragToZoom && THIS[ this.hash ].draggingToZoom){ - var factor = Math.pow( this.zoomPerDblClickDrag, canvasDragEventArgs.delta.y / 50); + var factor = Math.pow( this.zoomPerDblClickDrag, event.delta.y / 50); this.viewport.zoomBy(factor); } else if (gestureSettings.dragToPan && !THIS[ this.hash ].draggingToZoom) { if( !this.panHorizontal ){ - canvasDragEventArgs.delta.x = 0; + event.delta.x = 0; } if( !this.panVertical ){ - canvasDragEventArgs.delta.y = 0; + event.delta.y = 0; } if(this.viewport.flipped){ - canvasDragEventArgs.delta.x = -canvasDragEventArgs.delta.x; + event.delta.x = -event.delta.x; } if( this.constrainDuringPan ){ - var delta = this.viewport.deltaPointsFromPixels( canvasDragEventArgs.delta.negate() ); + var delta = this.viewport.deltaPointsFromPixels( event.delta.negate() ); this.viewport.centerSpringX.target.value += delta.x; this.viewport.centerSpringY.target.value += delta.y; @@ -3156,14 +3129,14 @@ function onCanvasDrag( event ) { this.viewport.centerSpringY.target.value -= delta.y; if (constrainedBounds.xConstrained) { - canvasDragEventArgs.delta.x = 0; + event.delta.x = 0; } if (constrainedBounds.yConstrained) { - canvasDragEventArgs.delta.y = 0; + event.delta.y = 0; } } - this.viewport.panBy( this.viewport.deltaPointsFromPixels( canvasDragEventArgs.delta.negate() ), gestureSettings.flickEnabled && !this.constrainDuringPan); + this.viewport.panBy( this.viewport.deltaPointsFromPixels( event.delta.negate() ), gestureSettings.flickEnabled && !this.constrainDuringPan); } } From 6abcc76a93ee3369267908f0a80641dc171440ed Mon Sep 17 00:00:00 2001 From: Ian Gilman Date: Mon, 13 Nov 2023 09:57:19 -0800 Subject: [PATCH 8/8] Changelog for #2431 --- changelog.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/changelog.txt b/changelog.txt index 11619fc1..b3b0ae36 100644 --- a/changelog.txt +++ b/changelog.txt @@ -11,6 +11,7 @@ OPENSEADRAGON CHANGELOG * MouseTracker options documentation fixes (#2389 @msalsbery) * Fixed: Sometimes if the viewport was flipped and the user zoomed in far enough, it would flip back (#2364 @SebDelile) * Fixed: Strange behavior if IIIF sizes were not in ascending order (#2416 @lutzhelm) +* Fixed: Two-finger tap on a Mac trackpad would zoom you out (#2431 @cavenel) 4.1.0: