Merge pull request #585 from openseadragon/m2

M2 demo
This commit is contained in:
Ian Gilman 2015-02-04 10:26:48 -08:00
commit 425d78ddb4
11 changed files with 915 additions and 27 deletions

View File

@ -39,7 +39,14 @@ OPENSEADRAGON CHANGELOG
* Rect and Point toString() functions are now consistent: rounding values to nearest hundredth * Rect and Point toString() functions are now consistent: rounding values to nearest hundredth
* Overlays appear in the DOM immediately on open or addOverlay (#507) * Overlays appear in the DOM immediately on open or addOverlay (#507)
* imageLoaderLimit now works (#544) * imageLoaderLimit now works (#544)
* Turning off scrollToZoom in gestureSettings now allows scroll events to propagate
* You can now set a minZoomLevel that's greater than the home zoom level
* Added union() to OpenSeadragon.Rect
* Fixed an error in fitBounds if the new and old bounds were extremely close in size
* Added ajaxWithCredentials option (#543) * Added ajaxWithCredentials option (#543)
* Added viewport-change event for after the viewport changes but before it's drawn
* A spring's current value is now updated immediately on reset (#524)
* Fixed an error in fitBounds that occurred sometimes with immediately = true
* Added support for HDPI (retina) displays (#583) * Added support for HDPI (retina) displays (#583)
1.2.2: (in progress) 1.2.2: (in progress)

View File

@ -201,6 +201,21 @@ $.Rect.prototype = /** @lends OpenSeadragon.Rect.prototype */{
); );
}, },
/**
* Returns the smallest rectangle that will contain this and the given rectangle.
* @param {OpenSeadragon.Rect} rect
* @return {OpenSeadragon.Rect} The new rectangle.
*/
// ----------
union: function(rect) {
var left = Math.min(this.x, rect.x);
var top = Math.min(this.y, rect.y);
var right = Math.max(this.x + this.width, rect.x + rect.width);
var bottom = Math.max(this.y + this.height, rect.y + rect.height);
return new OpenSeadragon.Rect(left, top, right - left, bottom - top);
},
/** /**
* Rotates a rectangle around a point. Currently only 90, 180, and 270 * Rotates a rectangle around a point. Currently only 90, 180, and 270
* degrees are supported. * degrees are supported.

View File

@ -117,10 +117,8 @@ $.Spring.prototype = /** @lends OpenSeadragon.Spring.prototype */{
* @param {Number} target * @param {Number} target
*/ */
resetTo: function( target ) { resetTo: function( target ) {
this.target.value = target; this.start.value = this.target.value = this.current.value = target;
this.target.time = this.current.time; this.start.time = this.target.time = this.current.time = $.now();
this.start.value = this.target.value;
this.start.time = this.target.time;
}, },
/** /**

View File

@ -409,8 +409,6 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
this._xSpring.resetTo(position.x); this._xSpring.resetTo(position.x);
this._ySpring.resetTo(position.y); this._ySpring.resetTo(position.y);
this._xSpring.update();
this._ySpring.update();
} else { } else {
if (sameTarget) { if (sameTarget) {
return; return;
@ -454,7 +452,6 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
} }
this._scaleSpring.resetTo(scale); this._scaleSpring.resetTo(scale);
this._scaleSpring.update();
this._updateForScale(); this._updateForScale();
} else { } else {
if (sameTarget) { if (sameTarget) {

View File

@ -2703,8 +2703,11 @@ function onCanvasScroll( event ) {
shift: event.shift, shift: event.shift,
originalEvent: event.originalEvent originalEvent: event.originalEvent
}); });
if (gestureSettings && gestureSettings.scrollToZoom) {
//cancels event //cancels event
return false; return false;
}
} }
function onContainerEnter( event ) { function onContainerEnter( event ) {
@ -2789,13 +2792,10 @@ function updateMulti( viewer ) {
function updateOnce( viewer ) { function updateOnce( viewer ) {
var containerSize,
animated;
//viewer.profiler.beginUpdate(); //viewer.profiler.beginUpdate();
if ( viewer.autoResize ) { if ( viewer.autoResize ) {
containerSize = _getSafeElemSize( viewer.container ); var containerSize = _getSafeElemSize( viewer.container );
if ( !containerSize.equals( THIS[ viewer.hash ].prevContainerSize ) ) { if ( !containerSize.equals( THIS[ viewer.hash ].prevContainerSize ) ) {
// maintain image position // maintain image position
var oldBounds = viewer.viewport.getBounds(); var oldBounds = viewer.viewport.getBounds();
@ -2806,8 +2806,22 @@ function updateOnce( viewer ) {
} }
} }
animated = viewer.viewport.update(); var viewportChange = viewer.viewport.update();
animated = viewer.world.update() || animated; var animated = viewer.world.update() || viewportChange;
if (viewportChange) {
/**
* Raised when any spring animation update occurs (zoom, pan, etc.),
* before the viewer has drawn the new location.
*
* @event viewport-change
* @memberof OpenSeadragon.Viewer
* @type {object}
* @property {OpenSeadragon.Viewer} eventSource - A reference to the Viewer which raised this event.
* @property {?Object} userData - Arbitrary subscriber-defined object.
*/
viewer.raiseEvent('viewport-change');
}
if( viewer.referenceStrip ){ if( viewer.referenceStrip ){
animated = viewer.referenceStrip.update( viewer.viewport ) || animated; animated = viewer.referenceStrip.update( viewer.viewport ) || animated;
@ -2838,7 +2852,8 @@ function updateOnce( viewer ) {
if (animated) { if (animated) {
/** /**
* Raised when any spring animation update occurs (zoom, pan, etc.). * Raised when any spring animation update occurs (zoom, pan, etc.),
* after the viewer has drawn the new location.
* *
* @event animation * @event animation
* @memberof OpenSeadragon.Viewer * @memberof OpenSeadragon.Viewer

View File

@ -132,6 +132,10 @@ $.Viewport = function( options ) {
animationTime: this.animationTime animationTime: this.animationTime
}); });
this._oldCenterX = this.centerSpringX.current.value;
this._oldCenterY = this.centerSpringY.current.value;
this._oldZoom = this.zoomSpring.current.value;
if (this.contentSize) { if (this.contentSize) {
this.resetContentSize( this.contentSize ); this.resetContentSize( this.contentSize );
} else { } else {
@ -275,7 +279,7 @@ $.Viewport.prototype = /** @lends OpenSeadragon.Viewport.prototype */{
this.minZoomLevel : this.minZoomLevel :
this.minZoomImageRatio * homeZoom; this.minZoomImageRatio * homeZoom;
return Math.min( zoom, homeZoom ); return zoom;
}, },
/** /**
@ -584,10 +588,17 @@ $.Viewport.prototype = /** @lends OpenSeadragon.Viewport.prototype */{
} }
newBounds = this._applyBoundaryConstraints( newBounds, immediately ); newBounds = this._applyBoundaryConstraints( newBounds, immediately );
center = newBounds.getCenter();
} }
if ( newZoom == oldZoom || newBounds.width == oldBounds.width ) { if (immediately) {
return this.panTo( constraints ? newBounds.getCenter() : center, immediately ); this.panTo( center, true );
return this.zoomTo(newZoom, null, true);
}
if (Math.abs(newZoom - oldZoom) < 0.00000000001 ||
Math.abs(newBounds.width - oldBounds.width) < 0.00000000001) {
return this.panTo( center, immediately );
} }
referencePoint = oldBounds.getTopLeft().times( referencePoint = oldBounds.getTopLeft().times(
@ -855,10 +866,7 @@ $.Viewport.prototype = /** @lends OpenSeadragon.Viewport.prototype */{
* @function * @function
*/ */
update: function() { update: function() {
var oldCenterX = this.centerSpringX.current.value, var oldZoomPixel,
oldCenterY = this.centerSpringY.current.value,
oldZoom = this.zoomSpring.current.value,
oldZoomPixel,
newZoomPixel, newZoomPixel,
deltaZoomPixels, deltaZoomPixels,
deltaZoomPoints; deltaZoomPoints;
@ -869,7 +877,7 @@ $.Viewport.prototype = /** @lends OpenSeadragon.Viewport.prototype */{
this.zoomSpring.update(); this.zoomSpring.update();
if (this.zoomPoint && this.zoomSpring.current.value != oldZoom) { if (this.zoomPoint && this.zoomSpring.current.value != this._oldZoom) {
newZoomPixel = this.pixelFromPoint( this.zoomPoint, true ); newZoomPixel = this.pixelFromPoint( this.zoomPoint, true );
deltaZoomPixels = newZoomPixel.minus( oldZoomPixel ); deltaZoomPixels = newZoomPixel.minus( oldZoomPixel );
deltaZoomPoints = this.deltaPointsFromPixels( deltaZoomPixels, true ); deltaZoomPoints = this.deltaPointsFromPixels( deltaZoomPixels, true );
@ -883,9 +891,15 @@ $.Viewport.prototype = /** @lends OpenSeadragon.Viewport.prototype */{
this.centerSpringX.update(); this.centerSpringX.update();
this.centerSpringY.update(); this.centerSpringY.update();
return this.centerSpringX.current.value != oldCenterX || var changed = this.centerSpringX.current.value != this._oldCenterX ||
this.centerSpringY.current.value != oldCenterY || this.centerSpringY.current.value != this._oldCenterY ||
this.zoomSpring.current.value != oldZoom; this.zoomSpring.current.value != this._oldZoom;
this._oldCenterX = this.centerSpringX.current.value;
this._oldCenterY = this.centerSpringY.current.value;
this._oldZoom = this.zoomSpring.current.value;
return changed;
}, },

20
test/demo/m2/README.md Normal file
View File

@ -0,0 +1,20 @@
# M2 Demo
This is an advanced demo/testbed, for proposed improvements to the new version of the Mirador project:
https://github.com/IIIF/m2/
You can see a previous version of Mirador here:
http://showcase.iiif.io/viewer/mirador/
## To Do
* Choosing between multiple versions of a page
* Detail images overlaid on the page
* Cropped images
### Maybe
* Show/hide pages?
* Lazyloading tilesources?

78
test/demo/m2/index.html Normal file
View File

@ -0,0 +1,78 @@
<!DOCTYPE html>
<html>
<head>
<title>Mirador POC</title>
<script type="text/javascript" src='../../../build/openseadragon/openseadragon.js'></script>
<script type="text/javascript" src='../../lib/jquery-1.9.1.min.js'></script>
<script src="//d3js.org/d3.v3.min.js" charset="utf-8"></script>
<script src="js/main.js"></script>
<!-- <script src="js/harvard-tilesources.js"></script> -->
<script src="js/openseadragon-svg-overlay.js"></script>
<style type="text/css">
html,
body {
width: 100%;
height: 100%;
margin: 0;
}
body {
background: #eee;
overflow: scroll;
}
.header {
height: 30px;
}
.nav {
display: inline-block;
margin-left: 50px;
}
.active {
background: #ddf;
}
.hidden {
visibility: hidden;
}
.openseadragon1 {
background: white;
}
.viewer-position {
position: absolute;
left: 0;
top: 30px;
right: 0;
bottom: 0;
}
.scroll-cover {
display: none;
overflow: scroll;
z-index: 100;
}
</style>
</head>
<body>
<div class="header">
<button class="thumbs">Thumbnails</button>
<button class="scroll">Scroll</button>
<button class="book">Book</button>
<button class="page">Page</button>
<div class="nav">
<button class="previous">Previous</button>
<button class="next">Next</button>
</div>
</div>
<div id="contentDiv" class="openseadragon1 viewer-position"></div>
<div class="scroll-cover viewer-position">
<div class="scroll-inner"></div>
</div>
</body>
</html>

1
test/demo/m2/js/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
harvard-tilesources.js

670
test/demo/m2/js/main.js Normal file
View File

@ -0,0 +1,670 @@
/* globals $, App, d3 */
(function() {
// ----------
window.App = {
// ----------
init: function() {
var self = this;
this.maxImages = 500;
this.mode = 'none';
this.pageBuffer = 0.05;
this.bigBuffer = 0.2;
this.page = 0;
this.modeNames = [
'thumbs',
'scroll',
'book',
'page'
];
this.viewer = OpenSeadragon({
id: "contentDiv",
prefixUrl: "../../../build/openseadragon/images/",
autoResize: false,
showHomeControl: false,
tileSources: this.getTileSources()
});
this.viewer.addHandler('open', function() {
self.$el = $(self.viewer.element);
self.setMode({
mode: 'thumbs',
immediately: true
});
});
this.viewer.addHandler('canvas-drag', function() {
if (self.mode === 'scroll') {
var result = self.hitTest(self.viewer.viewport.getCenter());
if (result) {
self.page = result.index;
}
}
});
this.viewer.addHandler('viewport-change', function(event) {
self.applyConstraints();
});
$.each(this.modeNames, function(i, v) {
$('.' + v).click(function() {
self.setMode({
mode: v
});
});
});
$('.next').click(function() {
self.next();
});
$('.previous').click(function() {
self.previous();
});
$(window).keyup(function(event) {
if (self.mode === 'thumbs') {
return;
}
if (event.which === 39) { // Right arrow
self.next();
} else if (event.which === 37) { // Left arrow
self.previous();
}
});
this.$scrollInner = $('.scroll-inner');
this.$scrollCover = $('.scroll-cover')
.scroll(function(event) {
var info = self.getScrollInfo();
if (!info || self.ignoreScroll) {
return;
}
var pos = new OpenSeadragon.Point(info.thumbBounds.getCenter().x,
info.thumbBounds.y + (info.viewportHeight / 2) +
(info.viewportMax * info.scrollFactor));
self.viewer.viewport.panTo(pos, true);
})
.mousemove(function(event) {
var pixel = new OpenSeadragon.Point(event.clientX, event.clientY);
var result = self.hitTest(self.viewer.viewport.pointFromPixel(pixel));
self.updateHover(result ? result.index : -1);
})
.click(function(event) {
var pixel = new OpenSeadragon.Point(event.clientX, event.clientY);
var result = self.hitTest(self.viewer.viewport.pointFromPixel(pixel));
if (result) {
self.setMode({
mode: 'page',
page: result.index
});
}
});
var svgNode = this.viewer.svgOverlay();
this.highlight = d3.select(svgNode).append("rect")
.style('fill', 'none')
.style('stroke', '#08f')
.style('opacity', 0)
.style('stroke-width', 0.05)
.attr("pointer-events", "none");
this.hover = d3.select(svgNode).append("rect")
.style('fill', 'none')
.style('stroke', '#08f')
.style('opacity', 0)
.style('stroke-width', 0.05)
.attr("pointer-events", "none");
$(window).resize(function() {
var newSize = new OpenSeadragon.Point(self.$el.width(), self.$el.height());
self.viewer.viewport.resize(newSize, false);
self.setMode({
mode: self.mode,
immediately: true
});
self.viewer.forceRedraw();
self.viewer.svgOverlay('resize');
});
this.update();
},
// ----------
next: function() {
var page = this.page + (this.mode === 'book' ? 2 : 1);
if (this.mode === 'book' && page % 2 === 0 && page !== 0) {
page --;
}
this.goToPage({
page: page
});
},
// ----------
previous: function() {
var page = this.page - (this.mode === 'book' ? 2 : 1);
if (this.mode === 'book' && page % 2 === 0 && page !== 0) {
page --;
}
this.goToPage({
page: page
});
},
// ----------
hitTest: function(pos) {
var count = this.viewer.world.getItemCount();
var item, box;
for (var i = 0; i < count; i++) {
item = this.viewer.world.getItemAt(i);
box = item.getBounds();
if (pos.x > box.x && pos.y > box.y && pos.x < box.x + box.width &&
pos.y < box.y + box.height) {
return {
item: item,
index: i
};
}
}
return null;
},
// ----------
getScrollInfo: function() {
if (!this.thumbBounds) {
return null;
}
var output = {};
var viewerWidth = this.$el.width();
var viewerHeight = this.$el.height();
var scrollTop = this.$scrollCover.scrollTop();
output.scrollMax = this.$scrollInner.height() - this.$scrollCover.height();
output.scrollFactor = (output.scrollMax > 0 ? scrollTop / output.scrollMax : 0);
output.thumbBounds = this.thumbBounds;
output.viewportHeight = output.thumbBounds.width * (viewerHeight / viewerWidth);
output.viewportMax = Math.max(0, output.thumbBounds.height - output.viewportHeight);
return output;
},
// ----------
update: function() {
var self = this;
$('.nav').toggle(this.mode === 'scroll' || this.mode === 'book' || this.mode === 'page');
$('.previous').toggleClass('hidden', this.page <= 0);
$('.next').toggleClass('hidden', this.page >= this.viewer.world.getItemCount() - 1);
$.each(this.modeNames, function(i, v) {
$('.' + v).toggleClass('active', v === self.mode);
});
},
// ----------
applyConstraints: function() {
if (this.mode === 'thumbs') {
return;
}
if (this.panBounds) {
var center = this.viewer.viewport.getCenter(true);
var viewBounds = this.viewer.viewport.getBounds(true);
var bounds = this.panBounds.clone();
var left = bounds.x + (viewBounds.width / 2);
var top = bounds.y + (viewBounds.height / 2);
var right = (bounds.x + bounds.width) - (viewBounds.width / 2);
var bottom = (bounds.y + bounds.height) - (viewBounds.height / 2);
var x;
if (left <= right) {
x = Math.max(left, Math.min(right, center.x));
} else {
x = bounds.x + (bounds.width / 2);
}
var y;
if (top <= bottom) {
y = Math.max(top, Math.min(bottom, center.y));
} else {
y = bounds.y + (bounds.height / 2);
}
if (x !== center.x || y !== center.y) {
this.viewer.viewport.centerSpringX.current.value = x;
this.viewer.viewport.centerSpringY.current.value = y;
}
}
},
// ----------
setMode: function(config) {
var self = this;
this.mode = config.mode;
if (config.page !== undefined) {
this.page = config.page; // Need to do this before layout
}
this.ignoreScroll = true;
this.thumbBounds = null;
var layout = this.createLayout();
if (this.mode === 'thumbs') {
this.viewer.gestureSettingsMouse.scrollToZoom = false;
this.viewer.zoomPerClick = 1;
this.viewer.panHorizontal = false;
this.viewer.panVertical = false;
var viewerWidth = this.$el.width();
var width = layout.bounds.width + (this.bigBuffer * 2);
var height = layout.bounds.height + (this.bigBuffer * 2);
var newHeight = viewerWidth * (height / width);
this.$scrollCover.show();
this.$scrollInner
.css({
height: newHeight
});
} else {
this.viewer.gestureSettingsMouse.scrollToZoom = true;
this.viewer.zoomPerClick = 2;
this.viewer.panHorizontal = true;
this.viewer.panVertical = true;
this.$scrollCover.hide();
}
this.setLayout({
layout: layout,
immediately: config.immediately
});
if (this.mode === 'thumbs') {
// Set up thumbBounds
this.thumbBounds = this.viewer.world.getHomeBounds();
this.thumbBounds.x -= this.bigBuffer;
this.thumbBounds.y -= this.bigBuffer;
this.thumbBounds.width += (this.bigBuffer * 2);
this.thumbBounds.height += (this.bigBuffer * 2);
// Scroll to the appropriate location
var info = this.getScrollInfo();
var viewportBounds = this.thumbBounds.clone();
viewportBounds.y += info.viewportMax * info.scrollFactor;
viewportBounds.height = info.viewportHeight;
var itemBounds = this.viewer.world.getItemAt(this.page).getBounds();
var top = itemBounds.y - this.bigBuffer;
var bottom = top + itemBounds.height + (this.bigBuffer * 2);
var normalY;
if (top < viewportBounds.y) {
normalY = top - this.thumbBounds.y;
} else if (bottom > viewportBounds.y + viewportBounds.height) {
normalY = (bottom - info.viewportHeight) - this.thumbBounds.y;
}
if (normalY !== undefined) {
var viewportFactor = normalY / info.viewportMax;
this.$scrollCover.scrollTop(info.scrollMax * viewportFactor);
}
}
this.goHome({
immediately: config.immediately
});
this.viewer.viewport.minZoomLevel = this.viewer.viewport.getZoom();
this.update();
this.updateHighlight();
this.updateHover(-1);
clearTimeout(this.scrollTimeout);
this.scrollTimeout = setTimeout(function() {
self.ignoreScroll = false;
}, this.viewer.animationTime * 1000);
},
// ----------
updateHighlight: function() {
if (this.mode !== 'thumbs') {
this.highlight.style('opacity', 0);
return;
}
var item = this.viewer.world.getItemAt(this.page);
var box = item.getBounds();
this.highlight
.style('opacity', 1)
.attr("x", box.x)
.attr("width", box.width)
.attr("y", box.y)
.attr("height", box.height);
},
// ----------
updateHover: function(page) {
if (page === -1 || this.mode !== 'thumbs') {
this.hover.style('opacity', 0);
this.$scrollCover.css({
'cursor': 'default'
});
return;
}
this.$scrollCover.css({
'cursor': 'pointer'
});
var item = this.viewer.world.getItemAt(page);
var box = item.getBounds();
this.hover
.style('opacity', 0.3)
.attr("x", box.x)
.attr("width", box.width)
.attr("y", box.y)
.attr("height", box.height);
},
// ----------
goToPage: function(config) {
var self = this;
var itemCount = this.viewer.world.getItemCount();
this.page = Math.max(0, Math.min(itemCount - 1, config.page));
var viewerWidth = this.$el.width();
var viewerHeight = this.$el.height();
var bounds = this.viewer.world.getItemAt(this.page).getBounds();
var x = bounds.x;
var y = bounds.y;
var width = bounds.width;
var height = bounds.height;
var box;
if (this.mode === 'book') {
var item;
if (this.page % 2) { // First in a pair
item = this.viewer.world.getItemAt(this.page + 1);
if (item) {
width += item.getBounds().width;
}
} else {
item = this.viewer.world.getItemAt(this.page - 1);
if (item) {
box = item.getBounds();
x -= width;
width += box.width;
}
}
}
x -= this.pageBuffer;
y -= this.pageBuffer;
width += (this.pageBuffer * 2);
height += (this.pageBuffer * 2);
if (this.mode === 'scroll') {
if (this.page === 0) {
x = bounds.x - this.pageBuffer;
width = height * (viewerWidth / viewerHeight);
} else if (this.page === this.viewer.world.getItemCount() - 1) {
width = height * (viewerWidth / viewerHeight);
x = (bounds.x + bounds.width + this.pageBuffer) - width;
}
}
box = new OpenSeadragon.Rect(x, y, width, height);
this.viewer.viewport.fitBounds(box, config.immediately);
this.panBounds = null;
var setPanBounds = function() {
if (self.mode === 'page' || self.mode === 'book') {
self.panBounds = box;
} else if (self.mode === 'scroll') {
self.panBounds = self.viewer.world.getItemAt(0).getBounds()
.union(self.viewer.world.getItemAt(itemCount - 1).getBounds());
self.panBounds.x -= self.pageBuffer;
self.panBounds.y -= self.pageBuffer;
self.panBounds.width += (self.pageBuffer * 2);
self.panBounds.height += (self.pageBuffer * 2);
}
};
clearTimeout(this.panBoundsTimeout);
if (config.immediately) {
setPanBounds();
} else {
this.panBoundsTimeout = setTimeout(setPanBounds, this.viewer.animationTime * 1000);
}
this.viewer.viewport.minZoomLevel = this.viewer.viewport.getZoom();
this.update();
},
// ----------
createLayout: function() {
var viewerWidth = this.$el.width();
var viewerHeight = this.$el.height();
var layoutConfig = {};
if (this.mode === 'thumbs') {
layoutConfig.columns = Math.floor(viewerWidth / 150);
layoutConfig.buffer = this.bigBuffer;
layoutConfig.sameWidth = true;
} else if (this.mode === 'scroll') {
layoutConfig.buffer = this.pageBuffer;
} else if (this.mode === 'book' || this.mode === 'page') {
layoutConfig.book = (this.mode === 'book');
var height = 1 + (this.pageBuffer * 2);
// Note that using window here is approximate, but that's close enough.
// We can't use viewer, because it may be stretched for the thumbs view.
layoutConfig.buffer = (height * ($(window).width() / $(window).height())) / 2;
}
var layout = {
bounds: null,
specs: []
};
var count = this.viewer.world.getItemCount();
var x = 0;
var y = 0;
var offset = new OpenSeadragon.Point();
var rowHeight = 0;
var item, box;
for (var i = 0; i < count; i++) {
item = this.viewer.world.getItemAt(i);
box = item.getBounds();
if (i === this.page) {
offset = box.getTopLeft().minus(new OpenSeadragon.Point(x, y));
}
box.x = x;
box.y = y;
if (layoutConfig.sameWidth) {
box.height = box.height / box.width;
box.width = 1;
} else {
box.width = box.width / box.height;
box.height = 1;
}
rowHeight = Math.max(rowHeight, box.height);
layout.specs.push({
item: item,
bounds: box
});
if (layoutConfig.columns && i % layoutConfig.columns === layoutConfig.columns - 1) {
x = 0;
y += rowHeight + layoutConfig.buffer;
rowHeight = 0;
} else {
if (!layoutConfig.book || i % 2 === 0) {
x += layoutConfig.buffer;
}
x += box.width;
}
}
var pos, spec;
for (i = 0; i < count; i++) {
spec = layout.specs[i];
pos = spec.bounds.getTopLeft().plus(offset);
spec.bounds.x = pos.x;
spec.bounds.y = pos.y;
if (layout.bounds) {
layout.bounds = layout.bounds.union(spec.bounds);
} else {
layout.bounds = spec.bounds.clone();
}
}
return layout;
},
// ----------
setLayout: function(config) {
var spec;
for (var i = 0; i < config.layout.specs.length; i++) {
spec = config.layout.specs[i];
spec.item.setPosition(spec.bounds.getTopLeft(), config.immediately);
spec.item.setWidth(spec.bounds.width, config.immediately);
}
},
// ----------
goHome: function(config) {
var viewerWidth = this.$el.width();
var viewerHeight = this.$el.height();
var layoutConfig = {};
if (this.mode === 'thumbs') {
var info = this.getScrollInfo();
var box = this.thumbBounds.clone();
box.height = box.width * (viewerHeight / viewerWidth);
box.y += info.viewportMax * info.scrollFactor;
this.viewer.viewport.fitBounds(box, config.immediately);
} else {
this.goToPage({
page: this.page,
immediately: config.immediately
});
}
},
// ----------
getTileSources: function() {
if (this.tileSources) {
return $.map(this.tileSources.slice(0, this.maxImages), function(v, i) {
return new OpenSeadragon.IIIFTileSource(v);
});
}
var inputs = [
{
Image: {
xmlns: "http://schemas.microsoft.com/deepzoom/2008",
Url: "http://openseadragon.github.io/example-images/highsmith/highsmith_files/",
Format: "jpg",
Overlap: "2",
TileSize: "256",
Size: {
Width: "7026",
Height: "9221"
}
}
}, {
Image: {
xmlns: "http://schemas.microsoft.com/deepzoom/2008",
Url: "http://openseadragon.github.io/example-images/duomo/duomo_files/",
Format: "jpg",
Overlap: "2",
TileSize: "256",
Size: {
Width: "13920",
Height: "10200"
}
}
}, {
// Image: {
// xmlns: "http://schemas.microsoft.com/deepzoom/2008",
// Url: "../../data/tall_files/",
// Format: "jpg",
// Overlap: "1",
// TileSize: "254",
// Size: {
// Width: "500",
// Height: "2000"
// }
// }
// }, {
// Image: {
// xmlns: "http://schemas.microsoft.com/deepzoom/2008",
// Url: "../../data/wide_files/",
// Format: "jpg",
// Overlap: "1",
// TileSize: "254",
// Size: {
// Width: "2000",
// Height: "500"
// }
// }
// }, {
Image: {
xmlns: "http://schemas.microsoft.com/deepzoom/2008",
Url: "../../data/testpattern_files/",
Format: "jpg",
Overlap: "1",
TileSize: "254",
Size: {
Width: "1000",
Height: "1000"
}
}
}
];
var outputs = [];
for (var i = 0; i < this.maxImages; i++) {
outputs.push(inputs[Math.floor(Math.random() * inputs.length)]);
}
return outputs;
}
};
// ----------
$(document).ready(function() {
App.init();
});
})();

View File

@ -0,0 +1,73 @@
(function() {
if (!window.OpenSeadragon) {
console.error('[openseadragon-svg-overlay] requires OpenSeadragon');
return;
}
var svgNS = 'http://www.w3.org/2000/svg';
var update = function(viewer) {
var info = viewer._svgOverlayInfo;
if (info.containerWidth !== viewer.container.clientWidth) {
info.containerWidth = viewer.container.clientWidth;
info.svg.setAttribute('width', info.containerWidth);
}
if (info.containerHeight !== viewer.container.clientHeight) {
info.containerHeight = viewer.container.clientHeight;
info.svg.setAttribute('height', info.containerHeight);
}
var p = viewer.viewport.pixelFromPoint(new OpenSeadragon.Point(0, 0), true);
var zoom = viewer.viewport.getZoom(true);
var scale = viewer.container.clientWidth * zoom;
info.node.setAttribute('transform',
'translate(' + p.x + ',' + p.y + ') scale(' + scale + ')');
};
OpenSeadragon.Viewer.prototype.svgOverlay = function(command) {
var self = this;
if (command === undefined) {
if (this._svgOverlayInfo) {
console.error('[openseadragon-svg-overlay] already initialized on this viewer');
return;
}
var info = this._svgOverlayInfo = {
containerWidth: 0,
containerHeight: 0
};
info.svg = document.createElementNS(svgNS, 'svg');
info.svg.setAttribute('pointer-events', 'none');
info.svg.style.position = 'absolute';
info.svg.style.left = 0;
info.svg.style.top = 0;
info.svg.style.width = '100%';
info.svg.style.height = '100%';
this.container.insertBefore(info.svg, this.canvas.nextSibling);
info.node = document.createElementNS(svgNS, 'g');
info.svg.appendChild(info.node);
this.addHandler('animation', function() {
update(self);
});
this.addHandler('open', function() {
update(self);
});
update(this);
return info.node;
} else if (command === 'resize') {
update(this);
} else {
console.error('[openseadragon-svg-overlay] unknown command: ' + command);
}
};
})();