mirror of
https://github.com/openseadragon/openseadragon.git
synced 2025-01-19 17:21:50 +03:00
Merge branch 'master' of https://github.com/openseadragon/openseadragon
This commit is contained in:
commit
9e69462405
@ -7,6 +7,9 @@ OPENSEADRAGON CHANGELOG
|
|||||||
* Added support for commonjs (#984)
|
* Added support for commonjs (#984)
|
||||||
* Added an option to addTiledImage to change the crossOriginPolicy (#981)
|
* Added an option to addTiledImage to change the crossOriginPolicy (#981)
|
||||||
* Fixed issue with tiles not appearing with wrapHorizontal/wrapVertical if you pan too far away from the origin (#987)
|
* Fixed issue with tiles not appearing with wrapHorizontal/wrapVertical if you pan too far away from the origin (#987)
|
||||||
|
* The Viewer's tileSources option is now smarter about detecting JSON vs XML vs URL (#999)
|
||||||
|
* The navigationControlAnchor option now works for custom toolbar as well (#1004)
|
||||||
|
* Added getFullyLoaded method and "fully-loaded-change" event to TiledImage to know when tiles are fully loaded (#837)
|
||||||
|
|
||||||
2.2.1:
|
2.2.1:
|
||||||
|
|
||||||
|
@ -165,6 +165,8 @@ $.TiledImage = function( options ) {
|
|||||||
compositeOperation: $.DEFAULT_SETTINGS.compositeOperation
|
compositeOperation: $.DEFAULT_SETTINGS.compositeOperation
|
||||||
}, options );
|
}, options );
|
||||||
|
|
||||||
|
this._fullyLoaded = false;
|
||||||
|
|
||||||
this._xSpring = new $.Spring({
|
this._xSpring = new $.Spring({
|
||||||
initial: x,
|
initial: x,
|
||||||
springStiffness: this.springStiffness,
|
springStiffness: this.springStiffness,
|
||||||
@ -220,6 +222,37 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
|
|||||||
return this._needsDraw;
|
return this._needsDraw;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns {Boolean} Whether all tiles necessary for this TiledImage to draw at the current view have been loaded.
|
||||||
|
*/
|
||||||
|
getFullyLoaded: function() {
|
||||||
|
return this._fullyLoaded;
|
||||||
|
},
|
||||||
|
|
||||||
|
// private
|
||||||
|
_setFullyLoaded: function(flag) {
|
||||||
|
if (flag === this._fullyLoaded) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._fullyLoaded = flag;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fired when the TiledImage's "fully loaded" flag (whether all tiles necessary for this TiledImage
|
||||||
|
* to draw at the current view have been loaded) changes.
|
||||||
|
*
|
||||||
|
* @event fully-loaded-change
|
||||||
|
* @memberof OpenSeadragon.TiledImage
|
||||||
|
* @type {object}
|
||||||
|
* @property {Boolean} fullyLoaded - The new "fully loaded" value.
|
||||||
|
* @property {OpenSeadragon.TiledImage} eventSource - A reference to the TiledImage which raised the event.
|
||||||
|
* @property {?Object} userData - Arbitrary subscriber-defined object.
|
||||||
|
*/
|
||||||
|
this.raiseEvent('fully-loaded-change', {
|
||||||
|
fullyLoaded: this._fullyLoaded
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clears all tiles and triggers an update on the next call to
|
* Clears all tiles and triggers an update on the next call to
|
||||||
* {@link OpenSeadragon.TiledImage#update}.
|
* {@link OpenSeadragon.TiledImage#update}.
|
||||||
@ -948,8 +981,10 @@ function updateViewport( tiledImage ) {
|
|||||||
// Load the new 'best' tile
|
// Load the new 'best' tile
|
||||||
if (best && !best.context2D) {
|
if (best && !best.context2D) {
|
||||||
loadTile( tiledImage, best, currentTime );
|
loadTile( tiledImage, best, currentTime );
|
||||||
|
tiledImage._setFullyLoaded(false);
|
||||||
|
} else {
|
||||||
|
tiledImage._setFullyLoaded(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1749,7 +1749,7 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype,
|
|||||||
if( this.toolbar ){
|
if( this.toolbar ){
|
||||||
this.toolbar.addControl(
|
this.toolbar.addControl(
|
||||||
this.navControl,
|
this.navControl,
|
||||||
{anchor: $.ControlAnchor.TOP_LEFT}
|
{anchor: this.navigationControlAnchor || $.ControlAnchor.TOP_LEFT}
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
this.addControl(
|
this.addControl(
|
||||||
@ -2124,9 +2124,11 @@ function getTileSourceImplementation( viewer, tileSource, imgOptions, successCal
|
|||||||
|
|
||||||
//allow plain xml strings or json strings to be parsed here
|
//allow plain xml strings or json strings to be parsed here
|
||||||
if ( $.type( tileSource ) == 'string' ) {
|
if ( $.type( tileSource ) == 'string' ) {
|
||||||
if ( tileSource.match( /\s*<.*/ ) ) {
|
//xml should start with "<" and end with ">"
|
||||||
|
if ( tileSource.match( /^\s*<.*>\s*$/ ) ) {
|
||||||
tileSource = $.parseXml( tileSource );
|
tileSource = $.parseXml( tileSource );
|
||||||
} else if ( tileSource.match( /\s*[\{\[].*/ ) ) {
|
//json should start with "{" or "[" and end with "}" or "]"
|
||||||
|
} else if ( tileSource.match(/^\s*[\{\[].*[\}\]]\s*$/ ) ) {
|
||||||
tileSource = $.parseJSON(tileSource);
|
tileSource = $.parseJSON(tileSource);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -211,11 +211,16 @@
|
|||||||
asyncTest('Transparent image on top of others', function() {
|
asyncTest('Transparent image on top of others', function() {
|
||||||
viewer.open('/test/data/testpattern.dzi');
|
viewer.open('/test/data/testpattern.dzi');
|
||||||
|
|
||||||
// TODO: replace with fully-loaded event listener when available.
|
var density = OpenSeadragon.pixelDensityRatio;
|
||||||
setTimeout(function() {
|
|
||||||
var imageData = viewer.drawer.context.getImageData(0, 0, 500, 500);
|
viewer.addHandler('open', function() {
|
||||||
|
var firstImage = viewer.world.getItemAt(0);
|
||||||
|
firstImage.addHandler('fully-loaded-change', function() {
|
||||||
|
var imageData = viewer.drawer.context.getImageData(0, 0,
|
||||||
|
500 * OpenSeadragon.pixelDensityRatio, 500 * density);
|
||||||
|
|
||||||
// Pixel 250,250 will be in the hole of the A
|
// Pixel 250,250 will be in the hole of the A
|
||||||
var expectedVal = getPixelValue(imageData, 250, 250);
|
var expectedVal = getPixelValue(imageData, 250 * density, 250 * density);
|
||||||
|
|
||||||
notEqual(expectedVal.r, 0, 'Red channel should not be 0');
|
notEqual(expectedVal.r, 0, 'Red channel should not be 0');
|
||||||
notEqual(expectedVal.g, 0, 'Green channel should not be 0');
|
notEqual(expectedVal.g, 0, 'Green channel should not be 0');
|
||||||
@ -223,13 +228,12 @@
|
|||||||
notEqual(expectedVal.a, 0, 'Alpha channel should not be 0');
|
notEqual(expectedVal.a, 0, 'Alpha channel should not be 0');
|
||||||
|
|
||||||
viewer.addSimpleImage({
|
viewer.addSimpleImage({
|
||||||
url: '/test/data/A.png'
|
url: '/test/data/A.png',
|
||||||
});
|
success: function() {
|
||||||
|
var secondImage = viewer.world.getItemAt(1);
|
||||||
// TODO: replace with fully-loaded event listener when available.
|
secondImage.addHandler('fully-loaded-change', function() {
|
||||||
setTimeout(function() {
|
var imageData = viewer.drawer.context.getImageData(0, 0, 500 * density, 500 * density);
|
||||||
var imageData = viewer.drawer.context.getImageData(0, 0, 500, 500);
|
var actualVal = getPixelValue(imageData, 250 * density, 250 * density);
|
||||||
var actualVal = getPixelValue(imageData, 250, 250);
|
|
||||||
|
|
||||||
equal(actualVal.r, expectedVal.r,
|
equal(actualVal.r, expectedVal.r,
|
||||||
'Red channel should not change in transparent part of the A');
|
'Red channel should not change in transparent part of the A');
|
||||||
@ -240,15 +244,18 @@
|
|||||||
equal(actualVal.a, expectedVal.a,
|
equal(actualVal.a, expectedVal.a,
|
||||||
'Alpha channel should not change in transparent part of the A');
|
'Alpha channel should not change in transparent part of the A');
|
||||||
|
|
||||||
var onAVal = getPixelValue(imageData, 333, 250);
|
var onAVal = getPixelValue(imageData, 333 * density, 250 * density);
|
||||||
equal(onAVal.r, 0, 'Red channel should be null on the A');
|
equal(onAVal.r, 0, 'Red channel should be null on the A');
|
||||||
equal(onAVal.g, 0, 'Green channel should be null on the A');
|
equal(onAVal.g, 0, 'Green channel should be null on the A');
|
||||||
equal(onAVal.b, 0, 'Blue channel should be null on the A');
|
equal(onAVal.b, 0, 'Blue channel should be null on the A');
|
||||||
equal(onAVal.a, 255, 'Alpha channel should be 255 on the A');
|
equal(onAVal.a, 255, 'Alpha channel should be 255 on the A');
|
||||||
|
|
||||||
start();
|
start();
|
||||||
}, 500);
|
});
|
||||||
}, 500);
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
function getPixelValue(imageData, x, y) {
|
function getPixelValue(imageData, x, y) {
|
||||||
var offset = 4 * (y * imageData.width + x);
|
var offset = 4 * (y * imageData.width + x);
|
||||||
|
@ -207,8 +207,8 @@
|
|||||||
|
|
||||||
Util.spyOnce(viewer.drawer, 'setClip', function(rect) {
|
Util.spyOnce(viewer.drawer, 'setClip', function(rect) {
|
||||||
var homeBounds = viewer.viewport.getHomeBounds();
|
var homeBounds = viewer.viewport.getHomeBounds();
|
||||||
var canvasClip = viewer.viewport
|
var canvasClip = viewer.drawer
|
||||||
.viewportToViewerElementRectangle(homeBounds);
|
.viewportToDrawerRectangle(homeBounds);
|
||||||
var precision = 0.00000001;
|
var precision = 0.00000001;
|
||||||
Util.assertRectangleEquals(rect, canvasClip, precision,
|
Util.assertRectangleEquals(rect, canvasClip, precision,
|
||||||
'clipping should be ' + canvasClip);
|
'clipping should be ' + canvasClip);
|
||||||
@ -222,6 +222,7 @@
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// ----------
|
||||||
asyncTest('getClipBounds', function() {
|
asyncTest('getClipBounds', function() {
|
||||||
var clip = new OpenSeadragon.Rect(100, 200, 800, 500);
|
var clip = new OpenSeadragon.Rect(100, 200, 800, 500);
|
||||||
|
|
||||||
@ -367,6 +368,7 @@
|
|||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// ----------
|
||||||
asyncTest('fitBounds in constructor', function() {
|
asyncTest('fitBounds in constructor', function() {
|
||||||
|
|
||||||
function assertRectEquals(actual, expected, message) {
|
function assertRectEquals(actual, expected, message) {
|
||||||
@ -412,6 +414,7 @@
|
|||||||
}]);
|
}]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// ----------
|
||||||
asyncTest('fitBounds with clipping', function() {
|
asyncTest('fitBounds with clipping', function() {
|
||||||
|
|
||||||
function assertRectEquals(actual, expected, message) {
|
function assertRectEquals(actual, expected, message) {
|
||||||
@ -455,4 +458,40 @@
|
|||||||
fitBoundsPlacement: OpenSeadragon.Placement.TOP_LEFT
|
fitBoundsPlacement: OpenSeadragon.Placement.TOP_LEFT
|
||||||
}]);
|
}]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// ----------
|
||||||
|
asyncTest('fullyLoaded', function() {
|
||||||
|
viewer.addHandler('open', function openHandler() {
|
||||||
|
viewer.removeHandler('open', openHandler);
|
||||||
|
|
||||||
|
var image = viewer.world.getItemAt(0);
|
||||||
|
equal(image.getFullyLoaded(), false, 'not fully loaded at first');
|
||||||
|
|
||||||
|
var count = 0;
|
||||||
|
|
||||||
|
var fullyLoadedChangeHandler = function(event) {
|
||||||
|
if (count === 0) {
|
||||||
|
equal(event.fullyLoaded, true, 'event includes true fullyLoaded property');
|
||||||
|
equal(image.getFullyLoaded(), true, 'image is fully loaded after event');
|
||||||
|
viewer.viewport.zoomBy(5, null, true);
|
||||||
|
} else if (count === 1) {
|
||||||
|
equal(event.fullyLoaded, false, 'event includes false fullyLoaded property');
|
||||||
|
equal(image.getFullyLoaded(), false, 'image is not fully loaded after zoom');
|
||||||
|
} else {
|
||||||
|
image.removeHandler('fully-loaded-change', fullyLoadedChangeHandler);
|
||||||
|
equal(image.getFullyLoaded(), true, 'image is once again fully loaded');
|
||||||
|
start();
|
||||||
|
}
|
||||||
|
|
||||||
|
count++;
|
||||||
|
};
|
||||||
|
|
||||||
|
image.addHandler('fully-loaded-change', fullyLoadedChangeHandler);
|
||||||
|
});
|
||||||
|
|
||||||
|
viewer.open([{
|
||||||
|
tileSource: '/test/data/tall.dzi',
|
||||||
|
}]);
|
||||||
|
});
|
||||||
|
|
||||||
})();
|
})();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user