mirror of
https://github.com/openseadragon/openseadragon.git
synced 2024-11-21 20:56:09 +03:00
commit
93096fe1c3
@ -3,6 +3,10 @@ OPENSEADRAGON CHANGELOG
|
||||
|
||||
1.0.1: (in progress)
|
||||
|
||||
* BREAKING CHANGE: the openseadragon-canvas element now have two child divs which mean: (#298)
|
||||
* the drawer element is no longer accessible via viewer.canvas.firstChild but via viewer.drawersContainer.firstChild or viewer.drawer.canvas.
|
||||
* the overlays elements are no longer accssible via viewer.canvas.childNodes but via viewer.overlaysContainer.childNodes or viewer.currentOverlays[i].element.
|
||||
* Added layers support. Multiple images can now been displayed on top of each other with transparency via the Viewer.addLayer method (#298)
|
||||
* DEPRECATION: overlay functions have been moved from Drawer to Viewer (#331)
|
||||
* Improved overlay functions (#331)
|
||||
* Fixed: Nav button highlight states aren't quite aligned on Firefox (#303)
|
||||
|
@ -90,6 +90,7 @@ $.Drawer = function( options ) {
|
||||
collectionOverlays: {}, // For collection mode. Here an overlay is actually a viewer.
|
||||
|
||||
//configurable settings
|
||||
opacity: $.DEFAULT_SETTINGS.opacity,
|
||||
maxImageCacheCount: $.DEFAULT_SETTINGS.maxImageCacheCount,
|
||||
imageLoaderLimit: $.DEFAULT_SETTINGS.imageLoaderLimit,
|
||||
minZoomImageRatio: $.DEFAULT_SETTINGS.minZoomImageRatio,
|
||||
@ -142,6 +143,7 @@ $.Drawer = function( options ) {
|
||||
this.canvas.style.width = "100%";
|
||||
this.canvas.style.height = "100%";
|
||||
this.canvas.style.position = "absolute";
|
||||
$.setElementOpacity( this.canvas, this.opacity, true );
|
||||
|
||||
// explicit left-align
|
||||
this.container.style.textAlign = "left";
|
||||
@ -225,6 +227,26 @@ $.Drawer.prototype = /** @lends OpenSeadragon.Drawer.prototype */{
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* Set the opacity of the drawer.
|
||||
* @method
|
||||
* @param {Number} opacity
|
||||
* @return {OpenSeadragon.Drawer} Chainable.
|
||||
*/
|
||||
setOpacity: function( opacity ) {
|
||||
this.opacity = opacity;
|
||||
$.setElementOpacity( this.canvas, this.opacity, true );
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* Get the opacity of the drawer.
|
||||
* @method
|
||||
* @returns {Number}
|
||||
*/
|
||||
getOpacity: function() {
|
||||
return this.opacity;
|
||||
},
|
||||
/**
|
||||
* Returns whether the Drawer is scheduled for an update at the
|
||||
* soonest possible opportunity.
|
||||
|
@ -212,6 +212,12 @@
|
||||
* Zoom level to use when image is first opened or the home button is clicked.
|
||||
* If 0, adjusts to fit viewer.
|
||||
*
|
||||
* @property {Number} [opacity=1]
|
||||
* Opacity of the drawer (1=opaque, 0=transparent)
|
||||
*
|
||||
* @property {Number} [layersAspectRatioEpsilon=0.0001]
|
||||
* Maximum aspectRatio mismatch between 2 layers.
|
||||
*
|
||||
* @property {Number} [degrees=0]
|
||||
* Initial rotation.
|
||||
*
|
||||
@ -772,6 +778,12 @@ window.OpenSeadragon = window.OpenSeadragon || function( options ){
|
||||
// INITIAL ROTATION
|
||||
degrees: 0,
|
||||
|
||||
// APPEARANCE
|
||||
opacity: 1,
|
||||
|
||||
// LAYERS SETTINGS
|
||||
layersAspectRatioEpsilon: 0.0001,
|
||||
|
||||
//REFERENCE STRIP SETTINGS
|
||||
showReferenceStrip: false,
|
||||
referenceStripScroll: 'horizontal',
|
||||
@ -1396,6 +1408,52 @@ window.OpenSeadragon = window.OpenSeadragon || function( options ){
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Find the first index at which an element is found in an array or -1
|
||||
* if not present.
|
||||
*
|
||||
* Code taken and adapted from
|
||||
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf#Compatibility
|
||||
*
|
||||
* @function
|
||||
* @param {Array} array The array from which to find the element
|
||||
* @param {Object} searchElement The element to find
|
||||
* @param {Number} [fromIndex=0] Index to start research.
|
||||
* @returns {Number} The index of the element in the array.
|
||||
*/
|
||||
indexOf: function( array, searchElement, fromIndex ) {
|
||||
if ( Array.prototype.indexOf ) {
|
||||
this.indexOf = function( array, searchElement, fromIndex ) {
|
||||
return array.indexOf( searchElement, fromIndex );
|
||||
};
|
||||
} else {
|
||||
this.indexOf = function( array, searchElement, fromIndex ) {
|
||||
var i,
|
||||
pivot = ( fromIndex ) ? fromIndex : 0,
|
||||
length;
|
||||
if ( !array ) {
|
||||
throw new TypeError( );
|
||||
}
|
||||
|
||||
length = array.length;
|
||||
if ( length === 0 || pivot >= length ) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( pivot < 0 ) {
|
||||
pivot = length - Math.abs( pivot );
|
||||
}
|
||||
|
||||
for ( i = pivot; i < length; i++ ) {
|
||||
if ( array[i] === searchElement ) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
};
|
||||
}
|
||||
return this.indexOf( array, searchElement, fromIndex );
|
||||
},
|
||||
|
||||
/**
|
||||
* Remove the specified CSS class from the element.
|
||||
|
445
src/viewer.js
445
src/viewer.js
@ -128,6 +128,8 @@ $.Viewer = function( options ) {
|
||||
|
||||
// Overlays list. An overlay allows to add html on top of the viewer.
|
||||
overlays: [],
|
||||
// Container inside the canvas where overlays are drawn.
|
||||
overlaysContainer: null,
|
||||
|
||||
//private state properties
|
||||
previousBody: [],
|
||||
@ -148,8 +150,10 @@ $.Viewer = function( options ) {
|
||||
* @member {OpenSeadragon.Drawer} drawer
|
||||
* @memberof OpenSeadragon.Viewer#
|
||||
*/
|
||||
drawer: null,
|
||||
drawers: [],
|
||||
drawer: null,
|
||||
drawers: [],
|
||||
// Container inside the canvas where drawers (layers) are drawn.
|
||||
drawersContainer: null,
|
||||
/**
|
||||
* Handles coordinate-related functionality - zoom, pan, rotation, etc. Created for each TileSource opened.
|
||||
* @member {OpenSeadragon.Viewport} viewport
|
||||
@ -260,6 +264,8 @@ $.Viewer = function( options ) {
|
||||
this.element = this.element || document.getElementById( this.id );
|
||||
this.canvas = $.makeNeutralElement( "div" );
|
||||
this.keyboardCommandArea = $.makeNeutralElement( "textarea" );
|
||||
this.drawersContainer = $.makeNeutralElement( "div" );
|
||||
this.overlaysContainer = $.makeNeutralElement( "div" );
|
||||
|
||||
this.canvas.className = "openseadragon-canvas";
|
||||
(function( style ){
|
||||
@ -297,6 +303,8 @@ $.Viewer = function( options ) {
|
||||
this.container.insertBefore( this.canvas, this.container.firstChild );
|
||||
this.container.insertBefore( this.keyboardCommandArea, this.container.firstChild );
|
||||
this.element.appendChild( this.container );
|
||||
this.canvas.appendChild( this.drawersContainer );
|
||||
this.canvas.appendChild( this.overlaysContainer );
|
||||
|
||||
//Used for toggling between fullscreen and default container size
|
||||
//TODO: these can be closure private and shared across Viewer
|
||||
@ -476,81 +484,26 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype,
|
||||
* @fires OpenSeadragon.Viewer.event:open-failed
|
||||
*/
|
||||
open: function ( tileSource ) {
|
||||
var _this = this,
|
||||
customTileSource,
|
||||
readySource,
|
||||
$TileSource,
|
||||
options;
|
||||
var _this = this;
|
||||
|
||||
_this._hideMessage();
|
||||
|
||||
//allow plain xml strings or json strings to be parsed here
|
||||
if( $.type( tileSource ) == 'string' ){
|
||||
if( tileSource.match(/\s*<.*/) ){
|
||||
tileSource = $.parseXml( tileSource );
|
||||
}else if( tileSource.match(/\s*[\{\[].*/) ){
|
||||
/*jshint evil:true*/
|
||||
tileSource = eval( '('+tileSource+')' );
|
||||
}
|
||||
}
|
||||
|
||||
setTimeout(function(){
|
||||
if ( $.type( tileSource ) == 'string') {
|
||||
//If its still a string it means it must be a url at this point
|
||||
tileSource = new $.TileSource( tileSource, function( event ){
|
||||
openTileSource( _this, event.tileSource );
|
||||
});
|
||||
tileSource.addHandler( 'open-failed', function ( event ) {
|
||||
/**
|
||||
* Raised when an error occurs loading a TileSource.
|
||||
*
|
||||
* @event open-failed
|
||||
* @memberof OpenSeadragon.Viewer
|
||||
* @type {object}
|
||||
* @property {OpenSeadragon.Viewer} eventSource - A reference to the Viewer which raised the event.
|
||||
* @property {String} message
|
||||
* @property {String} source
|
||||
* @property {?Object} userData - Arbitrary subscriber-defined object.
|
||||
*/
|
||||
_this.raiseEvent( 'open-failed', event );
|
||||
});
|
||||
|
||||
} else if ( $.isPlainObject( tileSource ) || tileSource.nodeType ){
|
||||
if( $.isFunction( tileSource.getTileUrl ) ){
|
||||
//Custom tile source
|
||||
customTileSource = new $.TileSource(tileSource);
|
||||
customTileSource.getTileUrl = tileSource.getTileUrl;
|
||||
openTileSource( _this, customTileSource );
|
||||
} else {
|
||||
//inline configuration
|
||||
$TileSource = $.TileSource.determineType( _this, tileSource );
|
||||
if ( !$TileSource ) {
|
||||
/***
|
||||
* Raised when an error occurs loading a TileSource.
|
||||
*
|
||||
* @event open-failed
|
||||
* @memberof OpenSeadragon.Viewer
|
||||
* @type {object}
|
||||
* @property {OpenSeadragon.Viewer} eventSource - A reference to the Viewer which raised the event.
|
||||
* @property {String} message
|
||||
* @property {String} source
|
||||
* @property {?Object} userData - Arbitrary subscriber-defined object.
|
||||
*/
|
||||
_this.raiseEvent( 'open-failed', {
|
||||
message: "Unable to load TileSource",
|
||||
source: tileSource
|
||||
});
|
||||
return;
|
||||
}
|
||||
options = $TileSource.prototype.configure.apply( _this, [ tileSource ]);
|
||||
readySource = new $TileSource( options );
|
||||
openTileSource( _this, readySource );
|
||||
}
|
||||
} else {
|
||||
//can assume it's already a tile source implementation
|
||||
openTileSource( _this, tileSource );
|
||||
}
|
||||
}, 1);
|
||||
getTileSourceImplementation( _this, tileSource, function( tileSource ) {
|
||||
openTileSource( _this, tileSource );
|
||||
}, function( event ) {
|
||||
/**
|
||||
* Raised when an error occurs loading a TileSource.
|
||||
*
|
||||
* @event open-failed
|
||||
* @memberof OpenSeadragon.Viewer
|
||||
* @type {object}
|
||||
* @property {OpenSeadragon.Viewer} eventSource - A reference to the Viewer which raised the event.
|
||||
* @property {String} message
|
||||
* @property {String} source
|
||||
* @property {?Object} userData - Arbitrary subscriber-defined object.
|
||||
*/
|
||||
_this.raiseEvent( 'open-failed', event );
|
||||
});
|
||||
|
||||
return this;
|
||||
},
|
||||
@ -572,15 +525,15 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype,
|
||||
}
|
||||
|
||||
this.clearOverlays();
|
||||
this.drawersContainer.innerHTML = "";
|
||||
this.overlaysContainer.innerHTML = "";
|
||||
|
||||
this.source = null;
|
||||
this.drawer = null;
|
||||
this.drawers = [];
|
||||
|
||||
this.viewport = this.preserveViewport ? this.viewport : null;
|
||||
//this.profiler = null;
|
||||
if (this.canvas){
|
||||
this.canvas.innerHTML = "";
|
||||
}
|
||||
|
||||
|
||||
VIEWERS[ this.hash ] = null;
|
||||
delete VIEWERS[ this.hash ];
|
||||
@ -1049,6 +1002,257 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype,
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* Add a layer.
|
||||
* options.tileSource can be anything that {@link OpenSeadragon.Viewer#open}
|
||||
* supports except arrays of images as layers cannot be sequences.
|
||||
* @function
|
||||
* @param {Object} options
|
||||
* @param {String|Object|Function} options.tileSource The TileSource of the layer.
|
||||
* @param {Number} [options.opacity=1] The opacity of the layer.
|
||||
* @param {Number} [options.level] The level of the layer. Added on top of
|
||||
* all other layers if not specified.
|
||||
* @returns {OpenSeadragon.Viewer} Chainable.
|
||||
* @fires OpenSeadragon.Viewer.event:add-layer
|
||||
* @fires OpenSeadragon.Viewer.event:add-layer-failed
|
||||
*/
|
||||
addLayer: function( options ) {
|
||||
var _this = this,
|
||||
tileSource = options.tileSource;
|
||||
|
||||
if ( !this.isOpen() ) {
|
||||
throw new Error( "An image must be loaded before adding layers." );
|
||||
}
|
||||
if ( !tileSource ) {
|
||||
throw new Error( "No tile source provided as new layer." );
|
||||
}
|
||||
if ( this.collectionMode ) {
|
||||
throw new Error( "Layers not supported in collection mode." );
|
||||
}
|
||||
|
||||
function raiseAddLayerFailed( event ) {
|
||||
/**
|
||||
* Raised when an error occurs while adding a layer.
|
||||
* @event add-layer-failed
|
||||
* @memberOf OpenSeadragon.Viewer
|
||||
* @type {object}
|
||||
* @property {OpenSeadragon.Viewer} eventSource - A reference to the Viewer which raised the event.
|
||||
* @property {String} message
|
||||
* @property {String} source
|
||||
* @property {Object} options The options passed to the addLayer method.
|
||||
* @property {?Object} userData - Arbitrary subscriber-defined object.
|
||||
*/
|
||||
_this.raiseEvent( 'add-layer-failed', event );
|
||||
}
|
||||
|
||||
getTileSourceImplementation( this, tileSource, function( tileSource ) {
|
||||
|
||||
if ( tileSource instanceof Array ) {
|
||||
raiseAddLayerFailed({
|
||||
message: "Sequences can not be added as layers.",
|
||||
source: tileSource,
|
||||
options: options
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
for ( var i = 0; i < _this.drawers.length; i++ ) {
|
||||
var otherAspectRatio = _this.drawers[ i ].source.aspectRatio;
|
||||
var diff = otherAspectRatio - tileSource.aspectRatio;
|
||||
if ( Math.abs( diff ) > _this.layersAspectRatioEpsilon ) {
|
||||
raiseAddLayerFailed({
|
||||
message: "Aspect ratio mismatch with layer " + i + ".",
|
||||
source: tileSource,
|
||||
options: options
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
var drawer = new $.Drawer({
|
||||
viewer: _this,
|
||||
source: tileSource,
|
||||
viewport: _this.viewport,
|
||||
element: _this.drawersContainer,
|
||||
opacity: options.opacity !== undefined ?
|
||||
options.opacity : _this.opacity,
|
||||
maxImageCacheCount: _this.maxImageCacheCount,
|
||||
imageLoaderLimit: _this.imageLoaderLimit,
|
||||
minZoomImageRatio: _this.minZoomImageRatio,
|
||||
wrapHorizontal: _this.wrapHorizontal,
|
||||
wrapVertical: _this.wrapVertical,
|
||||
immediateRender: _this.immediateRender,
|
||||
blendTime: _this.blendTime,
|
||||
alwaysBlend: _this.alwaysBlend,
|
||||
minPixelRatio: _this.minPixelRatio,
|
||||
timeout: _this.timeout,
|
||||
debugMode: _this.debugMode,
|
||||
debugGridColor: _this.debugGridColor
|
||||
});
|
||||
_this.drawers.push( drawer );
|
||||
if ( options.level !== undefined ) {
|
||||
_this.setLayerLevel( drawer, options.level );
|
||||
}
|
||||
THIS[ _this.hash ].forceRedraw = true;
|
||||
/**
|
||||
* Raised when a layer is successfully added.
|
||||
* @event add-layer
|
||||
* @memberOf OpenSeadragon.Viewer
|
||||
* @type {object}
|
||||
* @property {OpenSeadragon.Viewer} eventSource - A reference to the Viewer which raised the event.
|
||||
* @property {Object} options The options passed to the addLayer method.
|
||||
* @property {OpenSeadragon.Drawer} drawer The layer's underlying drawer.
|
||||
* @property {?Object} userData - Arbitrary subscriber-defined object.
|
||||
*/
|
||||
_this.raiseEvent( 'add-layer', {
|
||||
options: options,
|
||||
drawer: drawer
|
||||
});
|
||||
}, function( event ) {
|
||||
event.options = options;
|
||||
raiseAddLayerFailed(event);
|
||||
} );
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* Get the layer at the specified level.
|
||||
* @param {Number} level The layer to retrieve level.
|
||||
* @returns {OpenSeadragon.Drawer} The layer at the specified level.
|
||||
*/
|
||||
getLayerAtLevel: function( level ) {
|
||||
if ( level >= this.drawers.length ) {
|
||||
throw new Error( "Level bigger than number of layers." );
|
||||
}
|
||||
return this.drawers[ level ];
|
||||
},
|
||||
|
||||
/**
|
||||
* Get the level of the layer associated with the given drawer or -1 if not
|
||||
* present.
|
||||
* @param {OpenSeadragon.Drawer} drawer The underlying drawer of the layer.
|
||||
* @returns {Number} The level of the layer or -1 if not present.
|
||||
*/
|
||||
getLevelOfLayer: function( drawer ) {
|
||||
return $.indexOf( this.drawers, drawer );
|
||||
},
|
||||
|
||||
/**
|
||||
* Get the number of layers used.
|
||||
* @returns {Number} The number of layers used.
|
||||
*/
|
||||
getLayersCount: function() {
|
||||
return this.drawers.length;
|
||||
},
|
||||
|
||||
/**
|
||||
* Change the level of a layer so that it appears over or under others.
|
||||
* @param {OpenSeadragon.Drawer} drawer The underlying drawer of the changing
|
||||
* level layer.
|
||||
* @param {Number} level The new level
|
||||
* @returns {OpenSeadragon.Viewer} Chainable.
|
||||
* @fires OpenSeadragon.Viewer.event:layer-level-changed
|
||||
*/
|
||||
setLayerLevel: function( drawer, level ) {
|
||||
var oldLevel = this.getLevelOfLayer( drawer );
|
||||
|
||||
if ( level >= this.drawers.length ) {
|
||||
throw new Error( "Level bigger than number of layers." );
|
||||
}
|
||||
if ( level === oldLevel || oldLevel === -1 ) {
|
||||
return this;
|
||||
}
|
||||
if ( level === 0 || oldLevel === 0 ) {
|
||||
if ( THIS[ this.hash ].sequenced ) {
|
||||
throw new Error( "Cannot reassign base level when in sequence mode." );
|
||||
}
|
||||
// We need to re-assign the base drawer and the source
|
||||
this.drawer = level === 0 ? drawer : this.getLayerAtLevel( level );
|
||||
this.source = this.drawer.source;
|
||||
}
|
||||
this.drawers.splice( oldLevel, 1 );
|
||||
this.drawers.splice( level, 0, drawer );
|
||||
this.drawersContainer.removeChild( drawer.canvas );
|
||||
if ( level === 0 ) {
|
||||
var nextLevelCanvas = this.drawers[ 1 ].canvas;
|
||||
nextLevelCanvas.parentNode.insertBefore( drawer.canvas,
|
||||
nextLevelCanvas );
|
||||
} else {
|
||||
// Insert right after layer at level - 1
|
||||
var prevLevelCanvas = this.drawers[level - 1].canvas;
|
||||
prevLevelCanvas.parentNode.insertBefore( drawer.canvas,
|
||||
prevLevelCanvas.nextSibling );
|
||||
}
|
||||
|
||||
/**
|
||||
* Raised when the order of the layers has been changed.
|
||||
* @event layer-level-changed
|
||||
* @memberOf OpenSeadragon.Viewer
|
||||
* @type {object}
|
||||
* @property {OpenSeadragon.Viewer} eventSource - A reference to the Viewer which raised the event.
|
||||
* @property {OpenSeadragon.Drawer} drawer - The drawer which level has
|
||||
* been changed
|
||||
* @property {Number} previousLevel - The previous level of the drawer
|
||||
* @property {Number} newLevel - The new level of the drawer
|
||||
* @property {?Object} userData - Arbitrary subscriber-defined object.
|
||||
*/
|
||||
this.raiseEvent( 'layer-level-changed', {
|
||||
drawer: drawer,
|
||||
previousLevel: oldLevel,
|
||||
newLevel: level
|
||||
} );
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* Remove a layer. If there is only one layer, close the viewer.
|
||||
* @function
|
||||
* @param {OpenSeadragon.Drawer} drawer The underlying drawer of the layer
|
||||
* to remove
|
||||
* @returns {OpenSeadragon.Viewer} Chainable.
|
||||
* @fires OpenSeadragon.Viewer.event:remove-layer
|
||||
*/
|
||||
removeLayer: function( drawer ) {
|
||||
var index = this.drawers.indexOf( drawer );
|
||||
if ( index === -1 ) {
|
||||
return this;
|
||||
}
|
||||
if ( index === 0 ) {
|
||||
if ( THIS[ this.hash ].sequenced ) {
|
||||
throw new Error( "Cannot remove base layer when in sequence mode." );
|
||||
}
|
||||
if ( this.drawers.length === 1 ) {
|
||||
this.close();
|
||||
return this;
|
||||
}
|
||||
this.drawer = this.drawers[ 1 ];
|
||||
}
|
||||
|
||||
this.drawers.splice( index, 1 );
|
||||
this.drawersContainer.removeChild( drawer.canvas );
|
||||
/**
|
||||
* Raised when a layer is removed.
|
||||
* @event remove-layer
|
||||
* @memberOf OpenSeadragon.Viewer
|
||||
* @type {object}
|
||||
* @property {OpenSeadragon.Viewer} eventSource - A reference to the Viewer which raised the event.
|
||||
* @property {OpenSeadragon.Drawer} drawer The layer's underlying drawer.
|
||||
* @property {?Object} userData - Arbitrary subscriber-defined object.
|
||||
*/
|
||||
this.raiseEvent( 'remove-layer', { drawer: drawer } );
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* Force the viewer to redraw its drawers.
|
||||
* @returns {OpenSeadragon.Viewer} Chainable.
|
||||
*/
|
||||
forceRedraw: function() {
|
||||
THIS[ this.hash ].forceRedraw = true;
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* @function
|
||||
@ -1578,6 +1782,61 @@ function _getSafeElemSize (oElement) {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @function
|
||||
* @private
|
||||
*/
|
||||
function getTileSourceImplementation( viewer, tileSource, successCallback,
|
||||
failCallback ) {
|
||||
var _this = viewer;
|
||||
|
||||
//allow plain xml strings or json strings to be parsed here
|
||||
if ( $.type( tileSource ) == 'string' ) {
|
||||
if ( tileSource.match( /\s*<.*/ ) ) {
|
||||
tileSource = $.parseXml( tileSource );
|
||||
} else if ( tileSource.match( /\s*[\{\[].*/ ) ) {
|
||||
/*jshint evil:true*/
|
||||
tileSource = eval( '(' + tileSource + ')' );
|
||||
}
|
||||
}
|
||||
|
||||
setTimeout( function() {
|
||||
if ( $.type( tileSource ) == 'string' ) {
|
||||
//If its still a string it means it must be a url at this point
|
||||
tileSource = new $.TileSource( tileSource, function( event ) {
|
||||
successCallback( event.tileSource );
|
||||
});
|
||||
tileSource.addHandler( 'open-failed', function( event ) {
|
||||
failCallback( event );
|
||||
} );
|
||||
|
||||
} else if ( $.isPlainObject( tileSource ) || tileSource.nodeType ) {
|
||||
if ( $.isFunction( tileSource.getTileUrl ) ) {
|
||||
//Custom tile source
|
||||
var customTileSource = new $.TileSource( tileSource );
|
||||
customTileSource.getTileUrl = tileSource.getTileUrl;
|
||||
successCallback( customTileSource );
|
||||
} else {
|
||||
//inline configuration
|
||||
var $TileSource = $.TileSource.determineType( _this, tileSource );
|
||||
if ( !$TileSource ) {
|
||||
failCallback( {
|
||||
message: "Unable to load TileSource",
|
||||
source: tileSource
|
||||
});
|
||||
return;
|
||||
}
|
||||
var options = $TileSource.prototype.configure.apply( _this, [ tileSource ] );
|
||||
var readySource = new $TileSource( options );
|
||||
successCallback( readySource );
|
||||
}
|
||||
} else {
|
||||
//can assume it's already a tile source implementation
|
||||
successCallback( tileSource );
|
||||
}
|
||||
}, 1 );
|
||||
}
|
||||
|
||||
/**
|
||||
* @function
|
||||
* @private
|
||||
@ -1590,7 +1849,6 @@ function openTileSource( viewer, source ) {
|
||||
_this.close( );
|
||||
}
|
||||
|
||||
_this.canvas.innerHTML = "";
|
||||
THIS[ _this.hash ].prevContainerSize = _getSafeElemSize( _this.container );
|
||||
|
||||
|
||||
@ -1650,7 +1908,8 @@ function openTileSource( viewer, source ) {
|
||||
viewer: _this,
|
||||
source: _this.source,
|
||||
viewport: _this.viewport,
|
||||
element: _this.canvas,
|
||||
element: _this.drawersContainer,
|
||||
opacity: _this.opacity,
|
||||
maxImageCacheCount: _this.maxImageCacheCount,
|
||||
imageLoaderLimit: _this.imageLoaderLimit,
|
||||
minZoomImageRatio: _this.minZoomImageRatio,
|
||||
@ -1664,6 +1923,7 @@ function openTileSource( viewer, source ) {
|
||||
debugMode: _this.debugMode,
|
||||
debugGridColor: _this.debugGridColor
|
||||
});
|
||||
_this.drawers = [_this.drawer];
|
||||
|
||||
// Now that we have a drawer, see if it supports rotate. If not we need to remove the rotate buttons
|
||||
if (!_this.drawer.canRotate()) {
|
||||
@ -2210,8 +2470,8 @@ function updateOnce( viewer ) {
|
||||
}
|
||||
|
||||
if ( animated ) {
|
||||
viewer.drawer.update();
|
||||
drawOverlays( viewer.viewport, viewer.currentOverlays, viewer.canvas );
|
||||
updateDrawers( viewer );
|
||||
drawOverlays( viewer.viewport, viewer.currentOverlays, viewer.overlaysContainer );
|
||||
if( viewer.navigator ){
|
||||
viewer.navigator.update( viewer.viewport );
|
||||
}
|
||||
@ -2225,9 +2485,9 @@ function updateOnce( viewer ) {
|
||||
* @property {?Object} userData - Arbitrary subscriber-defined object.
|
||||
*/
|
||||
viewer.raiseEvent( "animation" );
|
||||
} else if ( THIS[ viewer.hash ].forceRedraw || viewer.drawer.needsUpdate() ) {
|
||||
viewer.drawer.update();
|
||||
drawOverlays( viewer.viewport, viewer.currentOverlays, viewer.canvas );
|
||||
} else if ( THIS[ viewer.hash ].forceRedraw || drawersNeedUpdate( viewer ) ) {
|
||||
updateDrawers( viewer );
|
||||
drawOverlays( viewer.viewport, viewer.currentOverlays, viewer.overlaysContainer );
|
||||
if( viewer.navigator ){
|
||||
viewer.navigator.update( viewer.viewport );
|
||||
}
|
||||
@ -2281,6 +2541,21 @@ function resizeViewportAndRecenter( viewer, containerSize, oldBounds, oldCenter
|
||||
viewport.fitBounds( newBounds, true );
|
||||
}
|
||||
|
||||
function updateDrawers( viewer ) {
|
||||
for (var i = 0; i < viewer.drawers.length; i++ ) {
|
||||
viewer.drawers[i].update();
|
||||
}
|
||||
}
|
||||
|
||||
function drawersNeedUpdate( viewer ) {
|
||||
for (var i = 0; i < viewer.drawers.length; i++ ) {
|
||||
if (viewer.drawers[i].needsUpdate()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Navigation Controls
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -652,7 +652,7 @@ $.Viewport.prototype = /** @lends OpenSeadragon.Viewport.prototype */{
|
||||
throw new Error('Currently only 0, 90, 180, and 270 degrees are supported.');
|
||||
}
|
||||
this.degrees = degrees;
|
||||
this.viewer.drawer.update();
|
||||
this.viewer.forceRedraw();
|
||||
|
||||
return this;
|
||||
},
|
||||
|
BIN
test/data/A.png
Normal file
BIN
test/data/A.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 16 KiB |
BIN
test/data/BBlue.png
Normal file
BIN
test/data/BBlue.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 19 KiB |
BIN
test/data/CCyan.png
Normal file
BIN
test/data/CCyan.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 48 KiB |
BIN
test/data/DDandelion.png
Normal file
BIN
test/data/DDandelion.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 9.5 KiB |
194
test/demo/layers.html
Normal file
194
test/demo/layers.html
Normal file
@ -0,0 +1,194 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>OpenSeadragon Layers 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: 800px;
|
||||
height: 600px;
|
||||
float: left;
|
||||
}
|
||||
|
||||
#availables, #arrows, #left, #updown, #right {
|
||||
float: left;
|
||||
}
|
||||
|
||||
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div>
|
||||
Simple demo page to show an OpenSeadragon viewer with layers.
|
||||
</div>
|
||||
<div id="contentDiv" class="openseadragon1"></div>
|
||||
|
||||
<div>
|
||||
<div id="availables">
|
||||
Available layers<br>
|
||||
<select name="layers-availables" size="4" multiple="multiple">
|
||||
<option>CCyan</option>
|
||||
<option>DDandelion</option>
|
||||
</select>
|
||||
</div>
|
||||
<div id="arrows">
|
||||
<div id="left">
|
||||
<button onclick="left();">⇚ Remove</button>
|
||||
</div>
|
||||
<div id="updown">
|
||||
<div id="up">
|
||||
<button onclick="up();">⇑ Up</button>
|
||||
</div>
|
||||
<div id="down">
|
||||
<button onclick="down();">⇓ Down</button>
|
||||
</div>
|
||||
</div>
|
||||
<div id="right">
|
||||
<button onclick="right();">⇛ Add</button>
|
||||
</div>
|
||||
</div>
|
||||
<div id="used">
|
||||
Used layers<br>
|
||||
<select name="layers-used" size="4" multiple="multiple">
|
||||
<option>A</option>
|
||||
<option>BBlue</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<br><br><br><br>
|
||||
|
||||
<div>
|
||||
Opacity: <br>
|
||||
<label for="AOpacity" >A</label>
|
||||
<input id="AOpacity" type="text" value="0.5"><br>
|
||||
<label for="BBlueOpacity" >BBlue</label>
|
||||
<input id="BBlueOpacity" type="text" value="1"><br>
|
||||
<label for="CCyanOpacity" >CCyan</label>
|
||||
<input id="CCyanOpacity" type="text" value="1"><br>
|
||||
<label for="DDandelion" >DDandelion</label>
|
||||
<input id="DDandelion" type="text" value="1"><br>
|
||||
</div>
|
||||
|
||||
<br><br><br><br>
|
||||
|
||||
<div>
|
||||
<button onclick="rotate();">Rotate</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
function getOpacity( layerName ) {
|
||||
var id = $( "label" ).filter( function( index ) {
|
||||
return layerName === this.innerHTML;
|
||||
} ).attr( "for" );
|
||||
return $( "#" + id ).val();
|
||||
}
|
||||
|
||||
function right() {
|
||||
var added = $( "#availables select option:selected" ).detach();
|
||||
$( "#used select" ).append( added );
|
||||
$.each( added, function( index, value ) {
|
||||
addLayer( value.innerHTML );
|
||||
} );
|
||||
}
|
||||
|
||||
function addLayer( layerName ) {
|
||||
var options = {
|
||||
tileSource: {
|
||||
type: 'legacy-image-pyramid',
|
||||
levels: [ {
|
||||
url: "../data/" + layerName + ".png",
|
||||
width: 1000,
|
||||
height: 1000
|
||||
} ]
|
||||
},
|
||||
opacity: getOpacity( layerName )
|
||||
};
|
||||
var addLayerHandler = function( event ) {
|
||||
if ( event.options === options ) {
|
||||
viewer.removeHandler( "add-layer", addLayerHandler );
|
||||
layers[layerName] = event.drawer;
|
||||
updateOrder();
|
||||
}
|
||||
};
|
||||
viewer.addHandler( "add-layer", addLayerHandler );
|
||||
viewer.addLayer( options );
|
||||
}
|
||||
|
||||
function left() {
|
||||
var removed = $( "#used select option:selected" ).detach();
|
||||
$( "#availables select" ).append( removed );
|
||||
$.each( removed, function( index, value ) {
|
||||
var layer = value.innerHTML;
|
||||
viewer.removeLayer( layers[layer] );
|
||||
delete layers[layer];
|
||||
updateOrder();
|
||||
} );
|
||||
}
|
||||
|
||||
function up() {
|
||||
$.each( $( "#used select option:selected" ), function( index, value ) {
|
||||
$( value ).prev( "option" ).insertAfter( value );
|
||||
} );
|
||||
updateOrder();
|
||||
}
|
||||
|
||||
function down() {
|
||||
$.each( $( "#used select option:selected" ).get().reverse(),
|
||||
function( index, value ) {
|
||||
$( value ).next( "option" ).insertBefore( value );
|
||||
} );
|
||||
updateOrder();
|
||||
}
|
||||
|
||||
function updateOrder() {
|
||||
var nbLayers = viewer.getLayersCount();
|
||||
if ( nbLayers < 2 ) {
|
||||
return;
|
||||
}
|
||||
$.each( $( "#used select option" ), function( index, value ) {
|
||||
var layer = value.innerHTML;
|
||||
viewer.setLayerLevel( layers[layer], nbLayers -1 - index );
|
||||
} );
|
||||
}
|
||||
|
||||
function rotate() {
|
||||
var viewport = viewer.viewport;
|
||||
viewport.setRotation( viewport.getRotation() + 90 );
|
||||
}
|
||||
|
||||
var viewer = OpenSeadragon( {
|
||||
id: "contentDiv",
|
||||
prefixUrl: "../../build/openseadragon/images/",
|
||||
tileSources: "../data/testpattern.dzi",
|
||||
showNavigator: true
|
||||
} );
|
||||
viewer.addHandler( "open", function() {
|
||||
$.each( $( "#used select option" ), function( index, value ) {
|
||||
var layer = value.innerHTML;
|
||||
addLayer( layer );
|
||||
} );
|
||||
} );
|
||||
|
||||
var layers = { };
|
||||
|
||||
$( "input" ).keyup( function( event ) {
|
||||
var elt = event.target;
|
||||
var layerName = $( "label" ).filter( function( index ) {
|
||||
return $( this ).attr( "for" ) === elt.id;
|
||||
} ).html();
|
||||
|
||||
var layer = layers[layerName];
|
||||
if ( layer ) {
|
||||
var opacity = $(elt).val();
|
||||
layer.setOpacity( opacity );
|
||||
}
|
||||
} );
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
278
test/layers.js
Normal file
278
test/layers.js
Normal file
@ -0,0 +1,278 @@
|
||||
/* global module, asyncTest, $, ok, equal, notEqual, start, test, Util, testLog */
|
||||
|
||||
( function() {
|
||||
var viewer;
|
||||
|
||||
module( 'Layers', {
|
||||
setup: function() {
|
||||
$( '<div id="layersexample"></div>' ).appendTo( "#qunit-fixture" );
|
||||
|
||||
testLog.reset();
|
||||
|
||||
viewer = OpenSeadragon( {
|
||||
id: 'layersexample',
|
||||
prefixUrl: '/build/openseadragon/images/',
|
||||
springStiffness: 100 // Faster animation = faster tests
|
||||
});
|
||||
},
|
||||
teardown: function() {
|
||||
if ( viewer && viewer.close ) {
|
||||
viewer.close();
|
||||
}
|
||||
|
||||
viewer = null;
|
||||
$( "#layersexample" ).remove();
|
||||
}
|
||||
} );
|
||||
|
||||
// ----------
|
||||
asyncTest( 'Layers operations', function() {
|
||||
expect( 23 );
|
||||
viewer.addHandler( "open", function( ) {
|
||||
equal( 1, viewer.getLayersCount( ),
|
||||
"One layer should be present after opening." );
|
||||
var options = {
|
||||
tileSource: {
|
||||
type: 'legacy-image-pyramid',
|
||||
levels: [ {
|
||||
url: "data/A.png",
|
||||
width: 1000,
|
||||
height: 1000
|
||||
} ]
|
||||
}
|
||||
};
|
||||
viewer.addLayer( options );
|
||||
viewer.addHandler( "add-layer", function addFirstLayerHandler( event ) {
|
||||
viewer.removeHandler( "add-layer", addFirstLayerHandler );
|
||||
var layer1 = event.drawer;
|
||||
equal( viewer.getLayersCount( ), 2,
|
||||
"2 layers should be present after adding a layer." );
|
||||
equal( options, event.options,
|
||||
"The options should be transmitted via the event." );
|
||||
equal( viewer.getLevelOfLayer( layer1 ), 1,
|
||||
"The first added layer should have a level of 1" );
|
||||
equal( viewer.getLayerAtLevel( 1 ), layer1,
|
||||
"The layer at level 1 should be the first added layer." );
|
||||
|
||||
viewer.addLayer( options );
|
||||
viewer.addHandler( "add-layer", function addSecondLayerHandler( event ) {
|
||||
viewer.removeHandler( "add-layer", addSecondLayerHandler );
|
||||
var layer2 = event.drawer;
|
||||
equal( viewer.getLayersCount( ), 3,
|
||||
"3 layers should be present after adding a second layer." );
|
||||
equal( viewer.getLevelOfLayer( layer2 ), 2,
|
||||
"If not specified, a layer should be added with the highest level." );
|
||||
equal( viewer.getLayerAtLevel( 2 ), layer2,
|
||||
"The layer at level 2 should be the second added layer." );
|
||||
|
||||
viewer.addHandler( "layer-level-changed",
|
||||
function layerLevelChangedHandler( event ) {
|
||||
viewer.removeHandler( "layer-level-changed",
|
||||
layerLevelChangedHandler );
|
||||
equal( event.drawer, layer2,
|
||||
"The layer which changed level should be layer2" );
|
||||
equal( event.previousLevel, 2, "Previous level should be 2." );
|
||||
equal( event.newLevel, 1, "New level should be 1." );
|
||||
});
|
||||
viewer.setLayerLevel( layer2, 1 );
|
||||
equal( viewer.getLevelOfLayer( layer2 ), 1,
|
||||
"Layer2 level should be 1 after setLayerLevel." );
|
||||
equal( viewer.getLevelOfLayer( layer1 ), 2,
|
||||
"Layer1 level should be 2 after setLayerLevel." );
|
||||
equal( viewer.getLayerAtLevel( 1 ), layer2,
|
||||
"The layer at level 1 should be layer2." );
|
||||
equal( viewer.getLayerAtLevel( 2 ), layer1,
|
||||
"The layer at level 2 should be layer1." );
|
||||
|
||||
options.level = 2;
|
||||
options.tileSource.levels[0].url = "data/CCyan.png";
|
||||
options.opacity = 0.5;
|
||||
viewer.addLayer( options );
|
||||
viewer.addHandler( "add-layer", function addThirdLayerHandler( event ) {
|
||||
viewer.removeHandler( "add-layer", addThirdLayerHandler );
|
||||
var layer3 = event.drawer;
|
||||
equal( viewer.getLayersCount( ), 4,
|
||||
"4 layers should be present after adding a third layer." );
|
||||
equal( viewer.getLevelOfLayer( layer3 ), 2,
|
||||
"Layer 3 should be added with level 2." );
|
||||
equal( viewer.getLevelOfLayer( layer2 ), 1,
|
||||
"Layer 2 should stay at level 1." );
|
||||
|
||||
viewer.addHandler( "remove-layer", function removeLayerHandler( event ) {
|
||||
viewer.removeHandler( "remove-layer", removeLayerHandler );
|
||||
|
||||
equal( layer2, event.drawer, "Removed layer should be layer2." );
|
||||
|
||||
equal( viewer.getLevelOfLayer( layer1 ), 2,
|
||||
"Layer 1 should be at level 2." );
|
||||
equal( viewer.getLevelOfLayer( layer2 ), -1,
|
||||
"Layer 2 should be at level -1." );
|
||||
equal( viewer.getLevelOfLayer( layer3 ), 1,
|
||||
"Layer 3 should be at level 1." );
|
||||
|
||||
});
|
||||
viewer.removeLayer( layer2 );
|
||||
|
||||
options.tileSource.levels[0].width = 500;
|
||||
viewer.addHandler( "add-layer-failed", function addLayerFailed( event ) {
|
||||
viewer.removeHandler( "add-layer-failed", addLayerFailed );
|
||||
|
||||
equal( viewer.getLayersCount(), 3 );
|
||||
|
||||
start();
|
||||
});
|
||||
viewer.addLayer( options );
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
viewer.open( '/test/data/testpattern.dzi' );
|
||||
});
|
||||
|
||||
asyncTest( 'Sequences as layers', function() {
|
||||
|
||||
var options = {
|
||||
tileSource: [{
|
||||
type: 'legacy-image-pyramid',
|
||||
levels: [{
|
||||
url: "data/A.png",
|
||||
width: 1000,
|
||||
height: 1000
|
||||
}]
|
||||
}, {
|
||||
type: 'legacy-image-pyramid',
|
||||
levels: [{
|
||||
url: "data/BBlue.png",
|
||||
width: 1000,
|
||||
height: 1000
|
||||
}]
|
||||
}]
|
||||
};
|
||||
|
||||
viewer.addHandler( "open", function openHandler() {
|
||||
viewer.removeHandler( "open", openHandler );
|
||||
|
||||
viewer.addHandler( "add-layer-failed",
|
||||
function addLayerFailedHandler( event ) {
|
||||
viewer.removeHandler( "add-layer-failed", addLayerFailedHandler );
|
||||
equal( event.message, "Sequences can not be added as layers." );
|
||||
equal( event.options, options, "Layer failed event should give the options." );
|
||||
start();
|
||||
} );
|
||||
viewer.addLayer( options );
|
||||
|
||||
});
|
||||
viewer.open( '/test/data/testpattern.dzi' );
|
||||
});
|
||||
|
||||
|
||||
asyncTest( 'Reassign base layer', function() {
|
||||
|
||||
var options = {
|
||||
tileSource: {
|
||||
type: 'legacy-image-pyramid',
|
||||
levels: [{
|
||||
url: "data/A.png",
|
||||
width: 1000,
|
||||
height: 1000
|
||||
}]
|
||||
},
|
||||
level: 0
|
||||
};
|
||||
viewer.addHandler( "open", function openHandler( ) {
|
||||
viewer.removeHandler( "open", openHandler );
|
||||
var testPatternDrawer = viewer.drawer;
|
||||
equal( viewer.drawer, testPatternDrawer, "Viewer.drawer should be set to testPatternDrawer." );
|
||||
viewer.addHandler( "add-layer", function addLayerHandler( event ) {
|
||||
viewer.removeHandler( "add-layer", addLayerHandler );
|
||||
var aDrawer = event.drawer;
|
||||
equal( viewer.drawer, aDrawer, "Viewer.drawer should be set to aDrawer." );
|
||||
viewer.setLayerLevel( aDrawer, 1 );
|
||||
equal( viewer.drawer, testPatternDrawer, "Viewer.drawer should be set back to testPatternDrawer." );
|
||||
|
||||
viewer.removeLayer( viewer.drawer );
|
||||
equal( viewer.drawer, aDrawer, "Viewer.drawer must be reassigned when removing base layer." );
|
||||
|
||||
viewer.removeLayer( viewer.drawer );
|
||||
ok( !viewer.isOpen(), "Viewer should be closed when removing last layer." );
|
||||
|
||||
start();
|
||||
});
|
||||
viewer.addLayer( options );
|
||||
});
|
||||
viewer.open( '/test/data/testpattern.dzi' );
|
||||
});
|
||||
|
||||
asyncTest( 'Layers and sequences', function() {
|
||||
expect( 1 );
|
||||
|
||||
// TODO: Remove workaround when issue #321 is fixed.
|
||||
// https://github.com/openseadragon/openseadragon/issues/321
|
||||
// viewer.open( [{
|
||||
// type: 'legacy-image-pyramid',
|
||||
// levels: [ {
|
||||
// url: "data/A.png",
|
||||
// width: 1000,
|
||||
// height: 1000
|
||||
// }]
|
||||
// },
|
||||
// {
|
||||
// type: 'legacy-image-pyramid',
|
||||
// levels: [ {
|
||||
// url: "data/BBlue.png",
|
||||
// width: 1000,
|
||||
// height: 1000
|
||||
// }]}] );
|
||||
|
||||
viewer.close();
|
||||
viewer = OpenSeadragon({
|
||||
id: 'layersexample',
|
||||
prefixUrl: '/build/openseadragon/images/',
|
||||
springStiffness: 100, // Faster animation = faster tests
|
||||
tileSources: [{
|
||||
type: 'legacy-image-pyramid',
|
||||
levels: [{
|
||||
url: "data/A.png",
|
||||
width: 1000,
|
||||
height: 1000
|
||||
}]
|
||||
},
|
||||
{
|
||||
type: 'legacy-image-pyramid',
|
||||
levels: [{
|
||||
url: "data/BBlue.png",
|
||||
width: 1000,
|
||||
height: 1000
|
||||
}]
|
||||
}]
|
||||
});
|
||||
// End workaround
|
||||
|
||||
var options = {
|
||||
tileSource: {
|
||||
type: 'legacy-image-pyramid',
|
||||
levels: [{
|
||||
url: "data/CCyan.png",
|
||||
width: 1000,
|
||||
height: 1000
|
||||
}]
|
||||
}
|
||||
};
|
||||
|
||||
viewer.addHandler( "open", function openHandler() {
|
||||
viewer.addHandler( "add-layer", function addLayerHandler( event ) {
|
||||
viewer.removeHandler( "add-layer", addLayerHandler );
|
||||
|
||||
var layer = event.drawer;
|
||||
try {
|
||||
viewer.setLayerLevel( layer, 0 );
|
||||
} catch (e) {
|
||||
ok( true );
|
||||
}
|
||||
start();
|
||||
} );
|
||||
viewer.addLayer( options );
|
||||
});
|
||||
|
||||
});
|
||||
})();
|
@ -22,3 +22,8 @@
|
||||
height: 500px;
|
||||
width: 500px;
|
||||
}
|
||||
|
||||
#layersexample {
|
||||
height: 500px;
|
||||
width: 500px;
|
||||
}
|
||||
|
@ -27,6 +27,7 @@
|
||||
<script src="/test/utils.js"></script>
|
||||
<script src="/test/events.js"></script>
|
||||
<script src="/test/units.js"></script>
|
||||
<script src="/test/layers.js"></script>
|
||||
<script src="/test/overlays.js"></script>
|
||||
<script src="/test/rotate.js"></script>
|
||||
</body>
|
||||
|
Loading…
Reference in New Issue
Block a user