diff --git a/src/drawer.js b/src/drawer.js index bad89a69..f4ed36a6 100644 --- a/src/drawer.js +++ b/src/drawer.js @@ -369,10 +369,11 @@ $.Drawer.prototype = /** @lends OpenSeadragon.Drawer.prototype */{ * @param {Float} opacity The opacity of the blending. * @param {Float} [scale=1] The scale at which tiles were drawn on the sketch. Default is 1. * Use scale to draw at a lower scale and then enlarge onto the main canvas. - * @param OpenSeadragon.Point} [translate] A translation vector that was used to draw the tiles + * @param {OpenSeadragon.Point} [translate] A translation vector that was used to draw the tiles + * @param {String} [options.compositeOperation] - How the image is composited onto other images; see compositeOperation in {@link OpenSeadragon.Options} for possible values. * @returns {undefined} */ - blendSketch: function(opacity, scale, translate) { + blendSketch: function(opacity, scale, translate, compositeOperation) { if (!this.useCanvas || !this.sketchCanvas) { return; } @@ -383,6 +384,9 @@ $.Drawer.prototype = /** @lends OpenSeadragon.Drawer.prototype */{ this.context.save(); this.context.globalAlpha = opacity; + if (compositeOperation) { + this.context.globalCompositeOperation = compositeOperation; + } this.context.drawImage( this.sketchCanvas, position.x, diff --git a/src/openseadragon.js b/src/openseadragon.js index 8613d2a8..a129f083 100644 --- a/src/openseadragon.js +++ b/src/openseadragon.js @@ -206,6 +206,11 @@ * @property {Number} [opacity=1] * Default opacity of the tiled images (1=opaque, 0=transparent) * + * @property {String} [compositeOperation=null] + * Valid values are 'source-over', 'source-atop', 'source-in', 'source-out', + * 'destination-over', 'destination-atop', 'destination-in', + * 'destination-out', 'lighter', 'copy' or 'xor' + * * @property {String|CanvasGradient|CanvasPattern|Function} [placeholderFillStyle=null] * Draws a colored rectangle behind the tile if it is not loaded yet. * You can pass a CSS color value like "#FF8800". @@ -1067,6 +1072,7 @@ if (typeof define === 'function' && define.amd) { // APPEARANCE opacity: 1, + compositeOperation: null, placeholderFillStyle: null, //REFERENCE STRIP SETTINGS diff --git a/src/tiledimage.js b/src/tiledimage.js index 05ca8848..dadeb5de 100644 --- a/src/tiledimage.js +++ b/src/tiledimage.js @@ -66,6 +66,7 @@ * @param {Number} [options.minPixelRatio] - See {@link OpenSeadragon.Options}. * @param {Number} [options.smoothTileEdgesMinZoom] - See {@link OpenSeadragon.Options}. * @param {Number} [options.opacity=1] - Opacity the tiled image should be drawn at. + * @param {String} [options.compositeOperation] - How the image is composited onto other images; see compositeOperation in {@link OpenSeadragon.Options} for possible values. * @param {Boolean} [options.debugMode] - See {@link OpenSeadragon.Options}. * @param {String|CanvasGradient|CanvasPattern|Function} [options.placeholderFillStyle] - See {@link OpenSeadragon.Options}. * @param {String|Boolean} [options.crossOriginPolicy] - See {@link OpenSeadragon.Options}. @@ -132,7 +133,6 @@ $.TiledImage = function( options ) { _midDraw: false, // Is the tiledImage currently updating the viewport? _needsDraw: true, // Does the tiledImage need to update the viewport again? _hasOpaqueTile: false, // Do we have even one fully opaque tile? - //configurable settings springStiffness: $.DEFAULT_SETTINGS.springStiffness, animationTime: $.DEFAULT_SETTINGS.animationTime, @@ -147,7 +147,8 @@ $.TiledImage = function( options ) { debugMode: $.DEFAULT_SETTINGS.debugMode, crossOriginPolicy: $.DEFAULT_SETTINGS.crossOriginPolicy, placeholderFillStyle: $.DEFAULT_SETTINGS.placeholderFillStyle, - opacity: $.DEFAULT_SETTINGS.opacity + opacity: $.DEFAULT_SETTINGS.opacity, + compositeOperation: $.DEFAULT_SETTINGS.compositeOperation }, options ); @@ -585,6 +586,21 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag this._needsDraw = true; }, + /** + * @returns {String} The TiledImage's current compositeOperation. + */ + getCompositeOperation: function() { + return this.compositeOperation; + }, + + /** + * @param {String} compositeOperation the tiled image should be drawn with this globalCompositeOperation. + */ + setCompositeOperation: function(compositeOperation) { + this.compositeOperation = compositeOperation; + this._needsDraw = true; + }, + // private _setScale: function(scale, immediately) { var sameTarget = (this._scaleSpring.target.value === scale); @@ -1313,7 +1329,9 @@ function drawTiles( tiledImage, lastDrawn ) { drawDebugInfo( tiledImage, lastDrawn ); return; } - var useSketch = tiledImage.opacity < 1; + var useSketch = tiledImage.opacity < 1 || + (tiledImage.compositeOperation && tiledImage.compositeOperation !== 'source-over'); + var sketchScale; var sketchTranslate; @@ -1405,7 +1423,7 @@ function drawTiles( tiledImage, lastDrawn ) { } if ( useSketch ) { - tiledImage._drawer.blendSketch( tiledImage.opacity, sketchScale, sketchTranslate ); + tiledImage._drawer.blendSketch( tiledImage.opacity, sketchScale, sketchTranslate, tiledImage.compositeOperation ); } drawDebugInfo( tiledImage, lastDrawn ); } diff --git a/src/viewer.js b/src/viewer.js index 723a4b65..16d5cfa1 100644 --- a/src/viewer.js +++ b/src/viewer.js @@ -1207,6 +1207,7 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype, * (portions of the image outside of this area will not be visible). Only works on * browsers that support the HTML5 canvas. * @param {Number} [options.opacity] Opacity the tiled image should be drawn at by default. + * @param {String} [options.compositeOperation] How the image is composited onto other images. * @param {Function} [options.success] A function that gets called when the image is * successfully added. It's passed the event object which contains a single property: * "item", the resulting TiledImage. @@ -1239,6 +1240,9 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype, if (options.opacity === undefined) { options.opacity = this.opacity; } + if (options.compositeOperation === undefined) { + options.compositeOperation = this.compositeOperation; + } var myQueueItem = { options: options @@ -1337,6 +1341,7 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype, clip: queueItem.options.clip, placeholderFillStyle: queueItem.options.placeholderFillStyle, opacity: queueItem.options.opacity, + compositeOperation: queueItem.options.compositeOperation, springStiffness: _this.springStiffness, animationTime: _this.animationTime, minZoomImageRatio: _this.minZoomImageRatio,