mirror of
https://github.com/openseadragon/openseadragon.git
synced 2024-11-28 16:16:08 +03:00
Merge pull request #365 from avandecreme/optimization
Overlays performance optimization. See #359
This commit is contained in:
commit
693b9e2e89
@ -78,7 +78,11 @@
|
|||||||
* @param {OpenSeadragon.OverlayPlacement} [options.placement=OpenSeadragon.OverlayPlacement.TOP_LEFT]
|
* @param {OpenSeadragon.OverlayPlacement} [options.placement=OpenSeadragon.OverlayPlacement.TOP_LEFT]
|
||||||
* Relative position to the viewport.
|
* Relative position to the viewport.
|
||||||
* Only used if location is a {@link OpenSeadragon.Point}.
|
* Only used if location is a {@link OpenSeadragon.Point}.
|
||||||
* @param {OpenSeadragon.Overlay.OnDrawCallback} options.onDraw
|
* @param {OpenSeadragon.Overlay.OnDrawCallback} [options.onDraw]
|
||||||
|
* @param {Boolean} [options.checkResize=true] Set to false to avoid to
|
||||||
|
* check the size of the overlay everytime it is drawn when using a
|
||||||
|
* {@link OpenSeadragon.Point} as options.location. It will improve
|
||||||
|
* performances but will cause a misalignment if the overlay size changes.
|
||||||
*/
|
*/
|
||||||
$.Overlay = function( element, location, placement ) {
|
$.Overlay = function( element, location, placement ) {
|
||||||
|
|
||||||
@ -125,6 +129,8 @@
|
|||||||
options.placement :
|
options.placement :
|
||||||
$.OverlayPlacement.TOP_LEFT;
|
$.OverlayPlacement.TOP_LEFT;
|
||||||
this.onDraw = options.onDraw;
|
this.onDraw = options.onDraw;
|
||||||
|
this.checkResize = options.checkResize === undefined ?
|
||||||
|
true : options.checkResize;
|
||||||
};
|
};
|
||||||
|
|
||||||
$.Overlay.prototype = /** @lends OpenSeadragon.Overlay.prototype */{
|
$.Overlay.prototype = /** @lends OpenSeadragon.Overlay.prototype */{
|
||||||
@ -212,19 +218,12 @@
|
|||||||
var element = this.element,
|
var element = this.element,
|
||||||
style = this.style,
|
style = this.style,
|
||||||
scales = this.scales,
|
scales = this.scales,
|
||||||
drawerCenter = new $.Point(
|
|
||||||
viewport.viewer.drawer.canvas.width / 2,
|
|
||||||
viewport.viewer.drawer.canvas.height / 2
|
|
||||||
),
|
|
||||||
degrees = viewport.degrees,
|
degrees = viewport.degrees,
|
||||||
position = viewport.pixelFromPoint(
|
position = viewport.pixelFromPoint(
|
||||||
this.bounds.getTopLeft(),
|
this.bounds.getTopLeft(),
|
||||||
true
|
true
|
||||||
),
|
),
|
||||||
size = viewport.deltaPixelsFromPoints(
|
size,
|
||||||
this.bounds.getSize(),
|
|
||||||
true
|
|
||||||
),
|
|
||||||
overlayCenter;
|
overlayCenter;
|
||||||
|
|
||||||
if ( element.parentNode != container ) {
|
if ( element.parentNode != container ) {
|
||||||
@ -232,10 +231,18 @@
|
|||||||
element.prevElementParent = element.parentNode;
|
element.prevElementParent = element.parentNode;
|
||||||
element.prevNextSibling = element.nextSibling;
|
element.prevNextSibling = element.nextSibling;
|
||||||
container.appendChild( element );
|
container.appendChild( element );
|
||||||
|
this.size = $.getElementSize( element );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !scales ) {
|
if ( scales ) {
|
||||||
this.size = $.getElementSize( element );
|
size = viewport.deltaPixelsFromPoints(
|
||||||
|
this.bounds.getSize(),
|
||||||
|
true
|
||||||
|
);
|
||||||
|
} else if ( this.checkResize ) {
|
||||||
|
size = $.getElementSize( element );
|
||||||
|
} else {
|
||||||
|
size = this.size;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.position = position;
|
this.position = position;
|
||||||
@ -254,6 +261,10 @@
|
|||||||
if( degrees !== 0 && this.scales ) {
|
if( degrees !== 0 && this.scales ) {
|
||||||
overlayCenter = new $.Point( size.x / 2, size.y / 2 );
|
overlayCenter = new $.Point( size.x / 2, size.y / 2 );
|
||||||
|
|
||||||
|
var drawerCenter = new $.Point(
|
||||||
|
viewport.viewer.drawer.canvas.width / 2,
|
||||||
|
viewport.viewer.drawer.canvas.height / 2
|
||||||
|
);
|
||||||
position = position.plus( overlayCenter ).rotate(
|
position = position.plus( overlayCenter ).rotate(
|
||||||
degrees,
|
degrees,
|
||||||
drawerCenter
|
drawerCenter
|
||||||
@ -263,10 +274,10 @@
|
|||||||
size = new $.Point( Math.abs( size.x ), Math.abs( size.y ) );
|
size = new $.Point( Math.abs( size.x ), Math.abs( size.y ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
// call the onDraw callback if there is one to allow, this allows someone to overwrite
|
// call the onDraw callback if it exists to allow one to overwrite
|
||||||
// the drawing/positioning/sizing of the overlay
|
// the drawing/positioning/sizing of the overlay
|
||||||
if (this.onDraw) {
|
if ( this.onDraw ) {
|
||||||
this.onDraw(position, size, element);
|
this.onDraw( position, size, element );
|
||||||
} else {
|
} else {
|
||||||
style.left = position.x + "px";
|
style.left = position.x + "px";
|
||||||
style.top = position.y + "px";
|
style.top = position.y + "px";
|
||||||
|
@ -2045,22 +2045,31 @@ function getOverlayObject( viewer, overlay ) {
|
|||||||
|
|
||||||
var location = overlay.location;
|
var location = overlay.location;
|
||||||
if ( !location ) {
|
if ( !location ) {
|
||||||
var rect = ( overlay.height && overlay.width ) ? new $.Rect(
|
if ( overlay.width && overlay.height ) {
|
||||||
overlay.x || overlay.px,
|
location = overlay.px !== undefined ?
|
||||||
overlay.y || overlay.py,
|
viewer.viewport.imageToViewportRectangle( new $.Rect(
|
||||||
overlay.width,
|
overlay.px,
|
||||||
overlay.height
|
overlay.py,
|
||||||
) : new $.Point(
|
overlay.width,
|
||||||
overlay.x || overlay.px,
|
overlay.height
|
||||||
overlay.y || overlay.py
|
) ) :
|
||||||
);
|
new $.Rect(
|
||||||
if( overlay.px !== undefined ) {
|
overlay.x,
|
||||||
//if they specified 'px' so it's in pixel coordinates so
|
overlay.y,
|
||||||
//we need to translate to viewport coordinates
|
overlay.width,
|
||||||
rect = viewer.viewport.imageToViewportRectangle( rect );
|
overlay.height
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
location = overlay.px !== undefined ?
|
||||||
|
viewer.viewport.imageToViewportCoordinates( new $.Point(
|
||||||
|
overlay.px,
|
||||||
|
overlay.py
|
||||||
|
) ) :
|
||||||
|
new $.Point(
|
||||||
|
overlay.x,
|
||||||
|
overlay.y
|
||||||
|
);
|
||||||
}
|
}
|
||||||
location = overlay.placement ? viewer.viewport.pointFromPixel( rect ) :
|
|
||||||
rect;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var placement = overlay.placement;
|
var placement = overlay.placement;
|
||||||
@ -2072,7 +2081,8 @@ function getOverlayObject( viewer, overlay ) {
|
|||||||
element: element,
|
element: element,
|
||||||
location: location,
|
location: location,
|
||||||
placement: placement,
|
placement: placement,
|
||||||
onDraw: overlay.onDraw
|
onDraw: overlay.onDraw,
|
||||||
|
checkResize: overlay.checkResize
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
217
test/overlays.js
217
test/overlays.js
@ -6,9 +6,9 @@
|
|||||||
module( "Overlays", {
|
module( "Overlays", {
|
||||||
setup: function() {
|
setup: function() {
|
||||||
var example = $( '<div id="example-overlays"></div>' ).appendTo( "#qunit-fixture" );
|
var example = $( '<div id="example-overlays"></div>' ).appendTo( "#qunit-fixture" );
|
||||||
var fixedOverlay = $( '<div id="fixed-overlay"></div>' ).appendTo(example);
|
var fixedOverlay = $( '<div id="fixed-overlay"></div>' ).appendTo( example );
|
||||||
fixedOverlay.width(70);
|
fixedOverlay.width( 70 );
|
||||||
fixedOverlay.height(60);
|
fixedOverlay.height( 60 );
|
||||||
|
|
||||||
testLog.reset();
|
testLog.reset();
|
||||||
},
|
},
|
||||||
@ -186,7 +186,7 @@
|
|||||||
equal( viewer.currentOverlays.length, 0, "No overlay should be open." );
|
equal( viewer.currentOverlays.length, 0, "No overlay should be open." );
|
||||||
|
|
||||||
var rect = new OpenSeadragon.Rect( 0.1, 0.1, 0.1, 0.1 );
|
var rect = new OpenSeadragon.Rect( 0.1, 0.1, 0.1, 0.1 );
|
||||||
var overlay = $( "<div/>" ).prop("id", "overlay").get( 0 );
|
var overlay = $( "<div/>" ).prop( "id", "overlay" ).get( 0 );
|
||||||
viewer.addOverlay( overlay, rect );
|
viewer.addOverlay( overlay, rect );
|
||||||
equal( viewer.overlays.length, 0, "No manual overlay should be added as global overlay." );
|
equal( viewer.overlays.length, 0, "No manual overlay should be added as global overlay." );
|
||||||
equal( viewer.currentOverlays.length, 1, "A manual overlay should be open." );
|
equal( viewer.currentOverlays.length, 1, "A manual overlay should be open." );
|
||||||
@ -221,7 +221,7 @@
|
|||||||
viewer = OpenSeadragon( {
|
viewer = OpenSeadragon( {
|
||||||
id: 'example-overlays',
|
id: 'example-overlays',
|
||||||
prefixUrl: '/build/openseadragon/images/',
|
prefixUrl: '/build/openseadragon/images/',
|
||||||
tileSources: [ '/test/data/testpattern.dzi', '/test/data/testpattern.dzi' ],
|
tileSources: '/test/data/testpattern.dzi',
|
||||||
springStiffness: 100, // Faster animation = faster tests
|
springStiffness: 100, // Faster animation = faster tests
|
||||||
overlays: [ {
|
overlays: [ {
|
||||||
px: 13,
|
px: 13,
|
||||||
@ -232,8 +232,9 @@
|
|||||||
}, {
|
}, {
|
||||||
px: 400,
|
px: 400,
|
||||||
py: 500,
|
py: 500,
|
||||||
id: "fixed-overlay"
|
id: "fixed-overlay",
|
||||||
}]
|
placement: "TOP_LEFT"
|
||||||
|
} ]
|
||||||
} );
|
} );
|
||||||
|
|
||||||
function checkOverlayPosition( contextMessage ) {
|
function checkOverlayPosition( contextMessage ) {
|
||||||
@ -284,7 +285,7 @@
|
|||||||
viewer = OpenSeadragon( {
|
viewer = OpenSeadragon( {
|
||||||
id: 'example-overlays',
|
id: 'example-overlays',
|
||||||
prefixUrl: '/build/openseadragon/images/',
|
prefixUrl: '/build/openseadragon/images/',
|
||||||
tileSources: [ '/test/data/testpattern.dzi', '/test/data/testpattern.dzi' ],
|
tileSources: '/test/data/testpattern.dzi',
|
||||||
springStiffness: 100, // Faster animation = faster tests
|
springStiffness: 100, // Faster animation = faster tests
|
||||||
overlays: [ {
|
overlays: [ {
|
||||||
x: 0.2,
|
x: 0.2,
|
||||||
@ -292,10 +293,11 @@
|
|||||||
width: 0.5,
|
width: 0.5,
|
||||||
height: 0.1,
|
height: 0.1,
|
||||||
id: "overlay"
|
id: "overlay"
|
||||||
},{
|
}, {
|
||||||
x: 0.5,
|
x: 0.5,
|
||||||
y: 0.6,
|
y: 0.6,
|
||||||
id: "fixed-overlay"
|
id: "fixed-overlay",
|
||||||
|
placement: "TOP_LEFT"
|
||||||
} ]
|
} ]
|
||||||
} );
|
} );
|
||||||
|
|
||||||
@ -309,9 +311,9 @@
|
|||||||
equal( actPosition.top, expPosition.y, "Y position mismatch " + contextMessage );
|
equal( actPosition.top, expPosition.y, "Y position mismatch " + contextMessage );
|
||||||
|
|
||||||
var expectedSize = viewport.deltaPixelsFromPoints(
|
var expectedSize = viewport.deltaPixelsFromPoints(
|
||||||
new OpenSeadragon.Point(0.5, 0.1));
|
new OpenSeadragon.Point( 0.5, 0.1 ) );
|
||||||
equal( $( "#overlay" ).width(), expectedSize.x, "Width mismatch " + contextMessage );
|
equal( $( "#overlay" ).width(), expectedSize.x, "Width mismatch " + contextMessage );
|
||||||
equal( $( "#overlay" ).height( ), expectedSize.y, "Height mismatch " + contextMessage );
|
equal( $( "#overlay" ).height(), expectedSize.y, "Height mismatch " + contextMessage );
|
||||||
|
|
||||||
|
|
||||||
expPosition = viewport.viewportToViewerElementCoordinates(
|
expPosition = viewport.viewportToViewerElementCoordinates(
|
||||||
@ -341,4 +343,193 @@
|
|||||||
} );
|
} );
|
||||||
} );
|
} );
|
||||||
|
|
||||||
} )();
|
asyncTest( 'Overlays placement', function() {
|
||||||
|
|
||||||
|
var scalableOverlayLocation = new OpenSeadragon.Rect( 0.2, 0.1, 0.5, 0.1 );
|
||||||
|
var fixedOverlayLocation = new OpenSeadragon.Point( 0.5, 0.6 );
|
||||||
|
|
||||||
|
viewer = OpenSeadragon( {
|
||||||
|
id: 'example-overlays',
|
||||||
|
prefixUrl: '/build/openseadragon/images/',
|
||||||
|
tileSources: '/test/data/testpattern.dzi',
|
||||||
|
springStiffness: 100, // Faster animation = faster tests
|
||||||
|
overlays: [ {
|
||||||
|
x: scalableOverlayLocation.x,
|
||||||
|
y: scalableOverlayLocation.y,
|
||||||
|
width: scalableOverlayLocation.width,
|
||||||
|
height: scalableOverlayLocation.height,
|
||||||
|
id: "overlay",
|
||||||
|
placement: "TOP_LEFT"
|
||||||
|
}, {
|
||||||
|
x: fixedOverlayLocation.x,
|
||||||
|
y: fixedOverlayLocation.y,
|
||||||
|
id: "fixed-overlay",
|
||||||
|
placement: "TOP_LEFT"
|
||||||
|
} ]
|
||||||
|
} );
|
||||||
|
|
||||||
|
// Scalable overlays are always TOP_LEFT
|
||||||
|
function checkScalableOverlayPosition( contextMessage ) {
|
||||||
|
var viewport = viewer.viewport;
|
||||||
|
|
||||||
|
var expPosition = viewport.viewportToViewerElementCoordinates(
|
||||||
|
new OpenSeadragon.Point( 0.2, 0.1 ) ).apply( Math.floor );
|
||||||
|
var actPosition = $( "#overlay" ).position();
|
||||||
|
equal( actPosition.left, expPosition.x, "X position mismatch " + contextMessage );
|
||||||
|
equal( actPosition.top, expPosition.y, "Y position mismatch " + contextMessage );
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkFixedOverlayPosition( expectedOffset, contextMessage ) {
|
||||||
|
var viewport = viewer.viewport;
|
||||||
|
|
||||||
|
var expPosition = viewport.viewportToViewerElementCoordinates(
|
||||||
|
new OpenSeadragon.Point( 0.5, 0.6 ) )
|
||||||
|
.apply( Math.floor )
|
||||||
|
.plus( expectedOffset );
|
||||||
|
var actPosition = $( "#fixed-overlay" ).position();
|
||||||
|
equal( actPosition.left, expPosition.x, "Fixed overlay X position mismatch " + contextMessage );
|
||||||
|
equal( actPosition.top, expPosition.y, "Fixed overlay Y position mismatch " + contextMessage );
|
||||||
|
}
|
||||||
|
|
||||||
|
waitForViewer( function() {
|
||||||
|
|
||||||
|
checkScalableOverlayPosition( "with TOP_LEFT placement." );
|
||||||
|
checkFixedOverlayPosition( new OpenSeadragon.Point( 0, 0 ),
|
||||||
|
"with TOP_LEFT placement." );
|
||||||
|
|
||||||
|
viewer.updateOverlay( "overlay", scalableOverlayLocation,
|
||||||
|
OpenSeadragon.OverlayPlacement.CENTER );
|
||||||
|
viewer.updateOverlay( "fixed-overlay", fixedOverlayLocation,
|
||||||
|
OpenSeadragon.OverlayPlacement.CENTER );
|
||||||
|
|
||||||
|
setTimeout( function() {
|
||||||
|
checkScalableOverlayPosition( "with CENTER placement." );
|
||||||
|
checkFixedOverlayPosition( new OpenSeadragon.Point( -35, -30 ),
|
||||||
|
"with CENTER placement." );
|
||||||
|
|
||||||
|
viewer.updateOverlay( "overlay", scalableOverlayLocation,
|
||||||
|
OpenSeadragon.OverlayPlacement.BOTTOM_RIGHT );
|
||||||
|
viewer.updateOverlay( "fixed-overlay", fixedOverlayLocation,
|
||||||
|
OpenSeadragon.OverlayPlacement.BOTTOM_RIGHT );
|
||||||
|
setTimeout( function() {
|
||||||
|
checkScalableOverlayPosition( "with BOTTOM_RIGHT placement." );
|
||||||
|
checkFixedOverlayPosition( new OpenSeadragon.Point( -70, -60 ),
|
||||||
|
"with BOTTOM_RIGHT placement." );
|
||||||
|
|
||||||
|
start();
|
||||||
|
}, 100 );
|
||||||
|
|
||||||
|
}, 100 );
|
||||||
|
|
||||||
|
} );
|
||||||
|
} );
|
||||||
|
|
||||||
|
asyncTest( 'Overlays placement and resizing check', function() {
|
||||||
|
|
||||||
|
var fixedOverlayLocation = new OpenSeadragon.Point( 0.5, 0.6 );
|
||||||
|
|
||||||
|
viewer = OpenSeadragon( {
|
||||||
|
id: 'example-overlays',
|
||||||
|
prefixUrl: '/build/openseadragon/images/',
|
||||||
|
tileSources: '/test/data/testpattern.dzi',
|
||||||
|
springStiffness: 100, // Faster animation = faster tests
|
||||||
|
overlays: [ {
|
||||||
|
x: fixedOverlayLocation.x,
|
||||||
|
y: fixedOverlayLocation.y,
|
||||||
|
id: "fixed-overlay",
|
||||||
|
placement: "CENTER",
|
||||||
|
checkResize: true
|
||||||
|
} ]
|
||||||
|
} );
|
||||||
|
|
||||||
|
function checkFixedOverlayPosition( expectedOffset, contextMessage ) {
|
||||||
|
var viewport = viewer.viewport;
|
||||||
|
|
||||||
|
var expPosition = viewport.viewportToViewerElementCoordinates(
|
||||||
|
new OpenSeadragon.Point( 0.5, 0.6 ) )
|
||||||
|
.apply( Math.floor )
|
||||||
|
.plus( expectedOffset );
|
||||||
|
var actPosition = $( "#fixed-overlay" ).position();
|
||||||
|
equal( actPosition.left, expPosition.x, "Fixed overlay X position mismatch " + contextMessage );
|
||||||
|
equal( actPosition.top, expPosition.y, "Fixed overlay Y position mismatch " + contextMessage );
|
||||||
|
}
|
||||||
|
|
||||||
|
waitForViewer( function() {
|
||||||
|
checkFixedOverlayPosition( new OpenSeadragon.Point( -35, -30 ),
|
||||||
|
"with overlay of size 70,60." );
|
||||||
|
|
||||||
|
$( "#fixed-overlay" ).width( 50 );
|
||||||
|
$( "#fixed-overlay" ).height( 40 );
|
||||||
|
|
||||||
|
// The resizing of the overlays is not detected by the viewer's loop.
|
||||||
|
viewer.forceRedraw();
|
||||||
|
|
||||||
|
setTimeout( function() {
|
||||||
|
checkFixedOverlayPosition( new OpenSeadragon.Point( -25, -20 ),
|
||||||
|
"with overlay of size 50,40." );
|
||||||
|
|
||||||
|
// Restore original size
|
||||||
|
$( "#fixed-overlay" ).width( 70 );
|
||||||
|
$( "#fixed-overlay" ).height( 60 );
|
||||||
|
|
||||||
|
start();
|
||||||
|
}, 100 );
|
||||||
|
} );
|
||||||
|
|
||||||
|
} );
|
||||||
|
|
||||||
|
asyncTest( 'Overlays placement and no resizing check', function() {
|
||||||
|
|
||||||
|
var fixedOverlayLocation = new OpenSeadragon.Point( 0.5, 0.6 );
|
||||||
|
|
||||||
|
viewer = OpenSeadragon( {
|
||||||
|
id: 'example-overlays',
|
||||||
|
prefixUrl: '/build/openseadragon/images/',
|
||||||
|
tileSources: '/test/data/testpattern.dzi',
|
||||||
|
springStiffness: 100, // Faster animation = faster tests
|
||||||
|
overlays: [ {
|
||||||
|
x: fixedOverlayLocation.x,
|
||||||
|
y: fixedOverlayLocation.y,
|
||||||
|
id: "fixed-overlay",
|
||||||
|
placement: "CENTER",
|
||||||
|
checkResize: false
|
||||||
|
} ]
|
||||||
|
} );
|
||||||
|
|
||||||
|
function checkFixedOverlayPosition( expectedOffset, contextMessage ) {
|
||||||
|
var viewport = viewer.viewport;
|
||||||
|
|
||||||
|
var expPosition = viewport.viewportToViewerElementCoordinates(
|
||||||
|
new OpenSeadragon.Point( 0.5, 0.6 ) )
|
||||||
|
.apply( Math.floor )
|
||||||
|
.plus( expectedOffset );
|
||||||
|
var actPosition = $( "#fixed-overlay" ).position();
|
||||||
|
equal( actPosition.left, expPosition.x, "Fixed overlay X position mismatch " + contextMessage );
|
||||||
|
equal( actPosition.top, expPosition.y, "Fixed overlay Y position mismatch " + contextMessage );
|
||||||
|
}
|
||||||
|
|
||||||
|
waitForViewer( function() {
|
||||||
|
checkFixedOverlayPosition( new OpenSeadragon.Point( -35, -30 ),
|
||||||
|
"with overlay of size 70,60." );
|
||||||
|
|
||||||
|
$( "#fixed-overlay" ).width( 50 );
|
||||||
|
$( "#fixed-overlay" ).height( 40 );
|
||||||
|
|
||||||
|
// The resizing of the overlays is not detected by the viewer's loop.
|
||||||
|
viewer.forceRedraw();
|
||||||
|
|
||||||
|
setTimeout( function() {
|
||||||
|
checkFixedOverlayPosition( new OpenSeadragon.Point( -35, -30 ),
|
||||||
|
"with overlay of size 50,40." );
|
||||||
|
|
||||||
|
// Restore original size
|
||||||
|
$( "#fixed-overlay" ).width( 70 );
|
||||||
|
$( "#fixed-overlay" ).height( 60 );
|
||||||
|
|
||||||
|
start();
|
||||||
|
}, 100 );
|
||||||
|
} );
|
||||||
|
|
||||||
|
} );
|
||||||
|
|
||||||
|
} )( );
|
||||||
|
Loading…
Reference in New Issue
Block a user