cleaning up drawer APIs

This commit is contained in:
Tom 2023-03-11 11:38:21 -05:00
parent a6e621b562
commit 6159ca7c7c
12 changed files with 317 additions and 475 deletions

View File

@ -37,7 +37,7 @@
/** /**
* @class Drawer * @class Drawer
* @memberof OpenSeadragon * @memberof OpenSeadragon
* @classdesc Handles rendering of tiles for an {@link OpenSeadragon.Viewer}. * @classdesc Default implementation of Drawer for an {@link OpenSeadragon.Viewer}.
* @param {Object} options - Options for this Drawer. * @param {Object} options - Options for this Drawer.
* @param {OpenSeadragon.Viewer} options.viewer - The Viewer that owns this Drawer. * @param {OpenSeadragon.Viewer} options.viewer - The Viewer that owns this Drawer.
* @param {OpenSeadragon.Viewport} options.viewport - Reference to Viewer viewport. * @param {OpenSeadragon.Viewport} options.viewport - Reference to Viewer viewport.
@ -48,55 +48,12 @@ $.Drawer = function(options) {
$.DrawerBase.call(this, options); $.DrawerBase.call(this, options);
$.console.assert( options.viewer, "[Drawer] options.viewer is required" );
//backward compatibility for positional args while preferring more
//idiomatic javascript options object as the only argument
var args = arguments;
if( !$.isPlainObject( options ) ){
options = {
source: args[ 0 ], // Reference to Viewer tile source.
viewport: args[ 1 ], // Reference to Viewer viewport.
element: args[ 2 ] // Parent element.
};
}
$.console.assert( options.viewport, "[Drawer] options.viewport is required" );
$.console.assert( options.element, "[Drawer] options.element is required" );
if ( options.source ) {
$.console.error( "[Drawer] options.source is no longer accepted; use TiledImage instead" );
}
this.viewer = options.viewer;
this.viewport = options.viewport;
this.debugGridColor = typeof options.debugGridColor === 'string' ? [options.debugGridColor] : options.debugGridColor || $.DEFAULT_SETTINGS.debugGridColor;
if (options.opacity) {
$.console.error( "[Drawer] options.opacity is no longer accepted; set the opacity on the TiledImage instead" );
}
this.useCanvas = $.supportsCanvas && ( this.viewer ? this.viewer.useCanvas : true );
/**
* The parent element of this Drawer instance, passed in when the Drawer was created.
* The parent of {@link OpenSeadragon.Drawer#canvas}.
* @member {Element} container
* @memberof OpenSeadragon.Drawer#
*/
this.container = $.getElement( options.element );
/**
* A <canvas> element if the browser supports them, otherwise a <div> element.
* Child element of {@link OpenSeadragon.Drawer#container}.
* @member {Element} canvas
* @memberof OpenSeadragon.Drawer#
*/
this.canvas = $.makeNeutralElement( this.useCanvas ? "canvas" : "div" );
/** /**
* 2d drawing context for {@link OpenSeadragon.Drawer#canvas} if it's a <canvas> element, otherwise null. * 2d drawing context for {@link OpenSeadragon.Drawer#canvas} if it's a <canvas> element, otherwise null.
* @member {Object} context * @member {Object} context
* @memberof OpenSeadragon.Drawer# * @memberof OpenSeadragon.Drawer#
*/ */
this.context = this.useCanvas ? this.canvas.getContext( this.useCanvas.contextType || "2d" ) : null; this.context = this.useCanvas ? this.canvas.getContext( '2d' ) : null;
/** /**
* Sketch canvas used to temporarily draw tiles which cannot be drawn directly * Sketch canvas used to temporarily draw tiles which cannot be drawn directly
@ -105,60 +62,35 @@ $.Drawer = function(options) {
this.sketchCanvas = null; this.sketchCanvas = null;
this.sketchContext = null; this.sketchContext = null;
/**
* @member {Element} element
* @memberof OpenSeadragon.Drawer#
* @deprecated Alias for {@link OpenSeadragon.Drawer#container}.
*/
this.element = this.container;
// We force our container to ltr because our drawing math doesn't work in rtl. // We force our container to ltr because our drawing math doesn't work in rtl.
// This issue only affects our canvas renderer, but we do it always for consistency. // This issue only affects our canvas renderer, but we do it always for consistency.
// Note that this means overlays you want to be rtl need to be explicitly set to rtl. // Note that this means overlays you want to be rtl need to be explicitly set to rtl.
this.container.dir = 'ltr'; this.container.dir = 'ltr';
// check canvas available width and height, set canvas width and height such that the canvas backing store is set to the proper pixel density
if (this.useCanvas) {
var viewportSize = this._calculateCanvasSize();
this.canvas.width = viewportSize.x;
this.canvas.height = viewportSize.y;
}
this.canvas.style.width = "100%";
this.canvas.style.height = "100%";
this.canvas.style.position = "absolute";
$.setElementOpacity( this.canvas, this.opacity, true );
// Allow pointer events to pass through the canvas element so implicit
// pointer capture works on touch devices
$.setElementPointerEventsNone( this.canvas );
$.setElementTouchActionNone( this.canvas );
// explicit left-align
this.container.style.textAlign = "left";
this.container.appendChild( this.canvas );
// Image smoothing for canvas rendering (only if canvas is used). // Image smoothing for canvas rendering (only if canvas is used).
// Canvas default is "true", so this will only be changed if user specified "false". // Canvas default is "true", so this will only be changed if user specified "false".
this._imageSmoothingEnabled = true; this._imageSmoothingEnabled = true;
}; };
$.extend( $.Drawer.prototype, $.DrawerBase.prototype, /** @lends OpenSeadragon.Drawer.prototype */ { $.extend( $.Drawer.prototype, $.DrawerBase.prototype, /** @lends OpenSeadragon.Drawer.prototype */ {
/** /**
* Draws the TiledImage to its Drawer. * Draws the TiledImages
*/ */
draw: function(tiledImage) { draw: function(tiledImages) {
if (tiledImage.opacity !== 0 || tiledImage._preload) { var _this = this;
tiledImage._midDraw = true; this._prepareNewFrame(); // prepare to draw a new frame
this._updateViewport(tiledImage); tiledImages.forEach(function(tiledImage){
tiledImage._midDraw = false; if (tiledImage.opacity !== 0 || tiledImage._preload) {
} tiledImage._midDraw = true;
// Images with opacity 0 should not need to be drawn in future. this._needsDraw = false is set in this._updateViewport() for other images. _this._updateViewportWithTiledImage(tiledImage);
else { tiledImage._midDraw = false;
tiledImage._needsDraw = false; }
} else {
tiledImage._needsDraw = false;
}
});
}, },
/** /**
@ -180,9 +112,51 @@ $.extend( $.Drawer.prototype, $.DrawerBase.prototype, /** @lends OpenSeadragon.D
}, },
/** /**
* Clears the Drawer so it's ready to draw another frame. * Turns image smoothing on or off for this viewer. Note: Ignored in some (especially older) browsers that do not support this property.
*
* @function
* @param {Boolean} [imageSmoothingEnabled] - Whether or not the image is
* drawn smoothly on the canvas; see imageSmoothingEnabled in
* {@link OpenSeadragon.Options} for more explanation.
*/ */
clear: function() { setImageSmoothingEnabled: function(imageSmoothingEnabled){
if ( this.useCanvas ) {
this._imageSmoothingEnabled = imageSmoothingEnabled;
this._updateImageSmoothingEnabled(this.context);
this.viewer.forceRedraw();
}
},
/**
* Draw a rectangle onto the canvas
* @param {OpenSeadragon.Rect} rect
*/
drawDebuggingRect: function(rect) {
if ( this.useCanvas ) {
var context = this.context;
context.save();
context.lineWidth = 2 * $.pixelDensityRatio;
context.strokeStyle = this.debugGridColor[0];
context.fillStyle = this.debugGridColor[0];
context.strokeRect(
rect.x * $.pixelDensityRatio,
rect.y * $.pixelDensityRatio,
rect.width * $.pixelDensityRatio,
rect.height * $.pixelDensityRatio
);
context.restore();
}
},
/**
* @private
* @inner
* Clears the Drawer so it's ready to draw another frame.
*
*/
_prepareNewFrame: function() {
this.canvas.innerHTML = ""; this.canvas.innerHTML = "";
if ( this.useCanvas ) { if ( this.useCanvas ) {
var viewportSize = this._calculateCanvasSize(); var viewportSize = this._calculateCanvasSize();
@ -202,31 +176,33 @@ $.extend( $.Drawer.prototype, $.DrawerBase.prototype, /** @lends OpenSeadragon.D
} }
}, },
_clear: function (useSketch, bounds) { /**
if (!this.useCanvas) { * @private
return; * @inner
} * @param {Boolean} useSketch Whether to clear sketch canvas or main canvas
var context = this._getContext(useSketch); * @param {OpenSeadragon.Rect} [bounds] The rectangle to clear
if (bounds) { */
context.clearRect(bounds.x, bounds.y, bounds.width, bounds.height); _clear: function(useSketch, bounds){
} else { if( this.useCanvas ){
var canvas = context.canvas; var context = this._getContext(useSketch);
context.clearRect(0, 0, canvas.width, canvas.height); if (bounds) {
context.clearRect(bounds.x, bounds.y, bounds.width, bounds.height);
} else {
var canvas = context.canvas;
context.clearRect(0, 0, canvas.width, canvas.height);
}
} }
}, },
/* Methods from TiledImage */ /* Methods from TiledImage */
/** /**
* @private * @private
* @inner * @inner
* Pretty much every other line in this needs to be documented so it's clear * Handles drawing a single TiledImage to the canvas
* how each piece of this routine contributes to the drawing process. That's *
* why there are so many TODO's inside this function.
*/ */
_updateViewport: function(tiledImage) { _updateViewportWithTiledImage: function(tiledImage) {
var _this = this; var _this = this;
tiledImage._needsDraw = false; tiledImage._needsDraw = false;
tiledImage._tilesLoading = 0; tiledImage._tilesLoading = 0;
@ -265,7 +241,7 @@ $.extend( $.Drawer.prototype, $.DrawerBase.prototype, /** @lends OpenSeadragon.D
var infoArray = tiledImage.getTileInfoForDrawing(); var infoArray = tiledImage.getTileInfoForDrawing();
infoArray.forEach(updateTile); infoArray.forEach(updateTile);
this._drawTiles(tiledImage, tiledImage.lastDrawn); this._drawTiles(tiledImage);
}, },
@ -348,7 +324,7 @@ $.extend( $.Drawer.prototype, $.DrawerBase.prototype, /** @lends OpenSeadragon.D
if (lastDrawn.length > 1 && if (lastDrawn.length > 1 &&
imageZoom > tiledImage.smoothTileEdgesMinZoom && imageZoom > tiledImage.smoothTileEdgesMinZoom &&
!tiledImage.iOSDevice && !tiledImage.iOSDevice &&
tiledImage.getRotation(true) % 360 === 0 && // TODO: support tile edge smoothing with tiled image rotation. tiledImage.getRotation(true) % 360 === 0 && // TO DO: support tile edge smoothing with tiled image rotation.
$.supportsCanvas && this.viewer.useCanvas) { $.supportsCanvas && this.viewer.useCanvas) {
// When zoomed in a lot (>100%) the tile edges are visible. // When zoomed in a lot (>100%) the tile edges are visible.
// So we have to composite them at ~100% and scale them up together. // So we have to composite them at ~100% and scale them up together.
@ -356,8 +332,8 @@ $.extend( $.Drawer.prototype, $.DrawerBase.prototype, /** @lends OpenSeadragon.D
useSketch = true; useSketch = true;
sketchScale = tile.getScaleForEdgeSmoothing(); sketchScale = tile.getScaleForEdgeSmoothing();
sketchTranslate = tile.getTranslationForEdgeSmoothing(sketchScale, sketchTranslate = tile.getTranslationForEdgeSmoothing(sketchScale,
this.getCanvasSize(false), this._getCanvasSize(false),
this.getCanvasSize(true)); this._getCanvasSize(true));
} }
var bounds; var bounds;
@ -409,39 +385,42 @@ $.extend( $.Drawer.prototype, $.DrawerBase.prototype, /** @lends OpenSeadragon.D
var usedClip = false; var usedClip = false;
if ( tiledImage._clip ) { if ( tiledImage._clip ) {
this.saveContext(useSketch); this._saveContext(useSketch);
var box = tiledImage.imageToViewportRectangle(tiledImage._clip, true); var box = tiledImage.imageToViewportRectangle(tiledImage._clip, true);
box = box.rotate(-tiledImage.getRotation(true), tiledImage._getRotationPoint(true)); box = box.rotate(-tiledImage.getRotation(true), tiledImage._getRotationPoint(true));
var clipRect = this.viewportToDrawerRectangle(box); var clipRect = this._viewportToDrawerRectangle(box);
if (sketchScale) { if (sketchScale) {
clipRect = clipRect.times(sketchScale); clipRect = clipRect.times(sketchScale);
} }
if (sketchTranslate) { if (sketchTranslate) {
clipRect = clipRect.translate(sketchTranslate); clipRect = clipRect.translate(sketchTranslate);
} }
this.setClip(clipRect, useSketch); this._setClip(clipRect, useSketch);
usedClip = true; usedClip = true;
} }
if (tiledImage._croppingPolygons) { if (tiledImage._croppingPolygons) {
var self = this; var self = this;
this.saveContext(useSketch); this._saveContext(useSketch);
try { try {
var polygons = tiledImage._croppingPolygons.map(function (polygon) { var polygons = tiledImage._croppingPolygons.map(function (polygon) {
return polygon.map(function (coord) { return polygon.map(function (coord) {
var point = tiledImage var point = tiledImage
.imageToViewportCoordinates(coord.x, coord.y, true) .imageToViewportCoordinates(coord.x, coord.y, true)
.rotate(-tiledImage.getRotation(true), tiledImage._getRotationPoint(true)); .rotate(-tiledImage.getRotation(true), tiledImage._getRotationPoint(true));
var clipPoint = self.viewportCoordToDrawerCoord(point); var clipPoint = self._viewportCoordToDrawerCoord(point);
if (sketchScale) { if (sketchScale) {
clipPoint = clipPoint.times(sketchScale); clipPoint = clipPoint.times(sketchScale);
} }
if (sketchTranslate) { // mostly fixes #2312
clipPoint = clipPoint.plus(sketchTranslate);
}
return clipPoint; return clipPoint;
}); });
}); });
this.clipWithPolygons(polygons, useSketch); this._clipWithPolygons(polygons, useSketch);
} catch (e) { } catch (e) {
$.console.error(e); $.console.error(e);
} }
@ -449,7 +428,7 @@ $.extend( $.Drawer.prototype, $.DrawerBase.prototype, /** @lends OpenSeadragon.D
} }
if ( tiledImage.placeholderFillStyle && tiledImage._hasOpaqueTile === false ) { if ( tiledImage.placeholderFillStyle && tiledImage._hasOpaqueTile === false ) {
var placeholderRect = this.viewportToDrawerRectangle(tiledImage.getBounds(true)); var placeholderRect = this._viewportToDrawerRectangle(tiledImage.getBounds(true));
if (sketchScale) { if (sketchScale) {
placeholderRect = placeholderRect.times(sketchScale); placeholderRect = placeholderRect.times(sketchScale);
} }
@ -479,15 +458,16 @@ $.extend( $.Drawer.prototype, $.DrawerBase.prototype, /** @lends OpenSeadragon.D
shouldRoundPositionAndSize = !isAnimating; shouldRoundPositionAndSize = !isAnimating;
} }
// Iterate over the tiles to draw, and draw them
for (var i = lastDrawn.length - 1; i >= 0; i--) { for (var i = lastDrawn.length - 1; i >= 0; i--) {
tile = lastDrawn[ i ]; tile = lastDrawn[ i ];
this.drawTile( tile, tiledImage._drawingHandler, useSketch, sketchScale, this._drawTile( tile, tiledImage._drawingHandler, useSketch, sketchScale,
sketchTranslate, shouldRoundPositionAndSize, tiledImage.source ); sketchTranslate, shouldRoundPositionAndSize, tiledImage.source );
tile.beingDrawn = true; tile.beingDrawn = true;
if( this.viewer ){ if( this.viewer ){
/** /**
* <em>- Needs documentation -</em> * Raised when a tile is drawn to the canvas
* *
* @event tile-drawn * @event tile-drawn
* @memberof OpenSeadragon.Viewer * @memberof OpenSeadragon.Viewer
@ -505,7 +485,7 @@ $.extend( $.Drawer.prototype, $.DrawerBase.prototype, /** @lends OpenSeadragon.D
} }
if ( usedClip ) { if ( usedClip ) {
this.restoreContext( useSketch ); this._restoreContext( useSketch );
} }
if (!sketchScale) { if (!sketchScale) {
@ -584,31 +564,15 @@ $.extend( $.Drawer.prototype, $.DrawerBase.prototype, /** @lends OpenSeadragon.D
/* Methods from Tile */ /* Methods from Tile */
/**
* This function converts the given point from to the drawer coordinate by
* multiplying it with the pixel density.
* This function does not take rotation into account, thus assuming provided
* point is at 0 degree.
* @param {OpenSeadragon.Point} point - the pixel point to convert
* @returns {OpenSeadragon.Point} Point in drawer coordinate system.
*/
viewportCoordToDrawerCoord: function(point) {
var vpPoint = this.viewport.pixelFromPointNoRotate(point, true);
return new $.Point(
vpPoint.x * $.pixelDensityRatio,
vpPoint.y * $.pixelDensityRatio
);
},
/** /**
* @private
* @inner
* This function will create multiple polygon paths on the drawing context by provided polygons, * This function will create multiple polygon paths on the drawing context by provided polygons,
* then clip the context to the paths. * then clip the context to the paths.
* @param {OpenSeadragon.Point[][]} polygons - an array of polygons. A polygon is an array of OpenSeadragon.Point * @param {OpenSeadragon.Point[][]} polygons - an array of polygons. A polygon is an array of OpenSeadragon.Point
* @param {Boolean} useSketch - Whether to use the sketch canvas or not. * @param {Boolean} useSketch - Whether to use the sketch canvas or not.
*/ */
clipWithPolygons: function (polygons, useSketch) { _clipWithPolygons: function (polygons, useSketch) {
if (!this.useCanvas) { if (!this.useCanvas) {
return; return;
} }
@ -622,31 +586,9 @@ $.extend( $.Drawer.prototype, $.DrawerBase.prototype, /** @lends OpenSeadragon.D
context.clip(); context.clip();
}, },
/**
* Scale from OpenSeadragon viewer rectangle to drawer rectangle
* (ignoring rotation)
* @param {OpenSeadragon.Rect} rectangle - The rectangle in viewport coordinate system.
* @returns {OpenSeadragon.Rect} Rectangle in drawer coordinate system.
*/
viewportToDrawerRectangle: function(rectangle) {
var topLeft = this.viewport.pixelFromPointNoRotate(rectangle.getTopLeft(), true);
var size = this.viewport.deltaPixelsFromPointsNoRotate(rectangle.getSize(), true);
return new $.Rect(
topLeft.x * $.pixelDensityRatio,
topLeft.y * $.pixelDensityRatio,
size.x * $.pixelDensityRatio,
size.y * $.pixelDensityRatio
);
},
/** /**
* @private
* @inner
* Draws the given tile. * Draws the given tile.
* @param {OpenSeadragon.Tile} tile - The tile to draw. * @param {OpenSeadragon.Tile} tile - The tile to draw.
* @param {Function} drawingHandler - Method for firing the drawing event if using canvas. * @param {Function} drawingHandler - Method for firing the drawing event if using canvas.
@ -660,35 +602,37 @@ $.extend( $.Drawer.prototype, $.DrawerBase.prototype, /** @lends OpenSeadragon.D
* context. * context.
* @param {OpenSeadragon.TileSource} source - The source specification of the tile. * @param {OpenSeadragon.TileSource} source - The source specification of the tile.
*/ */
drawTile: function( tile, drawingHandler, useSketch, scale, translate, shouldRoundPositionAndSize, source) { _drawTile: function( tile, drawingHandler, useSketch, scale, translate, shouldRoundPositionAndSize, source) {
$.console.assert(tile, '[Drawer.drawTile] tile is required'); $.console.assert(tile, '[Drawer._drawTile] tile is required');
$.console.assert(drawingHandler, '[Drawer.drawTile] drawingHandler is required'); $.console.assert(drawingHandler, '[Drawer._drawTile] drawingHandler is required');
if (this.useCanvas) { if (this.useCanvas) {
var context = this._getContext(useSketch); var context = this._getContext(useSketch);
scale = scale || 1; scale = scale || 1;
this.drawTileToCanvas(tile, context, drawingHandler, scale, translate, shouldRoundPositionAndSize, source); this._drawTileToCanvas(tile, context, drawingHandler, scale, translate, shouldRoundPositionAndSize, source);
} else { } else {
tile.drawTileToHTML( tile, this.canvas ); tile._drawTileToHTML( tile, this.canvas );
} }
}, },
/** /**
* Renders the tile in a canvas-based context. * @private
* @function * @inner
* @param {OpenSeadragon.Tile} tile - the tile to draw to the canvas * Renders the tile in a canvas-based context.
* @param {Canvas} context * @function
* @param {Function} drawingHandler - Method for firing the drawing event. * @param {OpenSeadragon.Tile} tile - the tile to draw to the canvas
* drawingHandler({context, tile, rendered}) * @param {Canvas} context
* where <code>rendered</code> is the context with the pre-drawn image. * @param {Function} drawingHandler - Method for firing the drawing event.
* @param {Number} [scale=1] - Apply a scale to position and size * drawingHandler({context, tile, rendered})
* @param {OpenSeadragon.Point} [translate] - A translation vector * where <code>rendered</code> is the context with the pre-drawn image.
* @param {Boolean} [shouldRoundPositionAndSize] - Tells whether to round * @param {Number} [scale=1] - Apply a scale to position and size
* position and size of tiles supporting alpha channel in non-transparency * @param {OpenSeadragon.Point} [translate] - A translation vector
* context. * @param {Boolean} [shouldRoundPositionAndSize] - Tells whether to round
* @param {OpenSeadragon.TileSource} source - The source specification of the tile. * position and size of tiles supporting alpha channel in non-transparency
*/ * context.
drawTileToCanvas: function( tile, context, drawingHandler, scale, translate, shouldRoundPositionAndSize, source) { * @param {OpenSeadragon.TileSource} source - The source specification of the tile.
*/
_drawTileToCanvas: function( tile, context, drawingHandler, scale, translate, shouldRoundPositionAndSize, source) {
var position = tile.position.times($.pixelDensityRatio), var position = tile.position.times($.pixelDensityRatio),
size = tile.size.times($.pixelDensityRatio), size = tile.size.times($.pixelDensityRatio),
@ -696,7 +640,7 @@ $.extend( $.Drawer.prototype, $.DrawerBase.prototype, /** @lends OpenSeadragon.D
if (!tile.context2D && !tile.cacheImageRecord) { if (!tile.context2D && !tile.cacheImageRecord) {
$.console.warn( $.console.warn(
'[Drawer.drawTileToCanvas] attempting to draw tile %s when it\'s not cached', '[Drawer._drawTileToCanvas] attempting to draw tile %s when it\'s not cached',
tile.toString()); tile.toString());
return; return;
} }
@ -782,15 +726,17 @@ $.extend( $.Drawer.prototype, $.DrawerBase.prototype, /** @lends OpenSeadragon.D
}, },
/** /**
* Renders the tile in an html container. * @private
* @function * @inner
* @param {OpenSeadragon.Tile} tile * Renders the tile in an html container.
* @param {Element} container * @function
*/ * @param {OpenSeadragon.Tile} tile
drawTileToHTML: function( tile, container ) { * @param {Element} container
*/
_drawTileToHTML: function( tile, container ) {
if (!tile.cacheImageRecord) { if (!tile.cacheImageRecord) {
$.console.warn( $.console.warn(
'[Drawer.drawTileToHTML] attempting to draw tile %s when it\'s not cached', '[Drawer._drawTileToHTML] attempting to draw tile %s when it\'s not cached',
tile.toString()); tile.toString());
return; return;
} }
@ -840,6 +786,13 @@ $.extend( $.Drawer.prototype, $.DrawerBase.prototype, /** @lends OpenSeadragon.D
$.setElementOpacity( tile.element, tile.opacity ); $.setElementOpacity( tile.element, tile.opacity );
}, },
/**
* @private
* @inner
* Get the context of the main or sketch canvas
* @param {Boolean} useSketch
* @returns
*/
_getContext: function( useSketch ) { _getContext: function( useSketch ) {
var context = this.context; var context = this.context;
if ( useSketch ) { if ( useSketch ) {
@ -872,8 +825,14 @@ $.extend( $.Drawer.prototype, $.DrawerBase.prototype, /** @lends OpenSeadragon.D
return context; return context;
}, },
// private /**
saveContext: function( useSketch ) { * @private
* @inner
* Save the context of the main or sketch canvas
* @param {Boolean} useSketch
* @returns
*/
_saveContext: function( useSketch ) {
if (!this.useCanvas) { if (!this.useCanvas) {
return; return;
} }
@ -881,8 +840,14 @@ $.extend( $.Drawer.prototype, $.DrawerBase.prototype, /** @lends OpenSeadragon.D
this._getContext( useSketch ).save(); this._getContext( useSketch ).save();
}, },
// private /**
restoreContext: function( useSketch ) { * @private
* @inner
* Restore the context of the main or sketch canvas
* @param {Boolean} useSketch
* @returns
*/
_restoreContext: function( useSketch ) {
if (!this.useCanvas) { if (!this.useCanvas) {
return; return;
} }
@ -891,7 +856,7 @@ $.extend( $.Drawer.prototype, $.DrawerBase.prototype, /** @lends OpenSeadragon.D
}, },
// private // private
setClip: function(rect, useSketch) { _setClip: function(rect, useSketch) {
if (!this.useCanvas) { if (!this.useCanvas) {
return; return;
} }
@ -1118,42 +1083,6 @@ $.extend( $.Drawer.prototype, $.DrawerBase.prototype, /** @lends OpenSeadragon.D
context.restore(); context.restore();
}, },
// private
debugRect: function(rect) {
if ( this.useCanvas ) {
var context = this.context;
context.save();
context.lineWidth = 2 * $.pixelDensityRatio;
context.strokeStyle = this.debugGridColor[0];
context.fillStyle = this.debugGridColor[0];
context.strokeRect(
rect.x * $.pixelDensityRatio,
rect.y * $.pixelDensityRatio,
rect.width * $.pixelDensityRatio,
rect.height * $.pixelDensityRatio
);
context.restore();
}
},
/**
* Turns image smoothing on or off for this viewer. Note: Ignored in some (especially older) browsers that do not support this property.
*
* @function
* @param {Boolean} [imageSmoothingEnabled] - Whether or not the image is
* drawn smoothly on the canvas; see imageSmoothingEnabled in
* {@link OpenSeadragon.Options} for more explanation.
*/
setImageSmoothingEnabled: function(imageSmoothingEnabled){
if ( this.useCanvas ) {
this._imageSmoothingEnabled = imageSmoothingEnabled;
this._updateImageSmoothingEnabled(this.context);
this.viewer.forceRedraw();
}
},
// private // private
_updateImageSmoothingEnabled: function(context){ _updateImageSmoothingEnabled: function(context){
context.msImageSmoothingEnabled = this._imageSmoothingEnabled; context.msImageSmoothingEnabled = this._imageSmoothingEnabled;
@ -1161,16 +1090,25 @@ $.extend( $.Drawer.prototype, $.DrawerBase.prototype, /** @lends OpenSeadragon.D
}, },
/** /**
* @private
* @inner
* Get the canvas size * Get the canvas size
* @param {Boolean} sketch If set to true return the size of the sketch canvas * @param {Boolean} sketch If set to true return the size of the sketch canvas
* @returns {OpenSeadragon.Point} The size of the canvas * @returns {OpenSeadragon.Point} The size of the canvas
*/ */
getCanvasSize: function(sketch) { _getCanvasSize: function(sketch) {
var canvas = this._getContext(sketch).canvas; var canvas = this._getContext(sketch).canvas;
return new $.Point(canvas.width, canvas.height); return new $.Point(canvas.width, canvas.height);
}, },
getCanvasCenter: function() { /**
* @private
* @inner
* Get the canvas center
* @param {Boolean} sketch If set to true return the center point of the sketch canvas
* @returns {OpenSeadragon.Point} The center point of the canvas
*/
_getCanvasCenter: function() {
return new $.Point(this.canvas.width / 2, this.canvas.height / 2); return new $.Point(this.canvas.width / 2, this.canvas.height / 2);
}, },
@ -1178,7 +1116,7 @@ $.extend( $.Drawer.prototype, $.DrawerBase.prototype, /** @lends OpenSeadragon.D
_offsetForRotation: function(options) { _offsetForRotation: function(options) {
var point = options.point ? var point = options.point ?
options.point.times($.pixelDensityRatio) : options.point.times($.pixelDensityRatio) :
this.getCanvasCenter(); this._getCanvasCenter();
var context = this._getContext(options.useSketch); var context = this._getContext(options.useSketch);
context.save(); context.save();
@ -1198,7 +1136,7 @@ $.extend( $.Drawer.prototype, $.DrawerBase.prototype, /** @lends OpenSeadragon.D
options = options || {}; options = options || {};
var point = options.point ? var point = options.point ?
options.point.times($.pixelDensityRatio) : options.point.times($.pixelDensityRatio) :
this.getCanvasCenter(); this._getCanvasCenter();
var context = this._getContext(options.useSketch); var context = this._getContext(options.useSketch);
context.translate(point.x, 0); context.translate(point.x, 0);
@ -1240,90 +1178,7 @@ $.extend( $.Drawer.prototype, $.DrawerBase.prototype, /** @lends OpenSeadragon.D
}; };
}, },
// deprecated functions
// deprecated
addOverlay: function( element, location, placement, onDraw ) {
$.console.error("drawer.addOverlay is deprecated. Use viewer.addOverlay instead.");
this.viewer.addOverlay( element, location, placement, onDraw );
return this;
},
// deprecated
updateOverlay: function( element, location, placement ) {
$.console.error("drawer.updateOverlay is deprecated. Use viewer.updateOverlay instead.");
this.viewer.updateOverlay( element, location, placement );
return this;
},
// deprecated
removeOverlay: function( element ) {
$.console.error("drawer.removeOverlay is deprecated. Use viewer.removeOverlay instead.");
this.viewer.removeOverlay( element );
return this;
},
// deprecated
clearOverlays: function() {
$.console.error("drawer.clearOverlays is deprecated. Use viewer.clearOverlays instead.");
this.viewer.clearOverlays();
return this;
},
// deprecated
needsUpdate: function() {
$.console.error( "[Drawer.needsUpdate] this function is deprecated. Use World.needsDraw instead." );
return this.viewer.world.needsDraw();
},
// deprecated
numTilesLoaded: function() {
$.console.error( "[Drawer.numTilesLoaded] this function is deprecated. Use TileCache.numTilesLoaded instead." );
return this.viewer.tileCache.numTilesLoaded();
},
// deprecated
reset: function() {
$.console.error( "[Drawer.reset] this function is deprecated. Use World.resetItems instead." );
this.viewer.world.resetItems();
return this;
},
// deprecated
update: function() {
$.console.error( "[Drawer.update] this function is deprecated. Use Drawer.clear and World.draw instead." );
this.clear();
this.viewer.world.draw();
return this;
},
/**
* Set the opacity of the drawer.
* @param {Number} opacity
* @returns {OpenSeadragon.Drawer} Chainable.
*/
setOpacity: function( opacity ) {
$.console.error("drawer.setOpacity is deprecated. Use tiledImage.setOpacity instead.");
var world = this.viewer.world;
for (var i = 0; i < world.getItemCount(); i++) {
world.getItemAt( i ).setOpacity( opacity );
}
return this;
},
/**
* Get the opacity of the drawer.
* @returns {Number}
*/
getOpacity: function() {
$.console.error("drawer.getOpacity is deprecated. Use tiledImage.getOpacity instead.");
var world = this.viewer.world;
var maxOpacity = 0;
for (var i = 0; i < world.getItemCount(); i++) {
var opacity = world.getItemAt( i ).getOpacity();
if ( opacity > maxOpacity ) {
maxOpacity = opacity;
}
}
return maxOpacity;
},
}); });

View File

@ -98,6 +98,7 @@ $.DrawerBase = function( options ) {
*/ */
this.element = this.container; this.element = this.container;
// TO DO: Does this need to be in DrawerBase, or only in Drawer implementations?
// We force our container to ltr because our drawing math doesn't work in rtl. // We force our container to ltr because our drawing math doesn't work in rtl.
// This issue only affects our canvas renderer, but we do it always for consistency. // This issue only affects our canvas renderer, but we do it always for consistency.
// Note that this means overlays you want to be rtl need to be explicitly set to rtl. // Note that this means overlays you want to be rtl need to be explicitly set to rtl.
@ -123,10 +124,6 @@ $.DrawerBase = function( options ) {
this.container.style.textAlign = "left"; this.container.style.textAlign = "left";
this.container.appendChild( this.canvas ); this.container.appendChild( this.canvas );
// Image smoothing for canvas rendering (only if canvas is used).
// Canvas default is "true", so this will only be changed if user specified "false".
this._imageSmoothingEnabled = true;
this._checkForAPIOverrides(); this._checkForAPIOverrides();
}; };
@ -134,14 +131,10 @@ $.DrawerBase = function( options ) {
$.DrawerBase.prototype = { $.DrawerBase.prototype = {
// Drawer implementaions must define the next four methods. These are called // Drawer implementaions must define the next four methods. These are called
// by core OSD, and forcing overrides (even for nullop methods) makes the // by core OSD and/or public APIs, and forcing overrides (even for nullop methods) makes the
// behavior of the implementations explicitly clear in the code. // behavior of the implementations explicitly clear in the code.
// Whether these have been overridden by child classes is checked in the // Whether these have been overridden by child classes is checked in the
// constructor (via _checkForAPIOverrides). It could make sense to consolidate // constructor (via _checkForAPIOverrides).
// these a bit (e.g. by making `draw` take an array of `TiledImage`s and
// clearing the view as needed, rather than the existing pattern of
// `drawer.clear(); world.draw()` in the calling code), but they have been
// left as-is to maintain backwards compatibility.
/** /**
* @param tiledImage the TiledImage that is ready to be drawn * @param tiledImage the TiledImage that is ready to be drawn
@ -164,13 +157,6 @@ $.DrawerBase.prototype = {
$.console.error('Drawer.destroy must be implemented by child class'); $.console.error('Drawer.destroy must be implemented by child class');
}, },
/**
* Clears the Drawer so it's ready to draw another frame.
*/
clear: function() {
$.console.error('Drawer.clear must be implemented by child class');
},
/** /**
* Turns image smoothing on or off for this viewer. Note: Ignored in some (especially older) browsers that do not support this property. * Turns image smoothing on or off for this viewer. Note: Ignored in some (especially older) browsers that do not support this property.
* *
@ -184,8 +170,26 @@ $.DrawerBase.prototype = {
}, },
/** /**
* Ensures that child classes have provided implementations for API methods * Optional public API to draw a rectangle (e.g. for debugging purposes)
* draw, canRotate, destroy, and clear. Throws an exception if the original * Child classes can override this method if they wish to support this
* @param {OpenSeadragon.Rect} rect
*/
drawDebuggingRect: function(rect) {
$.console.warn('[drawer].drawDebuggingRect is not implemented by this drawer');
},
// Deprecated functions
clear: function(){
$.console.warn('[drawer].clear() is deprecated. The drawer is responsible for clearing itself as needed before drawing tiles.');
},
// Private functions
/**
* @private
* @inner
* Ensures that child classes have provided implementations for public API methods
* draw, canRotate, destroy, and setImageSmoothinEnabled. Throws an exception if the original
* placeholder methods are still in place. * placeholder methods are still in place.
*/ */
_checkForAPIOverrides: function(){ _checkForAPIOverrides: function(){
@ -198,21 +202,24 @@ $.DrawerBase.prototype = {
if(this.destroy === $.DrawerBase.prototype.destroy){ if(this.destroy === $.DrawerBase.prototype.destroy){
throw("[drawer].destroy must be implemented by child class"); throw("[drawer].destroy must be implemented by child class");
} }
if(this.clear === $.DrawerBase.prototype.clear){
throw("[drawer].clear must be implemented by child class");
}
if(this.setImageSmoothingEnabled === $.DrawerBase.prototype.setImageSmoothingEnabled){ if(this.setImageSmoothingEnabled === $.DrawerBase.prototype.setImageSmoothingEnabled){
throw("[drawer].setImageSmoothingEnabled must be implemented by child class"); throw("[drawer].setImageSmoothingEnabled must be implemented by child class");
} }
}, },
// Utility functions internal API
/** /**
* @private
* @inner
* Scale from OpenSeadragon viewer rectangle to drawer rectangle * Scale from OpenSeadragon viewer rectangle to drawer rectangle
* (ignoring rotation) * (ignoring rotation)
* @param {OpenSeadragon.Rect} rectangle - The rectangle in viewport coordinate system. * @param {OpenSeadragon.Rect} rectangle - The rectangle in viewport coordinate system.
* @returns {OpenSeadragon.Rect} Rectangle in drawer coordinate system. * @returns {OpenSeadragon.Rect} Rectangle in drawer coordinate system.
*/ */
viewportToDrawerRectangle: function(rectangle) { _viewportToDrawerRectangle: function(rectangle) {
var topLeft = this.viewport.pixelFromPointNoRotate(rectangle.getTopLeft(), true); var topLeft = this.viewport.pixelFromPointNoRotate(rectangle.getTopLeft(), true);
var size = this.viewport.deltaPixelsFromPointsNoRotate(rectangle.getSize(), true); var size = this.viewport.deltaPixelsFromPointsNoRotate(rectangle.getSize(), true);
@ -225,6 +232,8 @@ $.DrawerBase.prototype = {
}, },
/** /**
* @private
* @inner
* This function converts the given point from to the drawer coordinate by * This function converts the given point from to the drawer coordinate by
* multiplying it with the pixel density. * multiplying it with the pixel density.
* This function does not take rotation into account, thus assuming provided * This function does not take rotation into account, thus assuming provided
@ -232,7 +241,7 @@ $.DrawerBase.prototype = {
* @param {OpenSeadragon.Point} point - the pixel point to convert * @param {OpenSeadragon.Point} point - the pixel point to convert
* @returns {OpenSeadragon.Point} Point in drawer coordinate system. * @returns {OpenSeadragon.Point} Point in drawer coordinate system.
*/ */
viewportCoordToDrawerCoord: function(point) { _viewportCoordToDrawerCoord: function(point) {
var vpPoint = this.viewport.pixelFromPointNoRotate(point, true); var vpPoint = this.viewport.pixelFromPointNoRotate(point, true);
return new $.Point( return new $.Point(
vpPoint.x * $.pixelDensityRatio, vpPoint.x * $.pixelDensityRatio,
@ -240,8 +249,13 @@ $.DrawerBase.prototype = {
); );
}, },
/**
// private * @private
* @inner
* Calculate width and height of the canvas based on viewport dimensions
* and pixelDensityRatio
* @returns {Dictionary} {x, y} size of the canvas
*/
_calculateCanvasSize: function() { _calculateCanvasSize: function() {
var pixelDensityRatio = $.pixelDensityRatio; var pixelDensityRatio = $.pixelDensityRatio;
var viewportSize = this.viewport.getContainerSize(); var viewportSize = this.viewport.getContainerSize();
@ -252,86 +266,6 @@ $.DrawerBase.prototype = {
}; };
}, },
/* Deprecated Functions */
// deprecated
addOverlay: function( element, location, placement, onDraw ) {
$.console.error("drawer.addOverlay is deprecated. Use viewer.addOverlay instead.");
this.viewer.addOverlay( element, location, placement, onDraw );
return this;
},
// deprecated
updateOverlay: function( element, location, placement ) {
$.console.error("drawer.updateOverlay is deprecated. Use viewer.updateOverlay instead.");
this.viewer.updateOverlay( element, location, placement );
return this;
},
// deprecated
removeOverlay: function( element ) {
$.console.error("drawer.removeOverlay is deprecated. Use viewer.removeOverlay instead.");
this.viewer.removeOverlay( element );
return this;
},
// deprecated
clearOverlays: function() {
$.console.error("drawer.clearOverlays is deprecated. Use viewer.clearOverlays instead.");
this.viewer.clearOverlays();
return this;
},
// deprecated
needsUpdate: function() {
$.console.error( "[Drawer.needsUpdate] this function is deprecated. Use World.needsDraw instead." );
return this.viewer.world.needsDraw();
},
// deprecated
numTilesLoaded: function() {
$.console.error( "[Drawer.numTilesLoaded] this function is deprecated. Use TileCache.numTilesLoaded instead." );
return this.viewer.tileCache.numTilesLoaded();
},
// deprecated
reset: function() {
$.console.error( "[Drawer.reset] this function is deprecated. Use World.resetItems instead." );
this.viewer.world.resetItems();
return this;
},
// deprecated
update: function() {
$.console.error( "[Drawer.update] this function is deprecated. Use Drawer.clear and World.draw instead." );
this.clear();
this.viewer.world.draw();
return this;
},
// deprecated
setOpacity: function( opacity ) {
$.console.error("drawer.setOpacity is deprecated. Use tiledImage.setOpacity instead.");
var world = this.viewer.world;
for (var i = 0; i < world.getItemCount(); i++) {
world.getItemAt( i ).setOpacity( opacity );
}
return this;
},
// deprecated
getOpacity: function() {
$.console.error("drawer.getOpacity is deprecated. Use tiledImage.getOpacity instead.");
var world = this.viewer.world;
var maxOpacity = 0;
for (var i = 0; i < world.getItemCount(); i++) {
var opacity = world.getItemAt( i ).getOpacity();
if ( opacity > maxOpacity ) {
maxOpacity = opacity;
}
}
return maxOpacity;
},
}; };
Object.defineProperty($.DrawerBase.prototype, "isOpenSeadragonDrawer", { Object.defineProperty($.DrawerBase.prototype, "isOpenSeadragonDrawer", {

View File

@ -310,7 +310,6 @@ $.extend( $.Navigator.prototype, $.EventSource.prototype, $.Viewer.prototype, /*
this.viewport.resize( containerSize, true ); this.viewport.resize( containerSize, true );
this.viewport.goHome(true); this.viewport.goHome(true);
this.oldContainerSize = containerSize; this.oldContainerSize = containerSize;
this.drawer.clear();
this.world.draw(); this.world.draw();
} }
} }

View File

@ -1148,6 +1148,10 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
}; };
}, },
/**
*
* @returns {Array} Array of Tiles within the viewport which should be drawn
*/
getTileInfoForDrawing: function(){ getTileInfoForDrawing: function(){
return this._tilesToDraw; return this._tilesToDraw;
}, },
@ -1252,9 +1256,6 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
} else { } else {
this._setFullyLoaded(this._tilesLoading === 0); this._setFullyLoaded(this._tilesLoading === 0);
} }
// return bestTile;
}, },
/** /**

View File

@ -3738,7 +3738,6 @@ function updateOnce( viewer ) {
function drawWorld( viewer ) { function drawWorld( viewer ) {
viewer.imageLoader.clear(); viewer.imageLoader.clear();
viewer.drawer.clear();
viewer.world.draw(); viewer.world.draw();
/** /**

View File

@ -711,6 +711,8 @@ $.Viewport.prototype = {
if(constraints){ if(constraints){
this.panTo(center, false); this.panTo(center, false);
newZoom = this._applyZoomConstraints(newZoom);
this.zoomTo(newZoom, null, false); this.zoomTo(newZoom, null, false);
var constrainedBounds = this.getConstrainedBounds(); var constrainedBounds = this.getConstrainedBounds();

View File

@ -256,10 +256,7 @@ $.extend( $.World.prototype, $.EventSource.prototype, /** @lends OpenSeadragon.W
* Draws all items. * Draws all items.
*/ */
draw: function() { draw: function() {
for ( var i = 0; i < this._items.length; i++ ) { this.viewer.drawer.draw(this._items);
this.viewer.drawer.draw(this._items[i]);
}
this._needsDraw = false; this._needsDraw = false;
}, },

View File

@ -131,8 +131,8 @@
var box = new OpenSeadragon.Rect(margins.left, margins.top, var box = new OpenSeadragon.Rect(margins.left, margins.top,
$('#contentDiv').width() - (margins.left + margins.right), $('#contentDiv').width() - (margins.left + margins.right),
$('#contentDiv').height() - (margins.top + margins.bottom)); $('#contentDiv').height() - (margins.top + margins.bottom));
// if drawDebuggingRect is implemented, use it to show the box
self.viewer.drawer.debugRect(box); self.viewer.drawer.drawDebuggingRect(box);
}); });
} }

View File

@ -106,7 +106,9 @@ export class ThreeJSDrawer extends OpenSeadragon.DrawerBase{
} }
// Public API required by all Drawer implementations // Public API required by all Drawer implementations
/**
* Clean up the renderer, removing all resources
*/
destroy(){ destroy(){
// clear all resources used by the renderer, geometries, textures etc // clear all resources used by the renderer, geometries, textures etc
@ -123,26 +125,61 @@ export class ThreeJSDrawer extends OpenSeadragon.DrawerBase{
this._camera = null; this._camera = null;
} }
clear(){
//not needed by this implementation // Public API required by all Drawer implementations
} /**
*
* @returns true if the drawer supports rotation
*/
canRotate(){ canRotate(){
return true; return true;
} }
draw(tiledImage){
// Public API required by all Drawer implementations
/**
*
* @param {Array} tiledImages Array of TiledImage objects to draw
*/
draw(tiledImages){
// actual drawing is handled by event listeneners // actual drawing is handled by event listeneners
// just mark this tiledImage as having been drawn (possibly unnecessary) // just mark the tiledImages as having been drawn (possibly unnecessary)
tiledImage._needsDraw = false; tiledImages.forEach(tiledImage => tiledImage._needsDraw = false);
} }
// Public API required by all Drawer implementations
/**
* Set the context2d imageSmoothingEnabled parameter
* @param {Boolean} enabled
*/
setImageSmoothingEnabled(enabled){ setImageSmoothingEnabled(enabled){
this._clippingContext.imageSmoothingEnabled = enabled; this._clippingContext.imageSmoothingEnabled = enabled;
this._outputContext.imageSmoothingEnabled = enabled; this._outputContext.imageSmoothingEnabled = enabled;
} }
/**
* Draw a rect onto the output canvas for debugging purposes
* @param {OpenSeadragon.Rect} rect
*/
drawDebuggingRect(rect){
let context = this._outputContext;
context.save();
context.lineWidth = 2 * OpenSeadragon.pixelDensityRatio;
context.strokeStyle = this.debugGridColor[0];
context.fillStyle = this.debugGridColor[0];
context.strokeRect(
rect.x * OpenSeadragon.pixelDensityRatio,
rect.y * OpenSeadragon.pixelDensityRatio,
rect.width * OpenSeadragon.pixelDensityRatio,
rect.height * OpenSeadragon.pixelDensityRatio
);
context.restore();
}
// Private methods // Private methods
_setupRenderer(){ _setupRenderer(){
//to do: test support for pages of sequence mode
let viewerBounds = this.viewer.viewport.getBoundsNoRotate(); let viewerBounds = this.viewer.viewport.getBoundsNoRotate();
this._camera = new THREE.OrthographicCamera( this._camera = new THREE.OrthographicCamera(
@ -171,13 +208,6 @@ export class ThreeJSDrawer extends OpenSeadragon.DrawerBase{
this.viewer.addHandler("viewport-change", () => this._viewportChangeHandler()); this.viewer.addHandler("viewport-change", () => this._viewportChangeHandler());
this.viewer.addHandler("home", () => this._viewportChangeHandler()); this.viewer.addHandler("home", () => this._viewportChangeHandler());
// this.viewer.world.addHandler("item-index-change", () => this.renderFrame());
// this.viewer.addHandler("crop-change", () => this.renderFrame());
// this.viewer.addHandler("clip-change", () => this.renderFrame());
// this.viewer.addHandler("opacity-change", () => this.renderFrame());
// this.viewer.addHandler("composite-operation-change", () => this.renderFrame());
this.viewer.addHandler("update-viewport", () => this.renderFrame()); this.viewer.addHandler("update-viewport", () => this.renderFrame());
this._viewportChangeHandler(); this._viewportChangeHandler();
@ -476,7 +506,7 @@ export class ThreeJSDrawer extends OpenSeadragon.DrawerBase{
if(item._clip){ if(item._clip){
var box = item.imageToViewportRectangle(item._clip, true); var box = item.imageToViewportRectangle(item._clip, true);
var rect = this.viewportToDrawerRectangle(box); var rect = this._viewportToDrawerRectangle(box);
this._clippingContext.beginPath(); this._clippingContext.beginPath();
this._clippingContext.rect(rect.x, rect.y, rect.width, rect.height); this._clippingContext.rect(rect.x, rect.y, rect.width, rect.height);
this._clippingContext.clip(); this._clippingContext.clip();
@ -486,7 +516,7 @@ export class ThreeJSDrawer extends OpenSeadragon.DrawerBase{
return polygon.map(function (coord) { return polygon.map(function (coord) {
let point = item.imageToViewportCoordinates(coord.x, coord.y, true) let point = item.imageToViewportCoordinates(coord.x, coord.y, true)
.rotate(_this.viewer.viewport.getRotation(true), _this.viewer.viewport.getCenter(true)); .rotate(_this.viewer.viewport.getRotation(true), _this.viewer.viewport.getCenter(true));
let clipPoint = _this.viewportCoordToDrawerCoord(point); let clipPoint = _this._viewportCoordToDrawerCoord(point);
return clipPoint; return clipPoint;
}); });
}); });
@ -625,6 +655,7 @@ export class ThreeJSDrawer extends OpenSeadragon.DrawerBase{
context.restore(); context.restore();
} }
// private
_drawDebugInfo( tiledImage ) { _drawDebugInfo( tiledImage ) {
let scene = this._tiledImageMap[tiledImage[this._uuid]]; let scene = this._tiledImageMap[tiledImage[this._uuid]];
let level = scene.userData.currentLevel; let level = scene.userData.currentLevel;
@ -641,25 +672,6 @@ export class ThreeJSDrawer extends OpenSeadragon.DrawerBase{
} }
} }
// private
_debugRect(rect) {
if ( this.useCanvas ) {
var context = this._outputContext;
context.save();
context.lineWidth = 2 * OpenSeadragon.pixelDensityRatio;
context.strokeStyle = this.debugGridColor[0];
context.fillStyle = this.debugGridColor[0];
context.strokeRect(
rect.x * OpenSeadragon.pixelDensityRatio,
rect.y * OpenSeadragon.pixelDensityRatio,
rect.width * OpenSeadragon.pixelDensityRatio,
rect.height * OpenSeadragon.pixelDensityRatio
);
context.restore();
}
}
// private // private
_restoreRotationChanges() { _restoreRotationChanges() {

View File

@ -111,7 +111,7 @@
<div id="image-picker"> <div id="image-picker">
<h3>Image options (drag and drop to re-order images)</h3> <h3>Image options (drag and drop to re-order images)</h3>
<div class="image-options"> <!-- <div class="image-options">
<span class="ui-icon ui-icon-arrowthick-2-n-s"></span> <span class="ui-icon ui-icon-arrowthick-2-n-s"></span>
<label><input type="checkbox" checked data-image="rainbow" class="toggle"> Rainbow Grid</label> <label><input type="checkbox" checked data-image="rainbow" class="toggle"> Rainbow Grid</label>
<div class="option-grid"> <div class="option-grid">
@ -159,7 +159,7 @@
<label>Composite: <select data-image="bblue" data-field="composite"></select></label> <label>Composite: <select data-image="bblue" data-field="composite"></select></label>
<label>Wrapping: <select data-image="bblue" data-field="wrapping"></select></label> <label>Wrapping: <select data-image="bblue" data-field="wrapping"></select></label>
</div> </div>
</div> </div> -->
</div> </div>

View File

@ -10,11 +10,24 @@ const sources = {
type:'image', type:'image',
url: "../data/BBlue.png", url: "../data/BBlue.png",
}, },
"duomo":"https://openseadragon.github.io/example-images/duomo/duomo.dzi",
}
const labels = {
rainbow: 'Rainbow Grid',
leaves: 'Leaves',
bblue: 'Blue B',
duomo: 'Duomo',
} }
var viewer = window.viewer = OpenSeadragon({ var viewer = window.viewer = OpenSeadragon({
id: "contentDiv", id: "contentDiv",
prefixUrl: "../../build/openseadragon/images/", prefixUrl: "../../build/openseadragon/images/",
// minZoomImageRatio:0.8,
// maxZoomPixelRatio:0.5,
minZoomImageRatio:0.01, minZoomImageRatio:0.01,
maxZoomPixelRatio:100,
smoothTileEdgesMinZoom:1.1,
crossOriginPolicy: 'Anonymous',
ajaxWithCredentials: false
}); });
let threeRenderer = window.threeRenderer = new ThreeJSDrawer({viewer, viewport: viewer.viewport, element:viewer.element}); let threeRenderer = window.threeRenderer = new ThreeJSDrawer({viewer, viewport: viewer.viewport, element:viewer.element});
@ -24,8 +37,11 @@ var viewer2 = window.viewer2 = OpenSeadragon({
prefixUrl: "../../build/openseadragon/images/", prefixUrl: "../../build/openseadragon/images/",
minZoomImageRatio:0.01, minZoomImageRatio:0.01,
customDrawer: ThreeJSDrawer, customDrawer: ThreeJSDrawer,
tileSources: sources['leaves'], tileSources: [sources['leaves'], sources['rainbow'], sources['duomo']],
sequenceMode: true,
imageSmoothingEnabled: false, imageSmoothingEnabled: false,
crossOriginPolicy: 'Anonymous',
ajaxWithCredentials: false
}); });
//make the test canvas mirror all changes to the viewer canvas //make the test canvas mirror all changes to the viewer canvas
@ -54,6 +70,13 @@ $('#image-picker').sortable({
} }
}); });
Object.keys(sources).forEach((key, index)=>{
let element = makeImagePickerElement(key, labels[key])
$('#image-picker').append(element);
if(index === 0){
element.find('.toggle').prop('checked',true);
}
})
$('#image-picker input.toggle').on('change',function(){ $('#image-picker input.toggle').on('change',function(){
let data = $(this).data(); let data = $(this).data();
@ -193,7 +216,26 @@ function addTileSource(image, checkbox){
} }
} }
function makeImagePickerElement(key, label){
return $(`<div class="image-options">
<span class="ui-icon ui-icon-arrowthick-2-n-s"></span>
<label><input type="checkbox" data-image="" class="toggle"> __title__</label>
<div class="option-grid">
<label>X: <input type="number" value="0" data-image="" data-field="x"> </label>
<label>Y: <input type="number" value="0" data-image="" data-field="y"> </label>
<label>Width: <input type="number" value="1" data-image="" data-field="width" min="0"> </label>
<label>Degrees: <input type="number" value="0" data-image="" data-field="degrees"> </label>
<label>Opacity: <input type="number" value="1" data-image="" data-field="opacity" min="0" max="1" step="0.2"> </label>
<label>Flipped: <input type="checkbox" data-image="" data-field="flipped"></label>
<label>Cropped: <input type="checkbox" data-image="" data-field="cropped"></label>
<label>Debug: <input type="checkbox" data-image="" data-field="debug"></label>
<label>Composite: <select data-image="" data-field="composite"></select></label>
<label>Wrapping: <select data-image="" data-field="wrapping"></select></label>
</div>
</div>`.replaceAll('data-image=""', `data-image="${key}"`).replace('__title__', label));
}

View File

@ -181,7 +181,8 @@
done(); done();
}); });
image.draw(); //image.draw(); // TO DO: Is this necessary for the test? It will now fail since tiledImage.draw() is not a thing.
viewer.drawer.draw( [ image ] );
}); });
viewer.open('/test/data/testpattern.dzi'); viewer.open('/test/data/testpattern.dzi');
@ -225,7 +226,7 @@
image.setClip(clip); image.setClip(clip);
assert.propEqual(image.getClip(), clip, 'clip is set correctly'); assert.propEqual(image.getClip(), clip, 'clip is set correctly');
Util.spyOnce(viewer.drawer, 'setClip', function(rect) { Util.spyOnce(viewer.drawer, '_setClip', function(rect) {
var homeBounds = viewer.viewport.getHomeBounds(); var homeBounds = viewer.viewport.getHomeBounds();
var canvasClip = viewer.drawer var canvasClip = viewer.drawer
.viewportToDrawerRectangle(homeBounds); .viewportToDrawerRectangle(homeBounds);