diff --git a/src/ol/format/kml.js b/src/ol/format/kml.js index 7bfa49b317..0e2b7bbf62 100644 --- a/src/ol/format/kml.js +++ b/src/ol/format/kml.js @@ -285,7 +285,8 @@ ol.format.KML.createStyleDefaults_ = function() { */ ol.format.KML.ICON_ANCHOR_UNITS_MAP_ = { 'fraction': ol.style.IconAnchorUnits.FRACTION, - 'pixels': ol.style.IconAnchorUnits.PIXELS + 'pixels': ol.style.IconAnchorUnits.PIXELS, + 'insetPixels': ol.style.IconAnchorUnits.PIXELS }; @@ -504,11 +505,26 @@ ol.format.KML.readURI_ = function(node) { ol.format.KML.readVec2_ = function(node) { var xunits = node.getAttribute('xunits'); var yunits = node.getAttribute('yunits'); + var origin; + if (xunits !== 'insetPixels') { + if (yunits !== 'insetPixels') { + origin = ol.style.IconOrigin.BOTTOM_LEFT; + } else { + origin = ol.style.IconOrigin.TOP_LEFT; + } + } else { + if (yunits !== 'insetPixels') { + origin = ol.style.IconOrigin.BOTTOM_RIGHT; + } else { + origin = ol.style.IconOrigin.TOP_RIGHT; + } + } return { x: parseFloat(node.getAttribute('x')), xunits: ol.format.KML.ICON_ANCHOR_UNITS_MAP_[xunits], y: parseFloat(node.getAttribute('y')), - yunits: ol.format.KML.ICON_ANCHOR_UNITS_MAP_[yunits] + yunits: ol.format.KML.ICON_ANCHOR_UNITS_MAP_[yunits], + origin: origin }; }; @@ -562,12 +578,14 @@ ol.format.KML.IconStyleParser_ = function(node, objectStack) { src = ol.format.KML.DEFAULT_IMAGE_STYLE_SRC_; } var anchor, anchorXUnits, anchorYUnits; + var anchorOrigin = ol.style.IconOrigin.BOTTOM_LEFT; var hotSpot = /** @type {ol.KMLVec2_|undefined} */ (object['hotSpot']); if (hotSpot) { anchor = [hotSpot.x, hotSpot.y]; anchorXUnits = hotSpot.xunits; anchorYUnits = hotSpot.yunits; + anchorOrigin = hotSpot.origin; } else if (src === ol.format.KML.DEFAULT_IMAGE_STYLE_SRC_) { anchor = ol.format.KML.DEFAULT_IMAGE_STYLE_ANCHOR_; anchorXUnits = ol.format.KML.DEFAULT_IMAGE_STYLE_ANCHOR_X_UNITS_; @@ -616,7 +634,7 @@ ol.format.KML.IconStyleParser_ = function(node, objectStack) { var imageStyle = new ol.style.Icon({ anchor: anchor, - anchorOrigin: ol.style.IconOrigin.BOTTOM_LEFT, + anchorOrigin: anchorOrigin, anchorXUnits: anchorXUnits, anchorYUnits: anchorYUnits, crossOrigin: 'anonymous', // FIXME should this be configurable? diff --git a/src/ol/typedefs.js b/src/ol/typedefs.js index b3cdc557d9..853b4c9b93 100644 --- a/src/ol/typedefs.js +++ b/src/ol/typedefs.js @@ -285,7 +285,8 @@ ol.ImageLoadFunctionType; /** * @typedef {{x: number, xunits: (ol.style.IconAnchorUnits|undefined), - * y: number, yunits: (ol.style.IconAnchorUnits|undefined)}} + * y: number, yunits: (ol.style.IconAnchorUnits|undefined), + * origin: (ol.style.IconOrigin|undefined)}} */ ol.KMLVec2_; diff --git a/test/spec/ol/format/kml.test.js b/test/spec/ol/format/kml.test.js index 98826257a0..fc2ea80bd1 100644 --- a/test/spec/ol/format/kml.test.js +++ b/test/spec/ol/format/kml.test.js @@ -1713,6 +1713,111 @@ describe('ol.format.KML', function() { expect(style.getZIndex()).to.be(undefined); }); + it('can read a IconStyle\'s hotspot', function() { + var text = + '' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ''; + var fs = format.readFeatures(text); + expect(fs).to.have.length(5); + fs.forEach(function(f) { + expect(f).to.be.an(ol.Feature); + expect(f.getId()).to.be.within(1, 5); + var styleFunction = f.getStyleFunction(); + expect(styleFunction).not.to.be(undefined); + var styleArray = styleFunction.call(f, 0); + expect(styleArray).to.be.an(Array); + expect(styleArray).to.have.length(1); + var style = styleArray[0]; + expect(style).to.be.an(ol.style.Style); + expect(style.getFill()).to.be(ol.format.KML.DEFAULT_FILL_STYLE_); + expect(style.getStroke()).to.be(ol.format.KML.DEFAULT_STROKE_STYLE_); + var imageStyle = style.getImage(); + expect(imageStyle).to.be.an(ol.style.Icon); + expect(new URL(imageStyle.getSrc()).href).to.eql(new URL('http://foo.png').href); + expect(imageStyle.anchor_).to.be.an(Array); + expect(imageStyle.anchor_).to.have.length(2); + if (f.getId() == 1) { + expect(imageStyle.anchor_[0]).to.be(0.5); + expect(imageStyle.anchor_[1]).to.be(0.5); + expect(imageStyle.anchorOrigin_).to.be(ol.style.IconOrigin.BOTTOM_LEFT); + expect(imageStyle.anchorXUnits_).to.be(ol.style.IconAnchorUnits.FRACTION); + expect(imageStyle.anchorYUnits_).to.be(ol.style.IconAnchorUnits.FRACTION); + } else { + expect(imageStyle.anchor_[0]).to.be(5); + expect(imageStyle.anchor_[1]).to.be(5); + expect(imageStyle.anchorXUnits_).to.be(ol.style.IconAnchorUnits.PIXELS); + expect(imageStyle.anchorYUnits_).to.be(ol.style.IconAnchorUnits.PIXELS); + if (f.getId() == 2) { + expect(imageStyle.anchorOrigin_).to.be(ol.style.IconOrigin.BOTTOM_LEFT); + } + if (f.getId() == 3) { + expect(imageStyle.anchorOrigin_).to.be(ol.style.IconOrigin.BOTTOM_RIGHT); + } + if (f.getId() == 4) { + expect(imageStyle.anchorOrigin_).to.be(ol.style.IconOrigin.TOP_LEFT); + } + if (f.getId() == 5) { + expect(imageStyle.anchorOrigin_).to.be(ol.style.IconOrigin.TOP_RIGHT); + } + } + expect(imageStyle.getRotation()).to.eql(0); + expect(imageStyle.getSize()).to.be(null); + expect(imageStyle.getScale()).to.be(1); + expect(style.getText()).to.be(ol.format.KML.DEFAULT_TEXT_STYLE_); + expect(style.getZIndex()).to.be(undefined); + }); + }); + it('can read a complex feature\'s IconStyle', function() { var text = '