diff --git a/src/ol/format/KML.js b/src/ol/format/KML.js index 0b2badd950..46d4674911 100644 --- a/src/ol/format/KML.js +++ b/src/ol/format/KML.js @@ -378,6 +378,24 @@ function createStyleDefaults() { */ let TEXTAREA; +/** + * A function that takes a url `{string}` and returns a url `{string}`. + * Might be used to change an icon path or to substitute a + * data url obtained from a KMZ array buffer. + * + * @typedef {function(string):string} IconUrlFunction + * @api + */ + +/** + * Function that returns a url unchanged. + * @param {string} href Input url. + * @return {string} Output url. + */ +function defaultIconUrlFunction(href) { + return href; +} + /** * @typedef {Object} Options * @property {boolean} [extractStyles=true] Extract styles from the KML. @@ -387,6 +405,8 @@ let TEXTAREA; * @property {boolean} [writeStyles=true] Write styles into KML. * @property {null|string} [crossOrigin='anonymous'] The `crossOrigin` attribute for loaded images. Note that you must provide a * `crossOrigin` value if you want to access pixel data with the Canvas renderer. + * @property {IconUrlFunction} [iconUrlFunction] Function that takes a url string and returns a url string. + * Might be used to change an icon path or to substitute a data url obtained from a KMZ array buffer. */ /** @@ -462,6 +482,13 @@ class KML extends XMLFeature { */ this.crossOrigin_ = options.crossOrigin !== undefined ? options.crossOrigin : 'anonymous'; + + /** + * @type {IconUrlFunction} + */ + this.iconUrlFunction_ = options.iconUrlFunction + ? options.iconUrlFunction + : defaultIconUrlFunction; } /** @@ -1282,7 +1309,7 @@ function iconStyleParser(node, objectStack) { rotation: rotation, scale: scale, size: size, - src: src, + src: this.iconUrlFunction_(src), color: color, }); styleObject['imageStyle'] = imageStyle; diff --git a/test/spec/ol/format/kml.test.js b/test/spec/ol/format/kml.test.js index 205b292cb7..8df3ea6e99 100644 --- a/test/spec/ol/format/kml.test.js +++ b/test/spec/ol/format/kml.test.js @@ -2154,6 +2154,52 @@ describe('ol.format.KML', function () { expect(style.getZIndex()).to.be(undefined); }); + it("can read a feature's IconStyle and apply an iconUrlFunction", function () { + format = new KML({ + iconUrlFunction: function (href) { + return href.replace(/^http:/, 'https:'); + }, + }); + const text = + '' + + ' ' + + ' ' + + ' ' + + ''; + const fs = format.readFeatures(text); + expect(fs).to.have.length(1); + const f = fs[0]; + expect(f).to.be.an(Feature); + const styleFunction = f.getStyleFunction(); + expect(styleFunction).not.to.be(undefined); + const styleArray = styleFunction(f, 0); + expect(styleArray).to.be.an(Array); + expect(styleArray).to.have.length(1); + const style = styleArray[0]; + expect(style).to.be.an(Style); + expect(style.getFill()).to.be(getDefaultFillStyle()); + expect(style.getStroke()).to.be(getDefaultStrokeStyle()); + const imageStyle = style.getImage(); + expect(imageStyle).to.be.an(Icon); + expect(new URL(imageStyle.getSrc()).href).to.eql( + new URL('https://foo.png').href + ); + expect(imageStyle.getAnchor()).to.be(null); + expect(imageStyle.getOrigin()).to.be(null); + expect(imageStyle.getRotation()).to.eql(0); + expect(imageStyle.getSize()).to.be(null); + expect(imageStyle.getScale()).to.be(1); + expect(imageStyle.getImage().crossOrigin).to.eql('anonymous'); + expect(style.getText()).to.be(getDefaultTextStyle()); + expect(style.getZIndex()).to.be(undefined); + }); + it("can read a IconStyle's hotspot", function () { const text = '' +