From 2d12531105d3a2c8d0b5456d669b030e669ece1e Mon Sep 17 00:00:00 2001 From: Andreas Hocevar Date: Fri, 5 Dec 2014 13:33:44 +0100 Subject: [PATCH] Allow styles to override feature geometries With this change, application developers are able to define styles that render a different geometry than the feature geometry. This can e.g. be used to render an interior point of a polygon instead of the polygon, or to render symbols like arrows along lines. --- externs/olx.js | 12 +++++++- src/ol/render/vector.js | 4 +-- src/ol/style/style.js | 61 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 74 insertions(+), 3 deletions(-) diff --git a/externs/olx.js b/externs/olx.js index 4370a7602f..fbbac87ba0 100644 --- a/externs/olx.js +++ b/externs/olx.js @@ -6075,7 +6075,8 @@ olx.style.TextOptions.prototype.stroke; /** - * @typedef {{fill: (ol.style.Fill|undefined), + * @typedef {{geometry: (undefined|string|ol.geom.Geometry|function(ol.Feature): ol.geom.Geometry), + * fill: (ol.style.Fill|undefined), * image: (ol.style.Image|undefined), * stroke: (ol.style.Stroke|undefined), * text: (ol.style.Text|undefined), @@ -6085,6 +6086,15 @@ olx.style.TextOptions.prototype.stroke; olx.style.StyleOptions; +/** + * Feature property or geometry or function returning a geometry to render + * for this style. + * @type {undefined|string|ol.geom.Geometry|function(ol.Feature): ol.geom.Geometry} + * @api + */ +olx.style.StyleOptions.prototype.geometry; + + /** * Fill style. * @type {ol.style.Fill|undefined} diff --git a/src/ol/render/vector.js b/src/ol/render/vector.js index c4481e958d..a1f3a3d832 100644 --- a/src/ol/render/vector.js +++ b/src/ol/render/vector.js @@ -123,8 +123,8 @@ ol.renderer.vector.renderFeature = function( */ ol.renderer.vector.renderFeature_ = function( replayGroup, feature, style, squaredTolerance) { - var geometry = feature.getGeometry(); - if (!goog.isDefAndNotNull(geometry)) { + var geometry = style.getGeometryFunction()(feature); + if (goog.isNull(geometry)) { return; } var simplifiedGeometry = geometry.getSimplifiedGeometry(squaredTolerance); diff --git a/src/ol/style/style.js b/src/ol/style/style.js index ad45b198c4..df2c619f85 100644 --- a/src/ol/style/style.js +++ b/src/ol/style/style.js @@ -1,7 +1,9 @@ goog.provide('ol.style.Style'); +goog.provide('ol.style.defaultGeometryFunction'); goog.require('goog.asserts'); goog.require('goog.functions'); +goog.require('ol.geom.Geometry'); goog.require('ol.geom.GeometryType'); goog.require('ol.style.Circle'); goog.require('ol.style.Fill'); @@ -24,6 +26,18 @@ ol.style.Style = function(opt_options) { var options = goog.isDef(opt_options) ? opt_options : {}; + /** + * Function that is called with a feature and returns the geometry to render + * for this style. + * @private + * @type {!function(ol.Feature): ol.geom.Geometry} + */ + this.geometryFunction_ = ol.style.defaultGeometryFunction; + + if (goog.isDef(options.geometry)) { + this.setGeometry(options.geometry); + } + /** * @private * @type {ol.style.Fill} @@ -57,6 +71,16 @@ ol.style.Style = function(opt_options) { }; +/** + * @return {!function(ol.Feature): ol.geom.Geometry} Function that is called + * with a feature and returns the geometry to render instead of the feature's + * geometry. + */ +ol.style.Style.prototype.getGeometryFunction = function() { + return this.geometryFunction_; +}; + + /** * @return {ol.style.Fill} Fill style. * @api @@ -102,6 +126,32 @@ ol.style.Style.prototype.getZIndex = function() { }; +/** + * Set a geometry that is rendered instead of the feature's geometry. + * + * @param {string|ol.geom.Geometry|function(ol.Feature): ol.geom.Geometry} geometry + * Feature property or geometry or function returning a geometry to render + * for this style. + * @api + */ +ol.style.Style.prototype.setGeometry = function(geometry) { + if (goog.isFunction(geometry)) { + this.geometryFunction_ = geometry; + } else if (goog.isString(geometry)) { + this.geometryFunction_ = function(feature) { + return feature.get(geometry); + }; + } else if (goog.isDef(geometry)) { + goog.asserts.assertInstanceof(geometry, ol.geom.Geometry); + this.geometryFunction_ = function() { + return geometry; + }; + } else { + this.geometryFunction_ = ol.style.defaultGeometryFunction; + } +}; + + /** * Set the zIndex. * @@ -264,3 +314,14 @@ ol.style.createDefaultEditingStyles = function() { return styles; }; + + +/** + * @param {ol.Feature} feature Feature to get the geometry for. + * @return {ol.geom.Geometry} Geometry to render. + */ +ol.style.defaultGeometryFunction = function(feature) { + goog.asserts.assert(!goog.isNull(feature)); + var geometry = feature.getGeometry(); + return goog.isDef(geometry) ? geometry : null; +};