From 15c35c93fd458085ae65c995ba56c7ca595aa95a Mon Sep 17 00:00:00 2001 From: thatcher Date: Wed, 23 Jan 2013 23:00:11 -0500 Subject: [PATCH] 0.9.90 adds support for a debug mode and real heterogeneous collection visualizations. straight html div/image support for both features is in process but incomplete --- build.properties | 2 +- build.xml | 8 +- openseadragon.js | 383 +++++++++++-- src/drawer.js | 153 +++++- src/navigator.js | 6 +- src/openseadragon.js | 20 +- src/point.js | 2 +- src/rectangle.js | 8 +- src/tilesourcecollection.js | 111 ++++ src/viewer.js | 79 ++- www/base.html | 18 +- www/developer-debug-mode.html | 39 ++ www/index.html | 11 +- www/tilesource-collection.html | 505 ++++++++++++++++++ ...llections.html => ui-reference-strip.html} | 2 +- 15 files changed, 1234 insertions(+), 113 deletions(-) create mode 100644 src/tilesourcecollection.js create mode 100644 www/developer-debug-mode.html create mode 100644 www/tilesource-collection.html rename www/{ui-collections.html => ui-reference-strip.html} (99%) diff --git a/build.properties b/build.properties index d1195683..54767969 100644 --- a/build.properties +++ b/build.properties @@ -6,7 +6,7 @@ PROJECT: openseadragon BUILD_MAJOR: 0 BUILD_MINOR: 9 -BUILD_ID: 82 +BUILD_ID: 90 BUILD: ${PROJECT}.${BUILD_MAJOR}.${BUILD_MINOR}.${BUILD_ID} VERSION: ${BUILD_MAJOR}.${BUILD_MINOR}.${BUILD_ID} diff --git a/build.xml b/build.xml index 265f9fb6..a4046a25 100644 --- a/build.xml +++ b/build.xml @@ -32,6 +32,7 @@ + @@ -65,14 +66,17 @@ + - + + + @@ -104,6 +108,7 @@ + @@ -113,6 +118,7 @@ + diff --git a/openseadragon.js b/openseadragon.js index b955ac28..2646f1a2 100644 --- a/openseadragon.js +++ b/openseadragon.js @@ -1,5 +1,5 @@ /** - * @version OpenSeadragon 0.9.82 + * @version OpenSeadragon 0.9.90 * * @fileOverview *

@@ -468,7 +468,6 @@ OpenSeadragon = window.OpenSeadragon || function( options ){ tileHost: null, //INTERFACE FEATURES - debugMode: true, animationTime: 1.5, blendTime: 0.1, alwaysBlend: false, @@ -478,6 +477,7 @@ OpenSeadragon = window.OpenSeadragon || function( options ){ wrapVertical: false, panHorizontal: true, panVertical: true, + visibilityRatio: 0.5, springStiffness: 5.0, clickTimeThreshold: 300, @@ -485,19 +485,21 @@ OpenSeadragon = window.OpenSeadragon || function( options ){ zoomPerClick: 2.0, zoomPerScroll: 1.2, zoomPerSecond: 2.0, + showNavigationControl: true, showSequenceControl: true, controlsFadeDelay: 2000, controlsFadeLength: 1500, mouseNavEnabled: true, + preserveViewport: false, + defaultZoomLevel: 0, + showNavigator: true, //promoted to default in 0.9.64 navigatorElement: null, navigatorHeight: null, navigatorWidth: null, navigatorPosition: null, navigatorSizeRatio: 0.2, - preserveViewport: false, - defaultZoomLevel: 0, showReferenceStrip: false, referenceStripScroll: 'horizontal', @@ -508,8 +510,10 @@ OpenSeadragon = window.OpenSeadragon || function( options ){ referenceStripSizeRatio: 0.2, //COLLECTION VISUALIZATION SETTINGS - collectionRows: 3, - collectionScroll: 'horizontal', + collectionRows: 3, //or columns depending on layout + collectionLayout: 'horizontal', //vertical + collectionMode: false, + collectionTileSize: 800, //EVENT RELATED CALLBACKS onPageChange: null, @@ -560,7 +564,11 @@ OpenSeadragon = window.OpenSeadragon || function( options ){ HOVER: '/images/next_hover.png', DOWN: '/images/next_pressed.png' } - } + }, + + //DEVELOPER SETTINGS + debugMode: false, + debugGridColor: '#437AB2' }, @@ -3295,8 +3303,7 @@ $.Control.prototype = { return -1; }; -}( OpenSeadragon )); -(function( $ ){ +}( OpenSeadragon ));(function( $ ){ // dictionary from hash to private properties var THIS = {}, @@ -3391,6 +3398,11 @@ $.Viewer = function( options ) { viewport: null, navigator: null, + //A collection viewport is a seperate viewport used to provide + //simultanious rendering of sets of tiless + collectionViewport: null, + collectionDrawer: null, + //UI image resources //TODO: rename navImages to uiImages navImages: null, @@ -3648,34 +3660,61 @@ $.extend( $.Viewer.prototype, $.EventHandler.prototype, $.ControlDock.prototype, this.canvas.innerHTML = ""; THIS[ this.hash ].prevContainerSize = $.getElementSize( this.container ); - if( source ){ - this.source = source; - } - this.viewport = this.viewport ? this.viewport : new $.Viewport({ - containerSize: THIS[ this.hash ].prevContainerSize, - contentSize: this.source.dimensions, - springStiffness: this.springStiffness, - animationTime: this.animationTime, - minZoomImageRatio: this.minZoomImageRatio, - maxZoomPixelRatio: this.maxZoomPixelRatio, - visibilityRatio: this.visibilityRatio, - wrapHorizontal: this.wrapHorizontal, - wrapVertical: this.wrapVertical - }); + if( this.collectionMode ){ + this.source = new $.TileSourceCollection({ + rows: this.collectionRows, + layout: this.collectionLayout, + tileSize: this.collectionTileSize, + tileSources: this.tileSources, + tileMargin: this.collectionTileMargin + }); + this.viewport = this.viewport ? this.viewport : new $.Viewport({ + collectionMode: true, + collectionTileSource: this.source, + containerSize: THIS[ this.hash ].prevContainerSize, + contentSize: this.source.dimensions, + springStiffness: this.springStiffness, + animationTime: this.animationTime, + minZoomImageRatio: 1, + maxZoomPixelRatio: 1 + }); + }else{ + if( source ){ + this.source = source; + } + this.viewport = this.viewport ? this.viewport : new $.Viewport({ + containerSize: THIS[ this.hash ].prevContainerSize, + contentSize: this.source.dimensions, + springStiffness: this.springStiffness, + animationTime: this.animationTime, + minZoomImageRatio: this.minZoomImageRatio, + maxZoomPixelRatio: this.maxZoomPixelRatio, + visibilityRatio: this.visibilityRatio, + wrapHorizontal: this.wrapHorizontal, + wrapVertical: this.wrapVertical + }); + } if( this.preserveVewport ){ this.viewport.resetContentSize( this.source.dimensions ); - } else if( this.defaultZoomLevel ){ - - this.viewport.zoomTo( - this.defaultZoomLevel, - this.viewport.getCenter(), - true - ); + } else if( this.defaultZoomLevel || this.collectionMode ){ + if( this.collectionMode ){ + /*this.viewport.zoomTo( + ( this.viewport.getMaxZoom() + this.viewport.getMaxZoom())/ 2, + this.viewport.getCenter(), + true + );*/ + }else{ + this.viewport.zoomTo( + this.defaultZoomLevel, + this.viewport.getCenter(), + true + ); + } } this.drawer = new $.Drawer({ @@ -3691,7 +3730,9 @@ $.extend( $.Viewer.prototype, $.EventHandler.prototype, $.ControlDock.prototype, immediateRender: this.immediateRender, blendTime: this.blendTime, alwaysBlend: this.alwaysBlend, - minPixelRatio: this.minPixelRatio + minPixelRatio: this.minPixelRatio, + debugMode: this.debugMode, + debugGridColor: this.debugGridColor }); //Instantiate a navigator if configured @@ -4729,7 +4770,7 @@ $.Navigator = function( options ){ style.overflow = 'hidden'; style.border = '2px solid #900'; //TODO: IE doesnt like this property being set - try{ style.outline = '2px auto #900'; }catch(e){/*ignore*/} + //try{ style.outline = '2px auto #909'; }catch(e){/*ignore*/} style.background = 'transparent'; style.float = 'left'; //Webkit style.cssFloat = 'left'; //Firefox @@ -4763,7 +4804,7 @@ $.Navigator = function( options ){ _this.viewer.setControlsEnabled( true ); (function( style ){ style.border = '2px solid #437AB2'; - style.outline = '2px auto #437AB2'; + //style.outline = '2px auto #437AB2'; }( this.element.style )); }, @@ -4771,7 +4812,7 @@ $.Navigator = function( options ){ _this.viewer.setControlsEnabled( false ); (function( style ){ style.border = '2px solid #900'; - style.outline = '2px auto #900'; + //style.outline = '2px auto #900'; }( this.element.style )); }, keyHandler: function(tracker, keyCode, shiftKey){ @@ -5177,7 +5218,7 @@ $.Point.prototype = { * vector components */ toString: function() { - return "(" + this.x + "," + this.y + ")"; + return "(" + Math.round(this.x) + "," + Math.round(this.y) + ")"; } }; @@ -6180,6 +6221,117 @@ function configureFromObject( tileSource, configuration ){ }; +}( OpenSeadragon )); + +(function( $ ){ + +/** + * @class + * @extends OpenSeadragon.TileSourceCollection + */ +$.TileSourceCollection = function( tileSize, tileSources, rows, layout ) { + + + if( $.isPlainObject( tileSize ) ){ + options = tileSize; + }else{ + options = { + tileSize: arguments[ 0 ], + tileSources: arguments[ 1 ], + rows: arguments[ 2 ], + layout: arguments[ 3 ] + }; + } + + if( !options.layout ){ + options.layout = 'horizontal'; + } + + var minLevel = 0, + levelSize = 1.0, + tilesPerRow = Math.ceil( options.tileSources.length / options.rows ), + longSide = tilesPerRow >= options.rows ? + tilesPerRow : + options.rows + + if( 'horizontal' == options.layout ){ + options.width = ( options.tileSize ) * tilesPerRow; + options.height = ( options.tileSize ) * options.rows; + } else { + options.height = ( options.tileSize + ( options.tileMargin * 2 ) ) * tilesPerRow; + options.width = ( options.tileSize + ( options.tileMargin * 2 ) ) * options.rows; + } + + options.tileOverlap = -options.tileMargin; + options.tilesPerRow = tilesPerRow; + + //Set min level to avoid loading sublevels since collection is a + //different kind of abstraction + + while( levelSize < ( options.tileSize ) * longSide ){ + //$.console.log( '%s levelSize %s minLevel %s', options.tileSize * longSide, levelSize, minLevel ); + levelSize = levelSize * 2.0; + minLevel++; + } + options.minLevel = minLevel; + + //for( var name in options ){ + // $.console.log( 'Collection %s %s', name, options[ name ] ); + //} + + $.TileSource.apply( this, [ options ] ); + +}; + +$.extend( $.TileSourceCollection.prototype, $.TileSource.prototype, { + + /** + * @function + * @param {Number} level + * @param {Number} x + * @param {Number} y + */ + getTileBounds: function( level, x, y ) { + var dimensionsScaled = this.dimensions.times( this.getLevelScale( level ) ), + px = this.tileSize * x - this.tileOverlap, + py = this.tileSize * y - this.tileOverlap, + sx = this.tileSize + 1 * this.tileOverlap, + sy = this.tileSize + 1 * this.tileOverlap, + scale = 1.0 / dimensionsScaled.x; + + sx = Math.min( sx, dimensionsScaled.x - px ); + sy = Math.min( sy, dimensionsScaled.y - py ); + + return new $.Rect( px * scale, py * scale, sx * scale, sy * scale ); + }, + + /** + * + * @function + * @name OpenSeadragon.TileSourceCollection.prototype.configure + */ + configure: function( data, url ){ + return + }, + + + /** + * @function + * @name OpenSeadragon.TileSourceCollection.prototype.getTileUrl + * @param {Number} level + * @param {Number} x + * @param {Number} y + */ + getTileUrl: function( level, x, y ) { + //$.console.log([ level, '/', x, '_', y ].join( '' )); + return null; + } + + + +}); + + }( OpenSeadragon )); @@ -6748,10 +6900,10 @@ $.Rect.prototype = { */ toString: function() { return "[" + - this.x + "," + - this.y + "," + - this.width + "x" + - this.height + + Math.round(this.x*100) + "," + + Math.round(this.y*100) + "," + + Math.round(this.width*100) + "x" + + Math.round(this.height*100) + "]"; } }; @@ -7822,7 +7974,8 @@ $.Drawer = function( options ) { updateAgain: true, //internal state / configurable settings - overlays: [], + overlays: [], + collectionOverlays: {}, //configurable settings maxImageCacheCount: $.DEFAULT_SETTINGS.maxImageCacheCount, @@ -7833,7 +7986,8 @@ $.Drawer = function( options ) { immediateRender: $.DEFAULT_SETTINGS.immediateRender, blendTime: $.DEFAULT_SETTINGS.blendTime, alwaysBlend: $.DEFAULT_SETTINGS.alwaysBlend, - minPixelRatio: $.DEFAULT_SETTINGS.minPixelRatio + minPixelRatio: $.DEFAULT_SETTINGS.minPixelRatio, + debugMode: $.DEFAULT_SETTINGS.debugMode }, options ); @@ -7879,7 +8033,7 @@ $.Drawer = function( options ) { }( this, this.overlays[ i ] )); } else if ( $.isFunction( this.overlays[ i ] ) ){ - + //TODO } } @@ -8687,23 +8841,152 @@ function drawOverlay( viewport, overlay, container ){ function drawTiles( drawer, lastDrawn ){ var i, - tile; + tile, + tileKey, + viewer, + viewport, + position, + tileSource, + collectionTileSource; for ( i = lastDrawn.length - 1; i >= 0; i-- ) { tile = lastDrawn[ i ]; - //TODO: get rid of this if by determining the tile draw method once up - // front and defining the appropriate 'draw' function - if ( USE_CANVAS ) { - tile.drawCanvas( drawer.context ); - } else { - tile.drawHTML( drawer.canvas ); + if( drawer.debugMode ){ + try{ + drawDebugInfo( drawer, tile, lastDrawn.length, i ); + }catch(e){ + $.console.error(e); + } } + + //We dont actually 'draw' a collection tile, rather its used to house + //an overlay which does the drawing in its own viewport + if( drawer.viewport.collectionMode ){ + tileKey = tile.x + '/' + tile.y; + viewport = drawer.viewport; + collectionTileSource = viewport.collectionTileSource; + if( !drawer.collectionOverlays[ tileKey ] ){ + position = collectionTileSource.layout == 'horizontal' ? + tile.x + ( tile.y * collectionTileSource.tilesPerRow ) : + tile.y + ( tile.x * collectionTileSource.tilesPerRow ), + tileSource = position < collectionTileSource.tileSources.length ? + collectionTileSource.tileSources[ position ] : + null; + //$.console.log("Rendering collection tile [%s] %s", position, tileKey); + if( tileSource ){ + drawer.collectionOverlays[ tileKey ] = viewer = new $.Viewer({ + element: $.makeNeutralElement( "div" ), + mouseNavEnabled: false, + showNavigator: false, + showSequenceControl: false, + showNavigationControl: false, + //visibilityRatio: 1, + //debugMode: true, + //debugGridColor: 'red', + tileSources: [ + tileSource + ] + }); + + (function(style){ + style['-webkit-box-reflect'] = + 'below 0px -webkit-gradient('+ + 'linear,left '+ + 'top,left '+ + 'bottom,from(transparent),color-stop(60%,transparent),to(rgba(255,255,255,0.4))'+ + ')'; + style['border'] = '1px solid rgba(255,255,255,0.2)'; + //style['borderRight'] = '1px solid #fff'; + }(viewer.element.style)); - tile.beingDrawn = true; + drawer.addOverlay( + viewer.element, + tile.bounds + ); + } + + }else{ + viewer = drawer.collectionOverlays[ tileKey ]; + if( viewer.viewport ){ + viewer.viewport.resize( tile.size, true ); + viewer.viewport.goHome( true ); + } + } + + } else { + + if ( USE_CANVAS ) { + tile.drawCanvas( drawer.context ); + } else { + tile.drawHTML( drawer.canvas ); + } + + tile.beingDrawn = true; + } } }; + +function drawDebugInfo( drawer, tile, count, i ){ + + if ( USE_CANVAS ) { + drawer.context.lineWidth = 2; + drawer.context.font = 'small-caps bold 12px ariel'; + drawer.context.strokeStyle = drawer.debugGridColor; + drawer.context.fillStyle = drawer.debugGridColor; + drawer.context.strokeRect( + tile.position.x, + tile.position.y, + tile.size.x, + tile.size.y + ); + if( tile.x == 0 && tile.y == 0 ){ + drawer.context.fillText( + "Zoom: " + drawer.viewport.getZoom(), + tile.position.x, + tile.position.y - 30 + ); + drawer.context.fillText( + "Pan: " + drawer.viewport.getBounds().toString(), + tile.position.x, + tile.position.y - 20 + ); + } + drawer.context.fillText( + "Level: " + tile.level, + tile.position.x + 10, + tile.position.y + 20 + ); + drawer.context.fillText( + "Column: " + tile.x, + tile.position.x + 10, + tile.position.y + 30 + ); + drawer.context.fillText( + "Row: " + tile.y, + tile.position.x + 10, + tile.position.y + 40 + ); + drawer.context.fillText( + "Order: " + i + " of " + count, + tile.position.x + 10, + tile.position.y + 50 + ); + drawer.context.fillText( + "Size: " + tile.size.toString(), + tile.position.x + 10, + tile.position.y + 60 + ); + drawer.context.fillText( + "Position: " + tile.position.toString(), + tile.position.x + 10, + tile.position.y + 70 + ); + } +}; + + }( OpenSeadragon )); (function( $ ){ diff --git a/src/drawer.js b/src/drawer.js index 1cc5082a..68834912 100644 --- a/src/drawer.js +++ b/src/drawer.js @@ -72,7 +72,8 @@ $.Drawer = function( options ) { updateAgain: true, //internal state / configurable settings - overlays: [], + overlays: [], + collectionOverlays: {}, //configurable settings maxImageCacheCount: $.DEFAULT_SETTINGS.maxImageCacheCount, @@ -83,7 +84,8 @@ $.Drawer = function( options ) { immediateRender: $.DEFAULT_SETTINGS.immediateRender, blendTime: $.DEFAULT_SETTINGS.blendTime, alwaysBlend: $.DEFAULT_SETTINGS.alwaysBlend, - minPixelRatio: $.DEFAULT_SETTINGS.minPixelRatio + minPixelRatio: $.DEFAULT_SETTINGS.minPixelRatio, + debugMode: $.DEFAULT_SETTINGS.debugMode }, options ); @@ -129,7 +131,7 @@ $.Drawer = function( options ) { }( this, this.overlays[ i ] )); } else if ( $.isFunction( this.overlays[ i ] ) ){ - + //TODO } } @@ -937,21 +939,150 @@ function drawOverlay( viewport, overlay, container ){ function drawTiles( drawer, lastDrawn ){ var i, - tile; + tile, + tileKey, + viewer, + viewport, + position, + tileSource, + collectionTileSource; for ( i = lastDrawn.length - 1; i >= 0; i-- ) { tile = lastDrawn[ i ]; - //TODO: get rid of this if by determining the tile draw method once up - // front and defining the appropriate 'draw' function - if ( USE_CANVAS ) { - tile.drawCanvas( drawer.context ); - } else { - tile.drawHTML( drawer.canvas ); + if( drawer.debugMode ){ + try{ + drawDebugInfo( drawer, tile, lastDrawn.length, i ); + }catch(e){ + $.console.error(e); + } } + + //We dont actually 'draw' a collection tile, rather its used to house + //an overlay which does the drawing in its own viewport + if( drawer.viewport.collectionMode ){ + tileKey = tile.x + '/' + tile.y; + viewport = drawer.viewport; + collectionTileSource = viewport.collectionTileSource; + if( !drawer.collectionOverlays[ tileKey ] ){ + position = collectionTileSource.layout == 'horizontal' ? + tile.x + ( tile.y * collectionTileSource.tilesPerRow ) : + tile.y + ( tile.x * collectionTileSource.tilesPerRow ), + tileSource = position < collectionTileSource.tileSources.length ? + collectionTileSource.tileSources[ position ] : + null; + //$.console.log("Rendering collection tile [%s] %s", position, tileKey); + if( tileSource ){ + drawer.collectionOverlays[ tileKey ] = viewer = new $.Viewer({ + element: $.makeNeutralElement( "div" ), + mouseNavEnabled: false, + showNavigator: false, + showSequenceControl: false, + showNavigationControl: false, + //visibilityRatio: 1, + //debugMode: true, + //debugGridColor: 'red', + tileSources: [ + tileSource + ] + }); + + (function(style){ + style['-webkit-box-reflect'] = + 'below 0px -webkit-gradient('+ + 'linear,left '+ + 'top,left '+ + 'bottom,from(transparent),color-stop(60%,transparent),to(rgba(255,255,255,0.4))'+ + ')'; + style['border'] = '1px solid rgba(255,255,255,0.2)'; + //style['borderRight'] = '1px solid #fff'; + }(viewer.element.style)); - tile.beingDrawn = true; + drawer.addOverlay( + viewer.element, + tile.bounds + ); + } + + }else{ + viewer = drawer.collectionOverlays[ tileKey ]; + if( viewer.viewport ){ + viewer.viewport.resize( tile.size, true ); + viewer.viewport.goHome( true ); + } + } + + } else { + + if ( USE_CANVAS ) { + tile.drawCanvas( drawer.context ); + } else { + tile.drawHTML( drawer.canvas ); + } + + tile.beingDrawn = true; + } } }; + +function drawDebugInfo( drawer, tile, count, i ){ + + if ( USE_CANVAS ) { + drawer.context.lineWidth = 2; + drawer.context.font = 'small-caps bold 12px ariel'; + drawer.context.strokeStyle = drawer.debugGridColor; + drawer.context.fillStyle = drawer.debugGridColor; + drawer.context.strokeRect( + tile.position.x, + tile.position.y, + tile.size.x, + tile.size.y + ); + if( tile.x == 0 && tile.y == 0 ){ + drawer.context.fillText( + "Zoom: " + drawer.viewport.getZoom(), + tile.position.x, + tile.position.y - 30 + ); + drawer.context.fillText( + "Pan: " + drawer.viewport.getBounds().toString(), + tile.position.x, + tile.position.y - 20 + ); + } + drawer.context.fillText( + "Level: " + tile.level, + tile.position.x + 10, + tile.position.y + 20 + ); + drawer.context.fillText( + "Column: " + tile.x, + tile.position.x + 10, + tile.position.y + 30 + ); + drawer.context.fillText( + "Row: " + tile.y, + tile.position.x + 10, + tile.position.y + 40 + ); + drawer.context.fillText( + "Order: " + i + " of " + count, + tile.position.x + 10, + tile.position.y + 50 + ); + drawer.context.fillText( + "Size: " + tile.size.toString(), + tile.position.x + 10, + tile.position.y + 60 + ); + drawer.context.fillText( + "Position: " + tile.position.toString(), + tile.position.x + 10, + tile.position.y + 70 + ); + } +}; + + }( OpenSeadragon )); diff --git a/src/navigator.js b/src/navigator.js index 17e835cb..93729e0b 100644 --- a/src/navigator.js +++ b/src/navigator.js @@ -65,7 +65,7 @@ $.Navigator = function( options ){ style.overflow = 'hidden'; style.border = '2px solid #900'; //TODO: IE doesnt like this property being set - try{ style.outline = '2px auto #900'; }catch(e){/*ignore*/} + //try{ style.outline = '2px auto #909'; }catch(e){/*ignore*/} style.background = 'transparent'; style.float = 'left'; //Webkit style.cssFloat = 'left'; //Firefox @@ -99,7 +99,7 @@ $.Navigator = function( options ){ _this.viewer.setControlsEnabled( true ); (function( style ){ style.border = '2px solid #437AB2'; - style.outline = '2px auto #437AB2'; + //style.outline = '2px auto #437AB2'; }( this.element.style )); }, @@ -107,7 +107,7 @@ $.Navigator = function( options ){ _this.viewer.setControlsEnabled( false ); (function( style ){ style.border = '2px solid #900'; - style.outline = '2px auto #900'; + //style.outline = '2px auto #900'; }( this.element.style )); }, keyHandler: function(tracker, keyCode, shiftKey){ diff --git a/src/openseadragon.js b/src/openseadragon.js index b32412f0..3f92af19 100644 --- a/src/openseadragon.js +++ b/src/openseadragon.js @@ -468,7 +468,6 @@ OpenSeadragon = window.OpenSeadragon || function( options ){ tileHost: null, //INTERFACE FEATURES - debugMode: true, animationTime: 1.5, blendTime: 0.1, alwaysBlend: false, @@ -478,6 +477,7 @@ OpenSeadragon = window.OpenSeadragon || function( options ){ wrapVertical: false, panHorizontal: true, panVertical: true, + visibilityRatio: 0.5, springStiffness: 5.0, clickTimeThreshold: 300, @@ -485,19 +485,21 @@ OpenSeadragon = window.OpenSeadragon || function( options ){ zoomPerClick: 2.0, zoomPerScroll: 1.2, zoomPerSecond: 2.0, + showNavigationControl: true, showSequenceControl: true, controlsFadeDelay: 2000, controlsFadeLength: 1500, mouseNavEnabled: true, + preserveViewport: false, + defaultZoomLevel: 0, + showNavigator: true, //promoted to default in 0.9.64 navigatorElement: null, navigatorHeight: null, navigatorWidth: null, navigatorPosition: null, navigatorSizeRatio: 0.2, - preserveViewport: false, - defaultZoomLevel: 0, showReferenceStrip: false, referenceStripScroll: 'horizontal', @@ -508,8 +510,10 @@ OpenSeadragon = window.OpenSeadragon || function( options ){ referenceStripSizeRatio: 0.2, //COLLECTION VISUALIZATION SETTINGS - collectionRows: 3, - collectionScroll: 'horizontal', + collectionRows: 3, //or columns depending on layout + collectionLayout: 'horizontal', //vertical + collectionMode: false, + collectionTileSize: 800, //EVENT RELATED CALLBACKS onPageChange: null, @@ -560,7 +564,11 @@ OpenSeadragon = window.OpenSeadragon || function( options ){ HOVER: '/images/next_hover.png', DOWN: '/images/next_pressed.png' } - } + }, + + //DEVELOPER SETTINGS + debugMode: false, + debugGridColor: '#437AB2' }, diff --git a/src/point.js b/src/point.js index 6f3e5ccd..7dbef722 100644 --- a/src/point.js +++ b/src/point.js @@ -135,7 +135,7 @@ $.Point.prototype = { * vector components */ toString: function() { - return "(" + this.x + "," + this.y + ")"; + return "(" + Math.round(this.x) + "," + Math.round(this.y) + ")"; } }; diff --git a/src/rectangle.js b/src/rectangle.js index e4b07866..0df617a6 100644 --- a/src/rectangle.js +++ b/src/rectangle.js @@ -105,10 +105,10 @@ $.Rect.prototype = { */ toString: function() { return "[" + - this.x + "," + - this.y + "," + - this.width + "x" + - this.height + + Math.round(this.x*100) + "," + + Math.round(this.y*100) + "," + + Math.round(this.width*100) + "x" + + Math.round(this.height*100) + "]"; } }; diff --git a/src/tilesourcecollection.js b/src/tilesourcecollection.js new file mode 100644 index 00000000..def1e571 --- /dev/null +++ b/src/tilesourcecollection.js @@ -0,0 +1,111 @@ + +(function( $ ){ + +/** + * @class + * @extends OpenSeadragon.TileSourceCollection + */ +$.TileSourceCollection = function( tileSize, tileSources, rows, layout ) { + + + if( $.isPlainObject( tileSize ) ){ + options = tileSize; + }else{ + options = { + tileSize: arguments[ 0 ], + tileSources: arguments[ 1 ], + rows: arguments[ 2 ], + layout: arguments[ 3 ] + }; + } + + if( !options.layout ){ + options.layout = 'horizontal'; + } + + var minLevel = 0, + levelSize = 1.0, + tilesPerRow = Math.ceil( options.tileSources.length / options.rows ), + longSide = tilesPerRow >= options.rows ? + tilesPerRow : + options.rows + + if( 'horizontal' == options.layout ){ + options.width = ( options.tileSize ) * tilesPerRow; + options.height = ( options.tileSize ) * options.rows; + } else { + options.height = ( options.tileSize + ( options.tileMargin * 2 ) ) * tilesPerRow; + options.width = ( options.tileSize + ( options.tileMargin * 2 ) ) * options.rows; + } + + options.tileOverlap = -options.tileMargin; + options.tilesPerRow = tilesPerRow; + + //Set min level to avoid loading sublevels since collection is a + //different kind of abstraction + + while( levelSize < ( options.tileSize ) * longSide ){ + //$.console.log( '%s levelSize %s minLevel %s', options.tileSize * longSide, levelSize, minLevel ); + levelSize = levelSize * 2.0; + minLevel++; + } + options.minLevel = minLevel; + + //for( var name in options ){ + // $.console.log( 'Collection %s %s', name, options[ name ] ); + //} + + $.TileSource.apply( this, [ options ] ); + +}; + +$.extend( $.TileSourceCollection.prototype, $.TileSource.prototype, { + + /** + * @function + * @param {Number} level + * @param {Number} x + * @param {Number} y + */ + getTileBounds: function( level, x, y ) { + var dimensionsScaled = this.dimensions.times( this.getLevelScale( level ) ), + px = this.tileSize * x - this.tileOverlap, + py = this.tileSize * y - this.tileOverlap, + sx = this.tileSize + 1 * this.tileOverlap, + sy = this.tileSize + 1 * this.tileOverlap, + scale = 1.0 / dimensionsScaled.x; + + sx = Math.min( sx, dimensionsScaled.x - px ); + sy = Math.min( sy, dimensionsScaled.y - py ); + + return new $.Rect( px * scale, py * scale, sx * scale, sy * scale ); + }, + + /** + * + * @function + * @name OpenSeadragon.TileSourceCollection.prototype.configure + */ + configure: function( data, url ){ + return + }, + + + /** + * @function + * @name OpenSeadragon.TileSourceCollection.prototype.getTileUrl + * @param {Number} level + * @param {Number} x + * @param {Number} y + */ + getTileUrl: function( level, x, y ) { + //$.console.log([ level, '/', x, '_', y ].join( '' )); + return null; + } + + + +}); + + +}( OpenSeadragon )); diff --git a/src/viewer.js b/src/viewer.js index f2664023..a0120ce3 100644 --- a/src/viewer.js +++ b/src/viewer.js @@ -1,4 +1,3 @@ - (function( $ ){ // dictionary from hash to private properties @@ -94,6 +93,11 @@ $.Viewer = function( options ) { viewport: null, navigator: null, + //A collection viewport is a seperate viewport used to provide + //simultanious rendering of sets of tiless + collectionViewport: null, + collectionDrawer: null, + //UI image resources //TODO: rename navImages to uiImages navImages: null, @@ -351,34 +355,61 @@ $.extend( $.Viewer.prototype, $.EventHandler.prototype, $.ControlDock.prototype, this.canvas.innerHTML = ""; THIS[ this.hash ].prevContainerSize = $.getElementSize( this.container ); - if( source ){ - this.source = source; - } - this.viewport = this.viewport ? this.viewport : new $.Viewport({ - containerSize: THIS[ this.hash ].prevContainerSize, - contentSize: this.source.dimensions, - springStiffness: this.springStiffness, - animationTime: this.animationTime, - minZoomImageRatio: this.minZoomImageRatio, - maxZoomPixelRatio: this.maxZoomPixelRatio, - visibilityRatio: this.visibilityRatio, - wrapHorizontal: this.wrapHorizontal, - wrapVertical: this.wrapVertical - }); + if( this.collectionMode ){ + this.source = new $.TileSourceCollection({ + rows: this.collectionRows, + layout: this.collectionLayout, + tileSize: this.collectionTileSize, + tileSources: this.tileSources, + tileMargin: this.collectionTileMargin + }); + this.viewport = this.viewport ? this.viewport : new $.Viewport({ + collectionMode: true, + collectionTileSource: this.source, + containerSize: THIS[ this.hash ].prevContainerSize, + contentSize: this.source.dimensions, + springStiffness: this.springStiffness, + animationTime: this.animationTime, + minZoomImageRatio: 1, + maxZoomPixelRatio: 1 + }); + }else{ + if( source ){ + this.source = source; + } + this.viewport = this.viewport ? this.viewport : new $.Viewport({ + containerSize: THIS[ this.hash ].prevContainerSize, + contentSize: this.source.dimensions, + springStiffness: this.springStiffness, + animationTime: this.animationTime, + minZoomImageRatio: this.minZoomImageRatio, + maxZoomPixelRatio: this.maxZoomPixelRatio, + visibilityRatio: this.visibilityRatio, + wrapHorizontal: this.wrapHorizontal, + wrapVertical: this.wrapVertical + }); + } if( this.preserveVewport ){ this.viewport.resetContentSize( this.source.dimensions ); - } else if( this.defaultZoomLevel ){ - - this.viewport.zoomTo( - this.defaultZoomLevel, - this.viewport.getCenter(), - true - ); + } else if( this.defaultZoomLevel || this.collectionMode ){ + if( this.collectionMode ){ + /*this.viewport.zoomTo( + ( this.viewport.getMaxZoom() + this.viewport.getMaxZoom())/ 2, + this.viewport.getCenter(), + true + );*/ + }else{ + this.viewport.zoomTo( + this.defaultZoomLevel, + this.viewport.getCenter(), + true + ); + } } this.drawer = new $.Drawer({ @@ -394,7 +425,9 @@ $.extend( $.Viewer.prototype, $.EventHandler.prototype, $.ControlDock.prototype, immediateRender: this.immediateRender, blendTime: this.blendTime, alwaysBlend: this.alwaysBlend, - minPixelRatio: this.minPixelRatio + minPixelRatio: this.minPixelRatio, + debugMode: this.debugMode, + debugGridColor: this.debugGridColor }); //Instantiate a navigator if configured diff --git a/www/base.html b/www/base.html index 902c84f4..3932b542 100644 --- a/www/base.html +++ b/www/base.html @@ -3,7 +3,7 @@ - @TITLE@ OpenSeadragon + @TITLE@ OpenSeadragon @VERSION@ Image Sequence -
  • +
  • Image Reference Strip
  • + + +
  • +

    Developer Tools

    +

    + These settings can be useful for developers who are trying + to add features to OpenSeadragon or when troubleshooting. +

    + +
  • diff --git a/www/developer-debug-mode.html b/www/developer-debug-mode.html new file mode 100644 index 00000000..f18634dc --- /dev/null +++ b/www/developer-debug-mode.html @@ -0,0 +1,39 @@ +

    developer: debug mode

    + +
    + Enabling developer mode provides some in-context information + about the tiles being drawn in a given viewport.

    + Currently this is only implemented for browsers supporting + HTML Canvas. +
    + +
    +
    + Seadragon in debug mode. + +
    +
    +
    + + + +

    +The relevant configuration options are shown below. +

    + +
    +    OpenSeadragon({
    +        ...
    +        debugMode:  true,
    +        ...
    +    });
    +
    \ No newline at end of file diff --git a/www/index.html b/www/index.html index e27eb0cd..52a39bdc 100644 --- a/www/index.html +++ b/www/index.html @@ -19,15 +19,6 @@ OpenSeadragon({ id: "contentDiv", prefixUrl: "/openseadragon/", - tileSources: "/openseadragon/examples/images/highsmith/highsmith.js"/*, - wrapVertical: true, - wrapHorizontal: true, - visibilityRatio: 0, - minPixelRatio: 1, - immediateRender: true, - minZoomImageRatio: 1, - maxZoomPixelRatio: 1, - showNavigationControl: false - */ + tileSources: "/openseadragon/examples/images/highsmith/highsmith.js" }); \ No newline at end of file diff --git a/www/tilesource-collection.html b/www/tilesource-collection.html new file mode 100644 index 00000000..aec4bb59 --- /dev/null +++ b/www/tilesource-collection.html @@ -0,0 +1,505 @@ +

    + example: tilesource-collection *NOTE* UNDER DEVELOPMENT +

    +

    + The image collection is a major hurdle for OpenSeadragon. It allows arbitrarily + large sets of tile sources, of mixed types, to be used to easily visualize the + group as 'wall' or 'grid'. Many core features are available for preview now, though + they may change soon. Many additional features are under development. +

    +

    + KNOWN ISSUE:
    + This implementation does not support plain html rendering techniques, eg canvas + is required for smooth, regular rendering. The plain html image rendering support, + for IE and small mobile devices should be done soon. +

    + +
    +

    A basic single row tile source collection.

    +

    + Just a simple row of tile sources visualized as a collection. +

    +
    +
    +
    + One row, mixed tile sources.. +
    +
    +
    +

    + No doubt this makes OpenSeadragon into a whole new platform for deepzoom + image visualization. +

    +
    +OpenSeadragon({
    +    ...
    +    collectionMode:     true,
    +    collectionRows:     1, 
    +    collectionTileSize: 1024,
    +    collectionTileMargin: 256,
    +    ...
    +});
    +
    + + diff --git a/www/ui-collections.html b/www/ui-reference-strip.html similarity index 99% rename from www/ui-collections.html rename to www/ui-reference-strip.html index d656e911..b73540a9 100644 --- a/www/ui-collections.html +++ b/www/ui-reference-strip.html @@ -1,4 +1,4 @@ -

    example: tilesource collections

    +

    example: tilesource reference strip