mirror of
https://github.com/openseadragon/openseadragon.git
synced 2024-11-21 20:56:09 +03:00
Merge branch 'master' into rotation-seams
This commit is contained in:
commit
36d8b3d9ad
@ -165,8 +165,11 @@ module.exports = function(grunt) {
|
||||
normal: {
|
||||
options: {
|
||||
urls: [ "http://localhost:8000/test/test.html" ],
|
||||
timeout: 10000
|
||||
}
|
||||
timeout: 10000,
|
||||
puppeteer: {
|
||||
headless: 'new'
|
||||
}
|
||||
},
|
||||
},
|
||||
coverage: {
|
||||
options: {
|
||||
|
@ -4,6 +4,14 @@ OPENSEADRAGON CHANGELOG
|
||||
5.0.0: (in progress...)
|
||||
|
||||
* BREAKING CHANGE: Dropped support for IE11 (#2300, #2361 @AndrewADev)
|
||||
* DEPRECATION: The OpenSeadragon.createCallback function is no longer recommended (#2367 @akansjain)
|
||||
* Introduced maxTilesPerFrame option to allow loading more tiles simultaneously (#2387 @jetic83)
|
||||
* Now when creating a viewer or navigator, we leave its position style alone if possible (#2393 @VIRAT9358)
|
||||
* 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)
|
||||
* Fixed: Two-finger tap on a Mac trackpad would zoom you out (#2431 @cavenel)
|
||||
|
||||
4.1.0:
|
||||
|
||||
|
717
package-lock.json
generated
717
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -35,7 +35,7 @@
|
||||
"grunt-contrib-compress": "^2.0.0",
|
||||
"grunt-contrib-concat": "^2.1.0",
|
||||
"grunt-contrib-connect": "^3.0.0",
|
||||
"grunt-contrib-qunit": "^6.2.0",
|
||||
"grunt-contrib-qunit": "^7.0.1",
|
||||
"grunt-contrib-uglify": "^5.0.1",
|
||||
"grunt-contrib-watch": "^1.1.0",
|
||||
"grunt-eslint": "^24.0.1",
|
||||
@ -48,4 +48,4 @@
|
||||
"test": "grunt test",
|
||||
"prepare": "grunt build"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -59,7 +59,9 @@
|
||||
if( this.element ){
|
||||
this.element = $.getElement( this.element );
|
||||
this.element.appendChild( this.container );
|
||||
this.element.style.position = 'relative';
|
||||
if( $.getElementStyle(this.element).position === 'static' ){
|
||||
this.element.style.position = 'relative';
|
||||
}
|
||||
this.container.style.width = '100%';
|
||||
this.container.style.height = '100%';
|
||||
}
|
||||
|
@ -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} );
|
||||
|
@ -57,16 +57,16 @@
|
||||
* @param {Boolean} [options.startDisabled=false]
|
||||
* If true, event tracking on the element will not start until
|
||||
* {@link OpenSeadragon.MouseTracker.setTracking|setTracking} is called.
|
||||
* @param {Number} options.clickTimeThreshold
|
||||
* @param {Number} [options.clickTimeThreshold=300]
|
||||
* The number of milliseconds within which a pointer down-up event combination
|
||||
* will be treated as a click gesture.
|
||||
* @param {Number} options.clickDistThreshold
|
||||
* @param {Number} [options.clickDistThreshold=5]
|
||||
* The maximum distance allowed between a pointer down event and a pointer up event
|
||||
* to be treated as a click gesture.
|
||||
* @param {Number} options.dblClickTimeThreshold
|
||||
* @param {Number} [options.dblClickTimeThreshold=300]
|
||||
* The number of milliseconds within which two pointer down-up event combinations
|
||||
* will be treated as a double-click gesture.
|
||||
* @param {Number} options.dblClickDistThreshold
|
||||
* @param {Number} [options.dblClickDistThreshold=20]
|
||||
* The maximum distance allowed between two pointer click events
|
||||
* to be treated as a click gesture.
|
||||
* @param {Number} [options.stopDelay=50]
|
||||
@ -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,
|
||||
|
@ -300,6 +300,12 @@
|
||||
* @property {Number} [rotationIncrement=90]
|
||||
* The number of degrees to rotate right or left when the rotate buttons or keyboard shortcuts are activated.
|
||||
*
|
||||
* @property {Number} [maxTilesPerFrame=1]
|
||||
* The number of tiles loaded per frame. As the frame rate of the client's machine is usually high (e.g., 50 fps),
|
||||
* one tile per frame should be a good choice. However, for large screens or lower frame rates, the number of
|
||||
* loaded tiles per frame can be adjusted here. Reasonable values might be 2 or 3 tiles per frame.
|
||||
* (Note that the actual frame rate is given by the client's browser and machine).
|
||||
*
|
||||
* @property {Number} [pixelsPerWheelLine=40]
|
||||
* For pixel-resolution scrolling devices, the number of pixels equal to one scroll line.
|
||||
*
|
||||
@ -1298,6 +1304,7 @@ function OpenSeadragon( options ){
|
||||
preserveImageSizeOnResize: false, // requires autoResize=true
|
||||
minScrollDeltaTime: 50,
|
||||
rotationIncrement: 90,
|
||||
maxTilesPerFrame: 1,
|
||||
|
||||
//DEFAULT CONTROL SETTINGS
|
||||
showSequenceControl: true, //SEQUENCE
|
||||
@ -2277,25 +2284,12 @@ function OpenSeadragon( options ){
|
||||
event.stopPropagation();
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Similar to OpenSeadragon.delegate, but it does not immediately call
|
||||
* the method on the object, returning a function which can be called
|
||||
* repeatedly to delegate the method. It also allows additional arguments
|
||||
* to be passed during construction which will be added during each
|
||||
* invocation, and each invocation can add additional arguments as well.
|
||||
*
|
||||
* @function
|
||||
* @param {Object} object
|
||||
* @param {Function} method
|
||||
* @param [args] any additional arguments are passed as arguments to the
|
||||
* created callback
|
||||
* @returns {Function}
|
||||
*/
|
||||
// Deprecated
|
||||
createCallback: function( object, method ) {
|
||||
//TODO: This pattern is painful to use and debug. It's much cleaner
|
||||
// to use pinning plus anonymous functions. Get rid of this
|
||||
// pattern!
|
||||
console.error('The createCallback function is deprecated and will be removed in future versions. Please use alternativeFunction instead.');
|
||||
var initialArgs = [],
|
||||
i;
|
||||
for ( i = 2; i < arguments.length; i++ ) {
|
||||
|
@ -185,7 +185,8 @@ $.TiledImage = function( options ) {
|
||||
opacity: $.DEFAULT_SETTINGS.opacity,
|
||||
preload: $.DEFAULT_SETTINGS.preload,
|
||||
compositeOperation: $.DEFAULT_SETTINGS.compositeOperation,
|
||||
subPixelRoundingForTransparency: $.DEFAULT_SETTINGS.subPixelRoundingForTransparency
|
||||
subPixelRoundingForTransparency: $.DEFAULT_SETTINGS.subPixelRoundingForTransparency,
|
||||
maxTilesPerFrame: $.DEFAULT_SETTINGS.maxTilesPerFrame
|
||||
}, options );
|
||||
|
||||
this._preload = this.preload;
|
||||
@ -1277,7 +1278,7 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
|
||||
var levelsInterval = this._getLevelsInterval();
|
||||
var lowestLevel = levelsInterval.lowestLevel;
|
||||
var highestLevel = levelsInterval.highestLevel;
|
||||
var bestTile = null;
|
||||
var bestTiles = [];
|
||||
var haveDrawn = false;
|
||||
var drawArea = this.getDrawArea();
|
||||
var currentTime = $.now();
|
||||
@ -1360,7 +1361,8 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
|
||||
optimalRatio - targetRenderPixelRatio
|
||||
);
|
||||
|
||||
// Update the level and keep track of 'best' tile to load
|
||||
// Update the level and keep track of 'best' tiles to load
|
||||
|
||||
var result = this._updateLevel(
|
||||
haveDrawn,
|
||||
drawLevel,
|
||||
@ -1369,10 +1371,10 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
|
||||
levelVisibility,
|
||||
drawArea,
|
||||
currentTime,
|
||||
bestTile
|
||||
bestTiles
|
||||
);
|
||||
|
||||
bestTile = result.best;
|
||||
bestTiles = result.best;
|
||||
var tiles = result.tiles.filter(tile => tile.loaded);
|
||||
var makeTileInfoObject = (function(level, levelOpacity, currentTime){
|
||||
return function(tile){
|
||||
@ -1394,9 +1396,15 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
|
||||
}
|
||||
}
|
||||
|
||||
// Load the new 'best' tile
|
||||
if (bestTile && !bestTile.context2D) {
|
||||
this._loadTile(bestTile, currentTime);
|
||||
|
||||
// Load the new 'best' n tiles
|
||||
if (bestTiles && bestTiles.length > 0) {
|
||||
bestTiles.forEach(function (tile) {
|
||||
if (tile && !tile.context2D) {
|
||||
this._loadTile(tile, currentTime);
|
||||
}
|
||||
}, this);
|
||||
|
||||
this._needsDraw = true;
|
||||
return false;
|
||||
} else {
|
||||
@ -1523,7 +1531,7 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
|
||||
* @param {Number} levelVisibility
|
||||
* @param {OpenSeadragon.Rect} drawArea
|
||||
* @param {Number} currentTime
|
||||
* @param {Object} result Dictionary {best: OpenSeadragon.Tile - the current "best" tile to draw, tiles: Array(OpenSeadragon.Tile) - the updated tiles}.
|
||||
* @param {Object} result Dictionary {best: OpenSeadragon.Tile - the current "best" tiles to draw, tiles: Array(OpenSeadragon.Tile) - the updated tiles}.
|
||||
*/
|
||||
_updateLevel: function(haveDrawn, drawLevel, level, levelOpacity,
|
||||
levelVisibility, drawArea, currentTime, best) {
|
||||
@ -1548,7 +1556,7 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
|
||||
* @property {Object} topleft deprecated, use drawArea instead
|
||||
* @property {Object} bottomright deprecated, use drawArea instead
|
||||
* @property {Object} currenttime
|
||||
* @property {Object} best
|
||||
* @property {Object[]} best
|
||||
* @property {?Object} userData - Arbitrary subscriber-defined object.
|
||||
*/
|
||||
this.viewer.raiseEvent('update-level', {
|
||||
@ -1782,7 +1790,7 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
|
||||
// the tile is already in the download queue
|
||||
this._tilesLoading++;
|
||||
} else if (!loadingCoverage) {
|
||||
best = this._compareTiles( best, tile );
|
||||
best = this._compareTiles( best, tile, this.maxTilesPerFrame );
|
||||
}
|
||||
|
||||
return {
|
||||
@ -2117,24 +2125,22 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
|
||||
/**
|
||||
* @private
|
||||
* @inner
|
||||
* Determines whether the 'last best' tile for the area is better than the
|
||||
* Determines the 'best tiles' from the given 'last best' tiles and the
|
||||
* tile in question.
|
||||
*
|
||||
* @param {OpenSeadragon.Tile} previousBest
|
||||
* @param {OpenSeadragon.Tile} tile
|
||||
* @returns {OpenSeadragon.Tile} The new best tile.
|
||||
* @param {OpenSeadragon.Tile[]} previousBest The best tiles so far.
|
||||
* @param {OpenSeadragon.Tile} tile The new tile to consider.
|
||||
* @param {Number} maxNTiles The max number of best tiles.
|
||||
* @returns {OpenSeadragon.Tile[]} The new best tiles.
|
||||
*/
|
||||
_compareTiles: function( previousBest, tile ) {
|
||||
_compareTiles: function( previousBest, tile, maxNTiles ) {
|
||||
if ( !previousBest ) {
|
||||
return tile;
|
||||
return [tile];
|
||||
}
|
||||
|
||||
if ( tile.visibility > previousBest.visibility ) {
|
||||
return tile;
|
||||
} else if ( tile.visibility === previousBest.visibility ) {
|
||||
if ( tile.squaredDistance < previousBest.squaredDistance ) {
|
||||
return tile;
|
||||
}
|
||||
previousBest.push(tile);
|
||||
this._sortTiles(previousBest);
|
||||
if (previousBest.length > maxNTiles) {
|
||||
previousBest.pop();
|
||||
}
|
||||
return previousBest;
|
||||
},
|
||||
|
@ -1662,6 +1662,7 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype,
|
||||
minZoomImageRatio: _this.minZoomImageRatio,
|
||||
wrapHorizontal: _this.wrapHorizontal,
|
||||
wrapVertical: _this.wrapVertical,
|
||||
maxTilesPerFrame: _this.maxTilesPerFrame,
|
||||
immediateRender: _this.immediateRender,
|
||||
blendTime: _this.blendTime,
|
||||
alwaysBlend: _this.alwaysBlend,
|
||||
|
35
test/demo/max-tiles-per-frame.html
Normal file
35
test/demo/max-tiles-per-frame.html
Normal file
@ -0,0 +1,35 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>OpenSeadragon maxTilesPerFrame Demo</title>
|
||||
<script type="text/javascript" src='../../build/openseadragon/openseadragon.js'></script>
|
||||
<script type="text/javascript" src='../lib/jquery-1.9.1.min.js'></script>
|
||||
<style type="text/css">
|
||||
|
||||
.openseadragon1 {
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div>
|
||||
Simple demo page to show an OpenSeadragon viewer with a higher maxTilesPerFrame.
|
||||
</div>
|
||||
<div id="contentDiv" class="openseadragon1"></div>
|
||||
<script type="text/javascript">
|
||||
|
||||
var viewer = OpenSeadragon({
|
||||
debugMode: true,
|
||||
id: "contentDiv",
|
||||
prefixUrl: "../../build/openseadragon/images/",
|
||||
tileSources: "https://openseadragon.github.io/example-images/duomo/duomo.dzi",
|
||||
showNavigator:true,
|
||||
debugMode:true,
|
||||
maxTilesPerFrame:3,
|
||||
});
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -234,25 +234,36 @@
|
||||
return;
|
||||
}
|
||||
|
||||
viewer.addHandler("open", function () {
|
||||
viewer.addHandler('open', function () {
|
||||
assert.ok(!OpenSeadragon.isFullScreen(), 'Started out not fullscreen');
|
||||
|
||||
const checkEnteringPreFullScreen = function(event) {
|
||||
const checkEnteringPreFullScreen = (event) => {
|
||||
viewer.removeHandler('pre-full-screen', checkEnteringPreFullScreen);
|
||||
assert.ok(event.fullScreen, 'Switching to fullscreen');
|
||||
assert.ok(!OpenSeadragon.isFullScreen(), 'Not yet fullscreen');
|
||||
};
|
||||
|
||||
// The fullscreen mode is always denied during tests so we are
|
||||
// exiting directly.
|
||||
const checkExitingFullScreen = function(event) {
|
||||
const checkExitingFullScreen = (event) => {
|
||||
viewer.removeHandler('full-screen', checkExitingFullScreen);
|
||||
assert.ok(!event.fullScreen, 'Exiting fullscreen');
|
||||
assert.ok(!OpenSeadragon.isFullScreen(), 'Disabled fullscreen');
|
||||
assert.ok(!event.fullScreen, 'Disabling fullscreen');
|
||||
assert.ok(!OpenSeadragon.isFullScreen(), 'Fullscreen disabled');
|
||||
done();
|
||||
}
|
||||
|
||||
// The 'new' headless mode allows us to enter fullscreen, so verify
|
||||
// that we see the correct values returned. We will then close out
|
||||
// of fullscreen to check the same values when exiting.
|
||||
const checkAcquiredFullScreen = (event) => {
|
||||
viewer.removeHandler('full-screen', checkAcquiredFullScreen);
|
||||
viewer.addHandler('full-screen', checkExitingFullScreen);
|
||||
assert.ok(event.fullScreen, 'Acquired fullscreen');
|
||||
assert.ok(OpenSeadragon.isFullScreen(), 'Fullscreen enabled');
|
||||
viewer.setFullScreen(false);
|
||||
};
|
||||
viewer.addHandler("pre-full-screen", checkEnteringPreFullScreen);
|
||||
viewer.addHandler("full-screen", checkExitingFullScreen);
|
||||
|
||||
|
||||
viewer.addHandler('pre-full-screen', checkEnteringPreFullScreen);
|
||||
viewer.addHandler('full-screen', checkAcquiredFullScreen);
|
||||
viewer.setFullScreen(true);
|
||||
});
|
||||
|
||||
|
@ -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",
|
||||
@ -141,6 +156,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');
|
||||
@ -238,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");
|
||||
@ -246,6 +281,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");
|
||||
});
|
||||
|
||||
})();
|
||||
|
Loading…
Reference in New Issue
Block a user