diff --git a/externs/olx.js b/externs/olx.js index 0cb5839951..81bdc6ccff 100644 --- a/externs/olx.js +++ b/externs/olx.js @@ -4491,12 +4491,13 @@ olx.style.FillOptions.prototype.color; /** * @typedef {{anchor: (Array.|undefined), - * anchorOrigin: (ol.style.IconAnchorOrigin|undefined), + * anchorOrigin: (ol.style.IconOrigin|undefined), * anchorXUnits: (ol.style.IconAnchorUnits|undefined), * anchorYUnits: (ol.style.IconAnchorUnits|undefined), * crossOrigin: (null|string|undefined), * img: (Image|undefined), - * origin: (Array.|undefined), + * offset: (Array.|undefined), + * offsetOrigin: (ol.style.IconOrigin|undefined), * scale: (number|undefined), * snapToPixel: (boolean|undefined), * rotateWithView: (boolean|undefined), @@ -4518,7 +4519,7 @@ olx.style.IconOptions.prototype.anchor; /** * Origin of the anchor: `bottom-left`, `bottom-right`, `top-left` or * `top-right`. Default is `top-left`. - * @type {ol.style.IconAnchorOrigin|undefined} + * @type {ol.style.IconOrigin|undefined} */ olx.style.IconOptions.prototype.anchorOrigin; @@ -4557,12 +4558,20 @@ olx.style.IconOptions.prototype.img; /** - * The top left corner, which, together with the size, define the - * sub-rectangle to use from the original icon image. Default value + * Offset, which, together with the size and the offset origin, + * define the sub-rectangle to use from the original icon image. Default value * is `[0, 0]`. * @type {Array.|undefined} */ -olx.style.IconOptions.prototype.origin; +olx.style.IconOptions.prototype.offset; + + +/** + * Origin of the offset: `bottom-left`, `bottom-right`, `top-left` or + * `top-right`. Default is `top-left`. + * @type {ol.style.IconOrigin|undefined} + */ +olx.style.IconOptions.prototype.offsetOrigin; /** diff --git a/src/ol/style/circlestyle.js b/src/ol/style/circlestyle.js index 564dbd5edd..1c25e013f9 100644 --- a/src/ol/style/circlestyle.js +++ b/src/ol/style/circlestyle.js @@ -40,6 +40,12 @@ ol.style.Circle = function(opt_options) { */ this.fill_ = goog.isDef(options.fill) ? options.fill : null; + /** + * @private + * @type {Array.} + */ + this.origin_ = [0, 0]; + /** * @private * @type {number} @@ -74,7 +80,6 @@ ol.style.Circle = function(opt_options) { goog.base(this, { opacity: 1, - origin: [0, 0], rotateWithView: false, rotation: 0, scale: 1, @@ -128,6 +133,15 @@ ol.style.Circle.prototype.getImageState = function() { }; +/** + * @inheritDoc + * @todo api + */ +ol.style.Circle.prototype.getOrigin = function() { + return this.origin_; +}; + + /** * @return {number} Radius. * @todo api diff --git a/src/ol/style/iconstyle.js b/src/ol/style/iconstyle.js index 6de655a9b4..e9581b4e16 100644 --- a/src/ol/style/iconstyle.js +++ b/src/ol/style/iconstyle.js @@ -1,7 +1,7 @@ goog.provide('ol.style.Icon'); -goog.provide('ol.style.IconAnchorOrigin'); goog.provide('ol.style.IconAnchorUnits'); goog.provide('ol.style.IconImageCache'); +goog.provide('ol.style.IconOrigin'); goog.require('goog.array'); goog.require('goog.asserts'); @@ -16,20 +16,20 @@ goog.require('ol.style.ImageState'); /** * @enum {string} */ -ol.style.IconAnchorOrigin = { - BOTTOM_LEFT: 'bottom-left', - BOTTOM_RIGHT: 'bottom-right', - TOP_LEFT: 'top-left', - TOP_RIGHT: 'top-right' +ol.style.IconAnchorUnits = { + FRACTION: 'fraction', + PIXELS: 'pixels' }; /** * @enum {string} */ -ol.style.IconAnchorUnits = { - FRACTION: 'fraction', - PIXELS: 'pixels' +ol.style.IconOrigin = { + BOTTOM_LEFT: 'bottom-left', + BOTTOM_RIGHT: 'bottom-right', + TOP_LEFT: 'top-left', + TOP_RIGHT: 'top-right' }; @@ -58,10 +58,10 @@ ol.style.Icon = function(opt_options) { /** * @private - * @type {ol.style.IconAnchorOrigin} + * @type {ol.style.IconOrigin} */ this.anchorOrigin_ = goog.isDef(options.anchorOrigin) ? - options.anchorOrigin : ol.style.IconAnchorOrigin.TOP_LEFT; + options.anchorOrigin : ol.style.IconOrigin.TOP_LEFT; /** * @private @@ -111,6 +111,25 @@ ol.style.Icon = function(opt_options) { this.iconImage_ = ol.style.IconImage_.get( image, src, crossOrigin, imageState); + /** + * @private + * @type {Array.} + */ + this.offset_ = goog.isDef(options.offset) ? options.offset : [0, 0]; + + /** + * @private + * @type {ol.style.IconOrigin} + */ + this.offsetOrigin_ = goog.isDef(options.offsetOrigin) ? + options.offsetOrigin : ol.style.IconOrigin.TOP_LEFT; + + /** + * @private + * @type {Array.} + */ + this.origin_ = null; + /** * @private * @type {ol.Size} @@ -122,12 +141,6 @@ ol.style.Icon = function(opt_options) { */ var opacity = goog.isDef(options.opacity) ? options.opacity : 1; - /** - * @private - * @type {Array.} - */ - var origin = goog.isDef(options.origin) ? options.origin : [0, 0]; - /** * @type {boolean} */ @@ -152,7 +165,6 @@ ol.style.Icon = function(opt_options) { goog.base(this, { opacity: opacity, - origin: origin, rotation: rotation, scale: scale, snapToPixel: snapToPixel, @@ -187,19 +199,19 @@ ol.style.Icon.prototype.getAnchor = function() { } } - if (this.anchorOrigin_ != ol.style.IconAnchorOrigin.TOP_LEFT) { + if (this.anchorOrigin_ != ol.style.IconOrigin.TOP_LEFT) { if (goog.isNull(size)) { return null; } if (anchor === this.anchor_) { anchor = this.anchor_.slice(); } - if (this.anchorOrigin_ == ol.style.IconAnchorOrigin.TOP_RIGHT || - this.anchorOrigin_ == ol.style.IconAnchorOrigin.BOTTOM_RIGHT) { + if (this.anchorOrigin_ == ol.style.IconOrigin.TOP_RIGHT || + this.anchorOrigin_ == ol.style.IconOrigin.BOTTOM_RIGHT) { anchor[0] = -anchor[0] + size[0]; } - if (this.anchorOrigin_ == ol.style.IconAnchorOrigin.BOTTOM_LEFT || - this.anchorOrigin_ == ol.style.IconAnchorOrigin.BOTTOM_RIGHT) { + if (this.anchorOrigin_ == ol.style.IconOrigin.BOTTOM_LEFT || + this.anchorOrigin_ == ol.style.IconOrigin.BOTTOM_RIGHT) { anchor[1] = -anchor[1] + size[1]; } } @@ -233,6 +245,37 @@ ol.style.Icon.prototype.getHitDetectionImage = function(pixelRatio) { }; +/** + * @inheritDoc + * @todo api + */ +ol.style.Icon.prototype.getOrigin = function() { + if (!goog.isNull(this.origin_)) { + return this.origin_; + } + var offset = this.offset_; + + if (this.offsetOrigin_ != ol.style.IconOrigin.TOP_LEFT) { + var size = this.getSize(); + var iconImageSize = this.iconImage_.getSize(); + if (goog.isNull(size) || goog.isNull(iconImageSize)) { + return null; + } + offset = offset.slice(); + if (this.offsetOrigin_ == ol.style.IconOrigin.TOP_RIGHT || + this.offsetOrigin_ == ol.style.IconOrigin.BOTTOM_RIGHT) { + offset[0] = iconImageSize[0] - size[0] - offset[0]; + } + if (this.offsetOrigin_ == ol.style.IconOrigin.BOTTOM_LEFT || + this.offsetOrigin_ == ol.style.IconOrigin.BOTTOM_RIGHT) { + offset[1] = iconImageSize[1] - size[1] - offset[1]; + } + } + this.origin_ = offset; + return this.origin_; +}; + + /** * @return {string|undefined} Image src. * @todo api diff --git a/src/ol/style/imagestyle.js b/src/ol/style/imagestyle.js index 787f308f4e..db63ef8937 100644 --- a/src/ol/style/imagestyle.js +++ b/src/ol/style/imagestyle.js @@ -15,7 +15,6 @@ ol.style.ImageState = { /** * @typedef {{opacity: number, - * origin: Array., * rotateWithView: boolean, * rotation: number, * scale: number, @@ -37,12 +36,6 @@ ol.style.Image = function(options) { */ this.opacity_ = options.opacity; - /** - * @private - * @type {Array.} - */ - this.origin_ = options.origin; - /** * @private * @type {boolean} @@ -78,14 +71,6 @@ ol.style.Image.prototype.getOpacity = function() { }; -/** - * @return {Array.} Origin. - */ -ol.style.Image.prototype.getOrigin = function() { - return this.origin_; -}; - - /** * @return {boolean} Rotate with map. */ @@ -148,6 +133,13 @@ ol.style.Image.prototype.getImageState = goog.abstractMethod; ol.style.Image.prototype.getHitDetectionImage = goog.abstractMethod; +/** + * @function + * @return {Array.} Origin. + */ +ol.style.Image.prototype.getOrigin = goog.abstractMethod; + + /** * @function * @return {ol.Size} Size.