From a0a94414dd80cd61340478de6fb01d14515e9a7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Lemoine?= Date: Tue, 7 Jan 2014 17:40:50 +0100 Subject: [PATCH 1/6] Add anchorXUnits and anchorYUnits options to ol.style.Icon --- src/objectliterals.jsdoc | 11 ++++++++++- src/ol/style/iconstyle.js | 40 +++++++++++++++++++++++++++++---------- 2 files changed, 40 insertions(+), 11 deletions(-) diff --git a/src/objectliterals.jsdoc b/src/objectliterals.jsdoc index 8d6611ca29..a7c0193eef 100644 --- a/src/objectliterals.jsdoc +++ b/src/objectliterals.jsdoc @@ -797,7 +797,16 @@ /** * @typedef {Object} olx.style.IconOptions - * @property {ol.Pixel|undefined} anchor Anchor. + * @property {ol.Pixel|undefined} anchor Anchor. Default value is [0.5, 0.5] + * (icon center). + * @property {ol.style.IconAnchorUnits|undefined} anchorXUnits Units in which the anchor x value is specified. + * A value of `'fraction'` indicates the x value is a fraction of the icon. + * A value of `'pixels'` indicates the x value in pixels. Default is + * `'fraction'`. + * @property {ol.style.IconAnchorUnits|undefined} anchorYUnits Units in which the anchor y value is specified. + * A value of `'fraction'` indicates the y value is a fraction of the icon. + * A value of `'pixels'` indicates the y value in pixels. Default is + * `'fraction'`. * @property {null|string|undefined} crossOrigin crossOrigin setting for image. * @property {number|undefined} scale Scale. * @property {number|undefined} rotation Rotation. diff --git a/src/ol/style/iconstyle.js b/src/ol/style/iconstyle.js index c4df241a40..7a4e74acdd 100644 --- a/src/ol/style/iconstyle.js +++ b/src/ol/style/iconstyle.js @@ -1,6 +1,7 @@ // FIXME decide default value for snapToPixel goog.provide('ol.style.Icon'); +goog.provide('ol.style.IconAnchorUnits'); goog.require('goog.array'); goog.require('goog.asserts'); @@ -12,6 +13,15 @@ goog.require('ol.style.Image'); goog.require('ol.style.ImageState'); +/** + * @enum {string} + */ +ol.style.IconAnchorUnits = { + FRACTION: 'fraction', + PIXELS: 'pixels' +}; + + /** * @constructor @@ -66,17 +76,24 @@ ol.style.Icon = function(opt_options) { */ var size = goog.isDef(options.size) ? options.size : null; + /** + * @private + * @type {ol.style.IconAnchorUnits} + */ + this.anchorXUnits_ = goog.isDef(options.anchorXUnits) ? + options.anchorXUnits : ol.style.IconAnchorUnits.FRACTION; + + /** + * @private + * @type {ol.style.IconAnchorUnits} + */ + this.anchorYUnits_ = goog.isDef(options.anchorYUnits) ? + options.anchorYUnits : ol.style.IconAnchorUnits.FRACTION; + /** * @type {ol.Pixel} */ - var anchor; - if (goog.isDef(options.anchor)) { - anchor = options.anchor; - } else if (!goog.isNull(size)) { - anchor = [size[0] / 2, size[1] / 2]; - } else { - anchor = null; - } + var anchor = goog.isDef(options.anchor) ? options.anchor : [0.5, 0.5]; /** * @type {number} @@ -139,8 +156,11 @@ ol.style.Icon.prototype.handleImageLoad_ = function() { if (goog.isNull(this.size)) { this.size = [this.image_.width, this.image_.height]; } - if (goog.isNull(this.anchor)) { - this.anchor = [this.size[0] / 2, this.size[1] / 2]; + if (this.anchorXUnits_ == ol.style.IconAnchorUnits.FRACTION) { + this.anchor[0] = this.size[0] * this.anchor[0]; + } + if (this.anchorYUnits_ == ol.style.IconAnchorUnits.FRACTION) { + this.anchor[1] = this.size[1] * this.anchor[1]; } this.unlistenImage_(); this.determineTainting_(); From 09e5574350e808e8f3bf230be10265d920e1600d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Lemoine?= Date: Tue, 7 Jan 2014 17:41:24 +0100 Subject: [PATCH 2/6] Use anchorXUnits and anchorYUnits in icon example --- examples/icon.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/examples/icon.js b/examples/icon.js index b21f5100e2..c97aca9a3b 100644 --- a/examples/icon.js +++ b/examples/icon.js @@ -19,6 +19,9 @@ var raster = new ol.layer.Tile({ var styleArray = [new ol.style.Style({ image: new ol.style.Icon({ + anchor: [0.5, 46], + anchorXUnits: 'fraction', + anchorYUnits: 'pixels', src: 'data/icon.png' }) })]; From 7487f974362ea962ceb6515d50d707e14f883e3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Lemoine?= Date: Tue, 7 Jan 2014 17:43:14 +0100 Subject: [PATCH 3/6] Support anchorXUnits and anchorYUnits in KML format --- src/ol/format/kmlformat.js | 51 ++++++++++++++++++++++++++++++++------ 1 file changed, 44 insertions(+), 7 deletions(-) diff --git a/src/ol/format/kmlformat.js b/src/ol/format/kmlformat.js index 4f0445bbc2..996f212c67 100644 --- a/src/ol/format/kmlformat.js +++ b/src/ol/format/kmlformat.js @@ -30,6 +30,7 @@ goog.require('ol.geom.Polygon'); goog.require('ol.proj'); goog.require('ol.style.Fill'); goog.require('ol.style.Icon'); +goog.require('ol.style.IconAnchorUnits'); goog.require('ol.style.Image'); goog.require('ol.style.Stroke'); goog.require('ol.style.Style'); @@ -43,8 +44,8 @@ ol.KML_RESPECT_VISIBILITY = false; /** - * @typedef {{x: number, xunits: (string|null), - * y: number, yunits: (string|null)}} + * @typedef {{x: number, xunits: (ol.style.IconAnchorUnits|undefined), + * y: number, yunits: (ol.style.IconAnchorUnits|undefined)}} */ ol.format.KMLVec2_; @@ -160,6 +161,22 @@ ol.format.KML.DEFAULT_FILL_STYLE_ = new ol.style.Fill({ ol.format.KML.DEFAULT_IMAGE_STYLE_ANCHOR_ = [2, 20]; // FIXME maybe [8, 32] ? +/** + * @const {ol.style.IconAnchorUnits} + * @private + */ +ol.format.KML.DEFAULT_IMAGE_STYLE_ANCHOR_X_UNITS_ = + ol.style.IconAnchorUnits.PIXELS; + + +/** + * @const {ol.style.IconAnchorUnits} + * @private + */ +ol.format.KML.DEFAULT_IMAGE_STYLE_ANCHOR_Y_UNITS_ = + ol.style.IconAnchorUnits.PIXELS; + + /** * @const {ol.Size} * @private @@ -181,6 +198,8 @@ ol.format.KML.DEFAULT_IMAGE_STYLE_SRC_ = */ ol.format.KML.DEFAULT_IMAGE_STYLE_ = new ol.style.Icon({ anchor: ol.format.KML.DEFAULT_IMAGE_STYLE_ANCHOR_, + anchorXUnits: ol.format.KML.DEFAULT_IMAGE_STYLE_ANCHOR_X_UNITS_, + anchorYUnits: ol.format.KML.DEFAULT_IMAGE_STYLE_ANCHOR_Y_UNITS_, crossOrigin: 'anonymous', rotation: 0, scale: 1, @@ -219,6 +238,16 @@ ol.format.KML.DEFAULT_STYLE_ = new ol.style.Style({ ol.format.KML.DEFAULT_STYLE_ARRAY_ = [ol.format.KML.DEFAULT_STYLE_]; +/** + * @const {Object.} + * @private + */ +ol.format.KML.ICON_ANCHOR_UNITS_MAP_ = { + 'fraction': ol.style.IconAnchorUnits.FRACTION, + 'pixels': ol.style.IconAnchorUnits.PIXELS +}; + + /** * @param {number} resolution Resolution. * @private @@ -394,11 +423,15 @@ ol.format.KML.readURI_ = function(node) { * @return {ol.format.KMLVec2_} Vec2. */ ol.format.KML.readVec2_ = function(node) { + var xunits = node.getAttribute('xunits'); + var yunits = node.getAttribute('yunits'); return { x: parseFloat(node.getAttribute('x')), - xunits: node.getAttribute('xunits'), + xunits: goog.isNull(xunits) ? + undefined : ol.format.KML.ICON_ANCHOR_UNITS_MAP_[xunits], y: parseFloat(node.getAttribute('y')), - yunits: node.getAttribute('yunits') + yunits: goog.isNull(yunits) ? + undefined : ol.format.KML.ICON_ANCHOR_UNITS_MAP_[yunits] }; }; @@ -452,15 +485,17 @@ ol.format.KML.IconStyleParser_ = function(node, objectStack) { } else { src = ol.format.KML.DEFAULT_IMAGE_STYLE_SRC_; } - var anchor; + var anchor, anchorXUnits, anchorYUnits; var hotSpot = /** @type {ol.format.KMLVec2_|undefined} */ (goog.object.get(object, 'hotSpot')); if (goog.isDef(hotSpot)) { - goog.asserts.assert(hotSpot.xunits == 'pixels'); - goog.asserts.assert(hotSpot.yunits == 'pixels'); anchor = [hotSpot.x, hotSpot.y]; + anchorXUnits = hotSpot.xunits; + anchorYUnits = hotSpot.yunits; } 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_; + anchorYUnits = ol.format.KML.DEFAULT_IMAGE_STYLE_ANCHOR_Y_UNITS_; } else { anchor = null; } @@ -482,6 +517,8 @@ ol.format.KML.IconStyleParser_ = function(node, objectStack) { } var imageStyle = new ol.style.Icon({ anchor: anchor, + anchorXUnits: anchorXUnits, + anchorYUnits: anchorYUnits, crossOrigin: 'anonymous', // FIXME should this be configurable? rotation: rotation, scale: scale, From 1acdef835d7c47ea019deac4a30d9ce6da7b2682 Mon Sep 17 00:00:00 2001 From: Tom Payne Date: Tue, 7 Jan 2014 17:43:39 +0100 Subject: [PATCH 4/6] Change default anchor for KML icons from Google Maps --- src/ol/format/kmlformat.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/ol/format/kmlformat.js b/src/ol/format/kmlformat.js index 996f212c67..65926e5361 100644 --- a/src/ol/format/kmlformat.js +++ b/src/ol/format/kmlformat.js @@ -496,6 +496,10 @@ ol.format.KML.IconStyleParser_ = function(node, objectStack) { anchor = ol.format.KML.DEFAULT_IMAGE_STYLE_ANCHOR_; anchorXUnits = ol.format.KML.DEFAULT_IMAGE_STYLE_ANCHOR_X_UNITS_; anchorYUnits = ol.format.KML.DEFAULT_IMAGE_STYLE_ANCHOR_Y_UNITS_; + } else if (/^http:\/\/maps\.(?:google|gstatic)\.com\//.test(src)) { + anchor = [0.5, 1]; + anchorXUnits = ol.style.IconAnchorUnits.FRACTION; + anchorYUnits = ol.style.IconAnchorUnits.FRACTION; } else { anchor = null; } From 5efc692b9d8bb8c98ed054960fbd1647d98b8738 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Lemoine?= Date: Wed, 8 Jan 2014 00:44:00 +0100 Subject: [PATCH 5/6] Add typecast to icon example --- examples/icon.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/icon.js b/examples/icon.js index c97aca9a3b..35b4da967f 100644 --- a/examples/icon.js +++ b/examples/icon.js @@ -18,12 +18,12 @@ var raster = new ol.layer.Tile({ }); var styleArray = [new ol.style.Style({ - image: new ol.style.Icon({ + image: new ol.style.Icon(/** @type {olx.style.IconOptions} */ ({ anchor: [0.5, 46], anchorXUnits: 'fraction', anchorYUnits: 'pixels', src: 'data/icon.png' - }) + })) })]; var vector = new ol.layer.Vector({ From 49120e4761b682a718071435d158aaf1cf5e37c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Lemoine?= Date: Wed, 8 Jan 2014 10:07:01 +0100 Subject: [PATCH 6/6] Icon anchors are Array. --- src/objectliterals.jsdoc | 2 +- src/ol/style/iconstyle.js | 2 +- src/ol/style/imagestyle.js | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/objectliterals.jsdoc b/src/objectliterals.jsdoc index a7c0193eef..6b033629e6 100644 --- a/src/objectliterals.jsdoc +++ b/src/objectliterals.jsdoc @@ -797,7 +797,7 @@ /** * @typedef {Object} olx.style.IconOptions - * @property {ol.Pixel|undefined} anchor Anchor. Default value is [0.5, 0.5] + * @property {Array.|undefined} anchor Anchor. Default value is [0.5, 0.5] * (icon center). * @property {ol.style.IconAnchorUnits|undefined} anchorXUnits Units in which the anchor x value is specified. * A value of `'fraction'` indicates the x value is a fraction of the icon. diff --git a/src/ol/style/iconstyle.js b/src/ol/style/iconstyle.js index 7a4e74acdd..5cb250f9ef 100644 --- a/src/ol/style/iconstyle.js +++ b/src/ol/style/iconstyle.js @@ -91,7 +91,7 @@ ol.style.Icon = function(opt_options) { options.anchorYUnits : ol.style.IconAnchorUnits.FRACTION; /** - * @type {ol.Pixel} + * @type {Array.} */ var anchor = goog.isDef(options.anchor) ? options.anchor : [0.5, 0.5]; diff --git a/src/ol/style/imagestyle.js b/src/ol/style/imagestyle.js index 4491030da5..6592f81313 100644 --- a/src/ol/style/imagestyle.js +++ b/src/ol/style/imagestyle.js @@ -19,7 +19,7 @@ ol.style.ImageState = { /** - * @typedef {{anchor: ol.Pixel, + * @typedef {{anchor: Array., * imageState: ol.style.ImageState, * rotation: number, * scale: number, @@ -42,7 +42,7 @@ ol.style.Image = function(options) { /** * @protected - * @type {ol.Pixel} + * @type {Array.} */ this.anchor = options.anchor; @@ -95,7 +95,7 @@ ol.style.Image.prototype.dispatchChangeEvent = function() { /** - * @return {ol.Pixel} Anchor. + * @return {Array.} Anchor. */ ol.style.Image.prototype.getAnchor = function() { return this.anchor;