diff --git a/externs/olx.js b/externs/olx.js index cfa4b74379..fd48e2b7f0 100644 --- a/externs/olx.js +++ b/externs/olx.js @@ -3863,6 +3863,7 @@ olx.source.IGCOptions.prototype.urls; * projection: ol.proj.ProjectionLike, * ratio: (number|undefined), * resolutions: (Array.|undefined), + * imageLoadFunction: (ol.ImageLoadFunctionType|undefined), * params: (Object|undefined)}} * @api */ @@ -3935,6 +3936,15 @@ olx.source.ImageMapGuideOptions.prototype.ratio; olx.source.ImageMapGuideOptions.prototype.resolutions; + +/** + * Optional function to load an image given a URL. + * @type {ol.TileLoadFunctionType|undefined} + * @api + */ +olx.source.ImageMapGuideOptions.prototype.imageLoadFunction; + + /** * Additional parameters. * @type {Object|undefined} @@ -4374,6 +4384,7 @@ olx.source.ImageVectorOptions.prototype.style; * hidpi: (boolean|undefined), * serverType: (ol.source.wms.ServerType|string|undefined), * logo: (string|olx.LogoOptions|undefined), + * imageLoadFunction: (ol.ImageLoadFunctionType|undefined), * params: Object., * projection: ol.proj.ProjectionLike, * ratio: (number|undefined), @@ -4418,6 +4429,14 @@ olx.source.ImageWMSOptions.prototype.hidpi; olx.source.ImageWMSOptions.prototype.serverType; +/** + * Optional function to load an image given a URL. + * @type {ol.TileLoadFunctionType|undefined} + * @api + */ +olx.source.ImageWMSOptions.prototype.imageLoadFunction; + + /** * Logo. * @type {string|olx.LogoOptions|undefined} @@ -4534,6 +4553,7 @@ olx.source.StamenOptions.prototype.url; * crossOrigin: (null|string|undefined), * imageExtent: (ol.Extent), * imageSize: (ol.Size|undefined), + * imageLoadFunction: (ol.ImageLoadFunctionType|undefined), * logo: (string|olx.LogoOptions|undefined), * projection: ol.proj.ProjectionLike, * url: string}} @@ -4574,6 +4594,14 @@ olx.source.ImageStaticOptions.prototype.imageExtent; olx.source.ImageStaticOptions.prototype.imageSize; +/** + * Optional function to load an image given a URL. + * @type {ol.TileLoadFunctionType|undefined} + * @api + */ +olx.source.ImageStaticOptions.prototype.imageLoadFunction; + + /** * Logo. * @type {string|olx.LogoOptions|undefined} diff --git a/src/ol/image.js b/src/ol/image.js index 46d2f065c8..e1881c0cae 100644 --- a/src/ol/image.js +++ b/src/ol/image.js @@ -20,9 +20,10 @@ goog.require('ol.extent'); * @param {Array.} attributions Attributions. * @param {string} src Image source URI. * @param {?string} crossOrigin Cross origin. + * @param {ol.ImageLoadFunctionType} imageLoadFunction Image load function. */ -ol.Image = - function(extent, resolution, pixelRatio, attributions, src, crossOrigin) { +ol.Image = function(extent, resolution, pixelRatio, attributions, src, + crossOrigin, imageLoadFunction) { goog.base(this, extent, resolution, pixelRatio, ol.ImageState.IDLE, attributions); @@ -59,6 +60,13 @@ ol.Image = * @type {ol.ImageState} */ this.state = ol.ImageState.IDLE; + + /** + * @private + * @type {ol.ImageLoadFunctionType} + */ + this.imageLoadFunction_ = imageLoadFunction; + }; goog.inherits(ol.Image, ol.ImageBase); @@ -66,8 +74,9 @@ goog.inherits(ol.Image, ol.ImageBase); /** * @param {Object=} opt_context Object. * @return {HTMLCanvasElement|Image|HTMLVideoElement} Image. + * @api */ -ol.Image.prototype.getImageElement = function(opt_context) { +ol.Image.prototype.getImage = function(opt_context) { if (goog.isDef(opt_context)) { var image; var key = goog.getUid(opt_context); @@ -126,7 +135,7 @@ ol.Image.prototype.load = function() { goog.events.listenOnce(this.image_, goog.events.EventType.LOAD, this.handleImageLoad_, false, this) ]; - this.image_.src = this.src_; + this.imageLoadFunction_(this, this.src_); } }; diff --git a/src/ol/imagebase.js b/src/ol/imagebase.js index 881c93dd53..5e0a464fbb 100644 --- a/src/ol/imagebase.js +++ b/src/ol/imagebase.js @@ -95,7 +95,7 @@ ol.ImageBase.prototype.getExtent = function() { * @param {Object=} opt_context Object. * @return {HTMLCanvasElement|Image|HTMLVideoElement} Image. */ -ol.ImageBase.prototype.getImageElement = goog.abstractMethod; +ol.ImageBase.prototype.getImage = goog.abstractMethod; /** diff --git a/src/ol/imagecanvas.js b/src/ol/imagecanvas.js index 3cd7ac9f2b..6cc9b7295b 100644 --- a/src/ol/imagecanvas.js +++ b/src/ol/imagecanvas.js @@ -33,6 +33,6 @@ goog.inherits(ol.ImageCanvas, ol.ImageBase); /** * @inheritDoc */ -ol.ImageCanvas.prototype.getImageElement = function(opt_context) { +ol.ImageCanvas.prototype.getImage = function(opt_context) { return this.canvas_; }; diff --git a/src/ol/imageloadfunction.js b/src/ol/imageloadfunction.js new file mode 100644 index 0000000000..0d4b74cda2 --- /dev/null +++ b/src/ol/imageloadfunction.js @@ -0,0 +1,21 @@ +goog.provide('ol.ImageLoadFunctionType'); + + +/** + * A function that takes an {@link ol.Image} for the image and a `{string}` for + * the src as arguments. It is supposed to make it so the underlying image + * {@link ol.Image#getImage} is assigned the content specified by the src. If + * not specified, the default is + * + * function(image, src) { + * image.getImage().src = src; + * } + * + * Providing a custom `imageLoadFunction` can be useful to load images with + * post requests or - in general - through XHR requests, where the src of the + * image element would be set to a data URI when the content is loaded. + * + * @typedef {function(ol.Image, string)} + * @api + */ +ol.ImageLoadFunctionType; diff --git a/src/ol/renderer/canvas/canvasimagelayerrenderer.js b/src/ol/renderer/canvas/canvasimagelayerrenderer.js index bfca200597..c223d84f1c 100644 --- a/src/ol/renderer/canvas/canvasimagelayerrenderer.js +++ b/src/ol/renderer/canvas/canvasimagelayerrenderer.js @@ -69,7 +69,7 @@ ol.renderer.canvas.ImageLayer.prototype.forEachFeatureAtPixel = */ ol.renderer.canvas.ImageLayer.prototype.getImage = function() { return goog.isNull(this.image_) ? - null : this.image_.getImageElement(); + null : this.image_.getImage(); }; diff --git a/src/ol/renderer/dom/domimagelayerrenderer.js b/src/ol/renderer/dom/domimagelayerrenderer.js index 46242e14db..ce2ca367c7 100644 --- a/src/ol/renderer/dom/domimagelayerrenderer.js +++ b/src/ol/renderer/dom/domimagelayerrenderer.js @@ -129,7 +129,7 @@ ol.renderer.dom.ImageLayer.prototype.prepareFrame = (imageExtent[0] - viewCenter[0]) / imageResolution, (viewCenter[1] - imageExtent[3]) / imageResolution); if (image != this.image_) { - var imageElement = image.getImageElement(this); + var imageElement = image.getImage(this); // Bootstrap sets the style max-width: 100% for all images, which breaks // prevents the image from being displayed in FireFox. Workaround by // overriding the max-width style. diff --git a/src/ol/renderer/webgl/webglimagelayerrenderer.js b/src/ol/renderer/webgl/webglimagelayerrenderer.js index 7022b626e9..8579d2cc9c 100644 --- a/src/ol/renderer/webgl/webglimagelayerrenderer.js +++ b/src/ol/renderer/webgl/webglimagelayerrenderer.js @@ -48,7 +48,7 @@ ol.renderer.webgl.ImageLayer.prototype.createTexture_ = function(image) { // http://www.khronos.org/webgl/wiki/WebGL_and_OpenGL_Differences#Non-Power_of_Two_Texture_Support // http://learningwebgl.com/blog/?p=2101 - var imageElement = image.getImageElement(); + var imageElement = image.getImage(); var gl = this.getWebGLMapRenderer().getGL(); var texture = gl.createTexture(); diff --git a/src/ol/source/imagemapguidesource.js b/src/ol/source/imagemapguidesource.js index 27c7adac6a..3d7c18f11f 100644 --- a/src/ol/source/imagemapguidesource.js +++ b/src/ol/source/imagemapguidesource.js @@ -3,6 +3,7 @@ goog.provide('ol.source.ImageMapGuide'); goog.require('goog.object'); goog.require('goog.uri.utils'); goog.require('ol.Image'); +goog.require('ol.ImageLoadFunctionType'); goog.require('ol.ImageUrlFunction'); goog.require('ol.extent'); goog.require('ol.source.Image'); @@ -59,6 +60,13 @@ ol.source.ImageMapGuide = function(options) { */ this.imageUrlFunction_ = imageUrlFunction; + /** + * @private + * @type {ol.ImageLoadFunctionType} + */ + this.imageLoadFunction_ = goog.isDef(options.imageLoadFunction) ? + options.imageLoadFunction : ol.source.Image.defaultImageLoadFunction; + /** * @private * @type {boolean} @@ -140,7 +148,8 @@ ol.source.ImageMapGuide.prototype.getImage = var imageUrl = this.imageUrlFunction_(extent, size, projection); if (goog.isDef(imageUrl)) { image = new ol.Image(extent, resolution, pixelRatio, - this.getAttributions(), imageUrl, this.crossOrigin_); + this.getAttributions(), imageUrl, this.crossOrigin_, + this.imageLoadFunction_); } else { image = null; } diff --git a/src/ol/source/imagesource.js b/src/ol/source/imagesource.js index 427359ed15..6cab2fe42d 100644 --- a/src/ol/source/imagesource.js +++ b/src/ol/source/imagesource.js @@ -88,3 +88,14 @@ ol.source.Image.prototype.findNearestResolution = * @return {ol.ImageBase} Single image. */ ol.source.Image.prototype.getImage = goog.abstractMethod; + + +/** + * Default image load function for image sources that use ol.Image image + * instances. + * @param {ol.Image} image Image. + * @param {string} src Source. + */ +ol.source.Image.defaultImageLoadFunction = function(image, src) { + image.getImage().src = src; +}; diff --git a/src/ol/source/imagestaticsource.js b/src/ol/source/imagestaticsource.js index 4aea4b4b81..bdc4e14d07 100644 --- a/src/ol/source/imagestaticsource.js +++ b/src/ol/source/imagestaticsource.js @@ -34,6 +34,9 @@ ol.source.ImageStatic = function(options) { var crossOrigin = goog.isDef(options.crossOrigin) ? options.crossOrigin : null; + var imageLoadFunction = goog.isDef(options.imageLoadFunction) ? + options.imageLoadFunction : ol.source.Image.defaultImageLoadFunction; + goog.base(this, { attributions: attributions, logo: options.logo, @@ -46,7 +49,7 @@ ol.source.ImageStatic = function(options) { * @type {ol.Image} */ this.image_ = new ol.Image(imageExtent, resolution, 1, attributions, - options.url, crossOrigin); + options.url, crossOrigin, imageLoadFunction); }; goog.inherits(ol.source.ImageStatic, ol.source.Image); diff --git a/src/ol/source/imagewmssource.js b/src/ol/source/imagewmssource.js index 05c162a141..4ba801d895 100644 --- a/src/ol/source/imagewmssource.js +++ b/src/ol/source/imagewmssource.js @@ -8,6 +8,7 @@ goog.require('goog.string'); goog.require('goog.uri.utils'); goog.require('ol'); goog.require('ol.Image'); +goog.require('ol.ImageLoadFunctionType'); goog.require('ol.extent'); goog.require('ol.proj'); goog.require('ol.source.Image'); @@ -49,6 +50,13 @@ ol.source.ImageWMS = function(opt_options) { */ this.url_ = options.url; + /** + * @private + * @type {ol.ImageLoadFunctionType} + */ + this.imageLoadFunction_ = goog.isDef(options.imageLoadFunction) ? + options.imageLoadFunction : ol.source.Image.defaultImageLoadFunction; + /** * @private * @type {Object} @@ -235,7 +243,7 @@ ol.source.ImageWMS.prototype.getImage = projection, params); this.image_ = new ol.Image(extent, resolution, pixelRatio, - this.getAttributions(), url, this.crossOrigin_); + this.getAttributions(), url, this.crossOrigin_, this.imageLoadFunction_); this.renderedRevision_ = this.getRevision(); diff --git a/test/spec/ol/source/imagewmssource.test.js b/test/spec/ol/source/imagewmssource.test.js index b407a27913..5031017338 100644 --- a/test/spec/ol/source/imagewmssource.test.js +++ b/test/spec/ol/source/imagewmssource.test.js @@ -134,6 +134,16 @@ describe('ol.source.ImageWMS', function() { expect(queryData.get('DPI')).to.be('180'); }); + it('creates an image with a custom imageLoadFunction', function() { + var imageLoadFunction = sinon.spy(); + options.imageLoadFunction = imageLoadFunction; + var source = new ol.source.ImageWMS(options); + var image = source.getImage(extent, resolution, pixelRatio, projection); + image.load(); + expect(imageLoadFunction).to.be.called(); + expect(imageLoadFunction.calledWith(image, image.src_)).to.be(true); + }); + }); describe('#getGetFeatureInfo', function() {