From 2d12531105d3a2c8d0b5456d669b030e669ece1e Mon Sep 17 00:00:00 2001 From: Andreas Hocevar Date: Fri, 5 Dec 2014 13:33:44 +0100 Subject: [PATCH 1/8] 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; +}; From 8d9acb8f4825ab5b8bcb5f9c2f8e645e68e324cd Mon Sep 17 00:00:00 2001 From: Andreas Hocevar Date: Tue, 9 Dec 2014 20:07:53 +0100 Subject: [PATCH 2/8] Add an example showing the use of ol.style.Style#geometry --- examples/earthquake-clusters.html | 75 +++++++++++++++ examples/earthquake-clusters.js | 155 ++++++++++++++++++++++++++++++ 2 files changed, 230 insertions(+) create mode 100644 examples/earthquake-clusters.html create mode 100644 examples/earthquake-clusters.js diff --git a/examples/earthquake-clusters.html b/examples/earthquake-clusters.html new file mode 100644 index 0000000000..d3f630e066 --- /dev/null +++ b/examples/earthquake-clusters.html @@ -0,0 +1,75 @@ + + + + + + + + + + + Earthquake Clusters + + + + + + +
+ +
+
+
+
+
+ +
+ +
+

Earthquake Clusters

+

Demonstrates the use of style geometries to render source features of a cluster.

+
+

+ This example parses a KML file and renders the features as clusters on a vector layer. The styling in this example is quite involved. Single earthquake locations (rendered as stars) have a size relative to their magnitude. Clusters have an opacity relative to the number of features in the cluster, and a size that represents the extent of the features that make up the cluster. When clicking or hovering on a cluster, the individual features that make up the cluster will be shown. +

+

To achieve this, we make heavy use of style functions and ol.style.Style#geometry. See the earthquake-clusters.js source to see how this is done.

+
+
KML, vector, style, geometry, cluster
+
+
+ +
+ + + + + + + + diff --git a/examples/earthquake-clusters.js b/examples/earthquake-clusters.js new file mode 100644 index 0000000000..862963d5cc --- /dev/null +++ b/examples/earthquake-clusters.js @@ -0,0 +1,155 @@ +goog.require('ol.Map'); +goog.require('ol.View'); +goog.require('ol.extent'); +goog.require('ol.interaction'); +goog.require('ol.interaction.Select'); +goog.require('ol.layer.Tile'); +goog.require('ol.layer.Vector'); +goog.require('ol.source.Cluster'); +goog.require('ol.source.KML'); +goog.require('ol.source.Stamen'); +goog.require('ol.style.Circle'); +goog.require('ol.style.Fill'); +goog.require('ol.style.RegularShape'); +goog.require('ol.style.Stroke'); +goog.require('ol.style.Style'); +goog.require('ol.style.Text'); + + +var earthquakeFill = new ol.style.Fill({ + color: 'rgba(255, 153, 0, 0.8)' +}); +var earthquakeStroke = new ol.style.Stroke({ + color: 'rgba(255, 204, 0, 0.2)', + width: 1 +}); +var textFill = new ol.style.Fill({ + color: '#fff' +}); +var textStroke = new ol.style.Stroke({ + color: 'rgba(0, 0, 0, 0.6)', + width: 3 +}); +var invisibleFill = new ol.style.Fill({ + color: 'rgba(255, 255, 255, 0.01)' +}); + +function createEarthquakeStyle(feature) { + // 2012_Earthquakes_Mag5.kml stores the magnitude of each earthquake in a + // standards-violating tag in each Placemark. We extract it + // from the Placemark's name instead. + var name = feature.get('name'); + var magnitude = parseFloat(name.substr(2)); + var radius = 5 + 20 * (magnitude - 5); + + return new ol.style.Style({ + geometry: feature.getGeometry(), + image: new ol.style.RegularShape({ + radius1: radius, + radius2: 3, + points: 5, + angle: Math.PI, + fill: earthquakeFill, + stroke: earthquakeStroke + }) + }); +} + +var maxFeatureCount; +function calculateClusterInfo(resolution) { + maxFeatureCount = 0; + var features = vector.getSource().getFeatures(); + var feature, radius; + for (var i = features.length - 1; i >= 0; --i) { + feature = features[i]; + var originalFeatures = feature.get('features'); + var extent = ol.extent.createEmpty(); + for (var j = 0, jj = originalFeatures.length; j < jj; ++j) { + ol.extent.extendCoordinate(extent, + originalFeatures[j].getGeometry().getCoordinates()); + } + maxFeatureCount = Math.max(maxFeatureCount, jj); + radius = 0.25 * (ol.extent.getWidth(extent) + ol.extent.getHeight(extent)) / + resolution; + feature.set('radius', radius); + } +} + +var currentResolution; +function styleFunction(feature, resolution) { + if (resolution != currentResolution) { + calculateClusterInfo(resolution); + currentResolution = resolution; + } + var style; + var size = feature.get('features').length; + if (size > 1) { + style = [new ol.style.Style({ + image: new ol.style.Circle({ + radius: feature.get('radius'), + fill: new ol.style.Fill({ + color: [255, 153, 0, Math.min(0.8, 0.4 + (size / maxFeatureCount))] + }) + }), + text: new ol.style.Text({ + text: size.toString(), + fill: textFill, + stroke: textStroke + }) + })]; + } else { + var originalFeature = feature.get('features')[0]; + style = [createEarthquakeStyle(originalFeature)]; + } + return style; +} + +function selectStyleFunction(feature, resolution) { + var styles = [new ol.style.Style({ + image: new ol.style.Circle({ + radius: feature.get('radius'), + fill: invisibleFill + }) + })]; + var originalFeatures = feature.get('features'); + var originalFeature; + for (var i = originalFeatures.length - 1; i >= 0; --i) { + originalFeature = originalFeatures[i]; + styles.push(createEarthquakeStyle(originalFeature)); + } + return styles; +} + +var vector = new ol.layer.Vector({ + source: new ol.source.Cluster({ + distance: 40, + source: new ol.source.KML({ + extractStyles: false, + projection: 'EPSG:3857', + url: 'data/kml/2012_Earthquakes_Mag5.kml' + }) + }), + style: styleFunction +}); + +var raster = new ol.layer.Tile({ + source: new ol.source.Stamen({ + layer: 'toner' + }) +}); + +var map = new ol.Map({ + layers: [raster, vector], + interactions: ol.interaction.defaults().extend([new ol.interaction.Select({ + condition: function(evt) { + return evt.originalEvent.type == 'mousemove' || + evt.type == 'singleclick'; + }, + style: selectStyleFunction + })]), + target: 'map', + view: new ol.View({ + center: [0, 0], + zoom: 2 + }) +}); From 49f9690786e7b5c118d89f547d0e7b774b77d477 Mon Sep 17 00:00:00 2001 From: Andreas Hocevar Date: Wed, 10 Dec 2014 10:43:59 +0100 Subject: [PATCH 3/8] Add tests for setGeometry --- test/spec/ol/style.test.js | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/test/spec/ol/style.test.js b/test/spec/ol/style.test.js index 8c64cb0497..7e4d712e4b 100644 --- a/test/spec/ol/style.test.js +++ b/test/spec/ol/style.test.js @@ -11,6 +11,35 @@ describe('ol.style.Style', function() { expect(style.getZIndex()).to.be(0.7); }); }); + + describe('#setGeometry', function() { + var style = new ol.style.Style(); + + it('creates a geometry function from a string', function() { + var feature = new ol.Feature(); + feature.set('myGeom', new ol.geom.Point([0, 0])); + style.setGeometry('myGeom'); + expect(style.getGeometryFunction()(feature)) + .to.eql(feature.get('myGeom')); + }); + + it('creates a geometry function from a geometry', function() { + var geom = new ol.geom.Point([0, 0]); + style.setGeometry(geom); + expect(style.getGeometryFunction()()) + .to.eql(geom); + }); + + it('returns the configured geometry function', function() { + var geom = new ol.geom.Point([0, 0]); + style.setGeometry(function() { + return geom; + }); + expect(style.getGeometryFunction()()) + .to.eql(geom); + }); + }); + }); describe('ol.style.createStyleFunction()', function() { @@ -42,4 +71,6 @@ describe('ol.style.createStyleFunction()', function() { }); +goog.require('ol.Feature'); +goog.require('ol.geom.Point'); goog.require('ol.style.Style'); From 6478454a937f0efe1d433f37909d14ffb86f7b30 Mon Sep 17 00:00:00 2001 From: Andreas Hocevar Date: Mon, 15 Dec 2014 23:22:26 +0100 Subject: [PATCH 4/8] Use getGeometryFunction() in immediate API --- src/ol/render/canvas/canvasimmediate.js | 4 ++-- src/ol/render/webgl/webglimmediate.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ol/render/canvas/canvasimmediate.js b/src/ol/render/canvas/canvasimmediate.js index 15bcef6896..2e19342f64 100644 --- a/src/ol/render/canvas/canvasimmediate.js +++ b/src/ol/render/canvas/canvasimmediate.js @@ -477,8 +477,8 @@ ol.render.canvas.Immediate.prototype.drawCircleGeometry = * @api */ ol.render.canvas.Immediate.prototype.drawFeature = function(feature, style) { - var geometry = feature.getGeometry(); - if (!goog.isDefAndNotNull(geometry) || + var geometry = style.getGeometryFunction()(feature); + if (goog.isNull(geometry) || !ol.extent.intersects(this.extent_, geometry.getExtent())) { return; } diff --git a/src/ol/render/webgl/webglimmediate.js b/src/ol/render/webgl/webglimmediate.js index 5095504b7a..2a388b37fa 100644 --- a/src/ol/render/webgl/webglimmediate.js +++ b/src/ol/render/webgl/webglimmediate.js @@ -118,8 +118,8 @@ ol.render.webgl.Immediate.prototype.drawCircleGeometry = * @api */ ol.render.webgl.Immediate.prototype.drawFeature = function(feature, style) { - var geometry = feature.getGeometry(); - if (!goog.isDefAndNotNull(geometry) || + var geometry = style.getGeometryFunction()(feature); + if (goog.isNull(geometry) || !ol.extent.intersects(this.extent_, geometry.getExtent())) { return; } From af30b88413b0c11b54fee54e53446bace3216cbc Mon Sep 17 00:00:00 2001 From: Andreas Hocevar Date: Tue, 16 Dec 2014 01:12:08 +0100 Subject: [PATCH 5/8] Allow geometryFunction to return undefined --- externs/olx.js | 4 ++-- src/ol/render/canvas/canvasimmediate.js | 2 +- src/ol/render/vector.js | 2 +- src/ol/render/webgl/webglimmediate.js | 2 +- src/ol/style/style.js | 15 +++++++-------- 5 files changed, 12 insertions(+), 13 deletions(-) diff --git a/externs/olx.js b/externs/olx.js index fbbac87ba0..f80a1c0467 100644 --- a/externs/olx.js +++ b/externs/olx.js @@ -6075,7 +6075,7 @@ olx.style.TextOptions.prototype.stroke; /** - * @typedef {{geometry: (undefined|string|ol.geom.Geometry|function(ol.Feature): ol.geom.Geometry), + * @typedef {{geometry: (undefined|string|ol.geom.Geometry|function(ol.Feature): (ol.geom.Geometry|undefined)), * fill: (ol.style.Fill|undefined), * image: (ol.style.Image|undefined), * stroke: (ol.style.Stroke|undefined), @@ -6089,7 +6089,7 @@ 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} + * @type {undefined|string|ol.geom.Geometry|function(ol.Feature): (ol.geom.Geometry|undefined)} * @api */ olx.style.StyleOptions.prototype.geometry; diff --git a/src/ol/render/canvas/canvasimmediate.js b/src/ol/render/canvas/canvasimmediate.js index 2e19342f64..efaaac5893 100644 --- a/src/ol/render/canvas/canvasimmediate.js +++ b/src/ol/render/canvas/canvasimmediate.js @@ -478,7 +478,7 @@ ol.render.canvas.Immediate.prototype.drawCircleGeometry = */ ol.render.canvas.Immediate.prototype.drawFeature = function(feature, style) { var geometry = style.getGeometryFunction()(feature); - if (goog.isNull(geometry) || + if (!goog.isDefAndNotNull(geometry) || !ol.extent.intersects(this.extent_, geometry.getExtent())) { return; } diff --git a/src/ol/render/vector.js b/src/ol/render/vector.js index a1f3a3d832..e02c7ada18 100644 --- a/src/ol/render/vector.js +++ b/src/ol/render/vector.js @@ -124,7 +124,7 @@ ol.renderer.vector.renderFeature = function( ol.renderer.vector.renderFeature_ = function( replayGroup, feature, style, squaredTolerance) { var geometry = style.getGeometryFunction()(feature); - if (goog.isNull(geometry)) { + if (!goog.isDefAndNotNull(geometry)) { return; } var simplifiedGeometry = geometry.getSimplifiedGeometry(squaredTolerance); diff --git a/src/ol/render/webgl/webglimmediate.js b/src/ol/render/webgl/webglimmediate.js index 2a388b37fa..4c07223ade 100644 --- a/src/ol/render/webgl/webglimmediate.js +++ b/src/ol/render/webgl/webglimmediate.js @@ -119,7 +119,7 @@ ol.render.webgl.Immediate.prototype.drawCircleGeometry = */ ol.render.webgl.Immediate.prototype.drawFeature = function(feature, style) { var geometry = style.getGeometryFunction()(feature); - if (goog.isNull(geometry) || + if (!goog.isDefAndNotNull(geometry) || !ol.extent.intersects(this.extent_, geometry.getExtent())) { return; } diff --git a/src/ol/style/style.js b/src/ol/style/style.js index df2c619f85..6b1f33f6db 100644 --- a/src/ol/style/style.js +++ b/src/ol/style/style.js @@ -30,7 +30,7 @@ ol.style.Style = function(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} + * @type {!function(ol.Feature): (ol.geom.Geometry|undefined)} */ this.geometryFunction_ = ol.style.defaultGeometryFunction; @@ -72,9 +72,9 @@ 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. + * @return {!function(ol.Feature): (ol.geom.Geometry|undefined)} 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_; @@ -129,7 +129,7 @@ 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 + * @param {string|ol.geom.Geometry|function(ol.Feature): (ol.geom.Geometry|undefined)} geometry * Feature property or geometry or function returning a geometry to render * for this style. * @api @@ -318,10 +318,9 @@ ol.style.createDefaultEditingStyles = function() { /** * @param {ol.Feature} feature Feature to get the geometry for. - * @return {ol.geom.Geometry} Geometry to render. + * @return {ol.geom.Geometry|undefined} Geometry to render. */ ol.style.defaultGeometryFunction = function(feature) { goog.asserts.assert(!goog.isNull(feature)); - var geometry = feature.getGeometry(); - return goog.isDef(geometry) ? geometry : null; + return feature.getGeometry(); }; From 19015d2ca9bc3749d2e9a7e16413262a3f30cb2e Mon Sep 17 00:00:00 2001 From: Andreas Hocevar Date: Thu, 18 Dec 2014 10:07:57 +0100 Subject: [PATCH 6/8] Create typedef --- externs/olx.js | 8 ++++---- src/ol/style/style.js | 24 ++++++++++++++++++------ 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/externs/olx.js b/externs/olx.js index f80a1c0467..83c1e2f418 100644 --- a/externs/olx.js +++ b/externs/olx.js @@ -6075,7 +6075,7 @@ olx.style.TextOptions.prototype.stroke; /** - * @typedef {{geometry: (undefined|string|ol.geom.Geometry|function(ol.Feature): (ol.geom.Geometry|undefined)), + * @typedef {{geometry: (undefined|string|ol.geom.Geometry|ol.style.GeometryFunction), * fill: (ol.style.Fill|undefined), * image: (ol.style.Image|undefined), * stroke: (ol.style.Stroke|undefined), @@ -6087,9 +6087,9 @@ 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|undefined)} + * Feature property or geometry or function returning a geometry to render for + * this style. + * @type {undefined|string|ol.geom.Geometry|ol.style.GeometryFunction} * @api */ olx.style.StyleOptions.prototype.geometry; diff --git a/src/ol/style/style.js b/src/ol/style/style.js index 6b1f33f6db..8ea5cdc272 100644 --- a/src/ol/style/style.js +++ b/src/ol/style/style.js @@ -27,10 +27,8 @@ 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|undefined)} + * @type {!ol.style.GeometryFunction} */ this.geometryFunction_ = ol.style.defaultGeometryFunction; @@ -72,7 +70,7 @@ ol.style.Style = function(opt_options) { /** - * @return {!function(ol.Feature): (ol.geom.Geometry|undefined)} Function that + * @return {!ol.style.GeometryFunction} Function that * is called with a feature and returns the geometry to render instead of the * feature's geometry. */ @@ -129,7 +127,7 @@ 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|undefined)} geometry + * @param {string|ol.geom.Geometry|ol.style.GeometryFunction} geometry * Feature property or geometry or function returning a geometry to render * for this style. * @api @@ -139,7 +137,10 @@ ol.style.Style.prototype.setGeometry = function(geometry) { this.geometryFunction_ = geometry; } else if (goog.isString(geometry)) { this.geometryFunction_ = function(feature) { - return feature.get(geometry); + var result = feature.get(geometry); + goog.asserts.assert(!goog.isDefAndNotNull(result) || + goog.asserts.assertInstanceof(result, ol.geom.Geometry)); + return result; }; } else if (goog.isDef(geometry)) { goog.asserts.assertInstanceof(geometry, ol.geom.Geometry); @@ -317,6 +318,17 @@ ol.style.createDefaultEditingStyles = function() { /** + * A function that takes an `{ol.Feature}` as argument and returns a geometry + * that will be rendered and styled for the feature. + * + * @typedef {function(ol.Feature): (ol.geom.Geometry|undefined)} + * @api + */ +ol.style.GeometryFunction; + + +/** + * Function that is called with a feature and returns its default geometry. * @param {ol.Feature} feature Feature to get the geometry for. * @return {ol.geom.Geometry|undefined} Geometry to render. */ From 2bf191b5e3804b5362ee775ee04cc79807c0692f Mon Sep 17 00:00:00 2001 From: Andreas Hocevar Date: Thu, 18 Dec 2014 10:08:35 +0100 Subject: [PATCH 7/8] Assert that feature.get('foo') returns a geometry --- src/ol/style/style.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/ol/style/style.js b/src/ol/style/style.js index 8ea5cdc272..5aa4421765 100644 --- a/src/ol/style/style.js +++ b/src/ol/style/style.js @@ -138,8 +138,9 @@ ol.style.Style.prototype.setGeometry = function(geometry) { } else if (goog.isString(geometry)) { this.geometryFunction_ = function(feature) { var result = feature.get(geometry); - goog.asserts.assert(!goog.isDefAndNotNull(result) || - goog.asserts.assertInstanceof(result, ol.geom.Geometry)); + if (goog.isDefAndNotNull(result)) { + goog.asserts.assertInstanceof(result, ol.geom.Geometry); + } return result; }; } else if (goog.isDef(geometry)) { From 784701641d7614da430cb08e345155e58b68618f Mon Sep 17 00:00:00 2001 From: Andreas Hocevar Date: Thu, 18 Dec 2014 10:28:21 +0100 Subject: [PATCH 8/8] Add a getGeometry method --- src/ol/style/style.js | 32 +++++++++++++++++++++++++------- test/spec/ol/style.test.js | 18 ++++++++++++++++++ 2 files changed, 43 insertions(+), 7 deletions(-) diff --git a/src/ol/style/style.js b/src/ol/style/style.js index 5aa4421765..e010186eac 100644 --- a/src/ol/style/style.js +++ b/src/ol/style/style.js @@ -26,6 +26,12 @@ ol.style.Style = function(opt_options) { var options = goog.isDef(opt_options) ? opt_options : {}; + /** + * @private + * @type {string|ol.geom.Geometry|ol.style.GeometryFunction} + */ + this.geometry_ = null; + /** * @private * @type {!ol.style.GeometryFunction} @@ -70,9 +76,20 @@ ol.style.Style = function(opt_options) { /** - * @return {!ol.style.GeometryFunction} Function that - * is called with a feature and returns the geometry to render instead of the - * feature's geometry. + * @return {string|ol.geom.Geometry|ol.style.GeometryFunction} + * Feature property or geometry or function that returns the geometry that will + * be rendered with this style. + * @api + */ +ol.style.Style.prototype.getGeometry = function() { + return this.geometry_; +}; + + +/** + * @return {!ol.style.GeometryFunction} Function that is called with a feature + * and returns the geometry to render instead of the feature's geometry. + * @api */ ol.style.Style.prototype.getGeometryFunction = function() { return this.geometryFunction_; @@ -143,14 +160,15 @@ ol.style.Style.prototype.setGeometry = function(geometry) { } return result; }; + } else if (goog.isNull(geometry)) { + this.geometryFunction_ = ol.style.defaultGeometryFunction; } else if (goog.isDef(geometry)) { goog.asserts.assertInstanceof(geometry, ol.geom.Geometry); this.geometryFunction_ = function() { return geometry; }; - } else { - this.geometryFunction_ = ol.style.defaultGeometryFunction; } + this.geometry_ = geometry; }; @@ -319,8 +337,8 @@ ol.style.createDefaultEditingStyles = function() { /** - * A function that takes an `{ol.Feature}` as argument and returns a geometry - * that will be rendered and styled for the feature. + * A function that takes an {@link ol.Feature} as argument and returns an + * {@link ol.geom.Geometry} that will be rendered and styled for the feature. * * @typedef {function(ol.Feature): (ol.geom.Geometry|undefined)} * @api diff --git a/test/spec/ol/style.test.js b/test/spec/ol/style.test.js index 7e4d712e4b..2a42d4ac02 100644 --- a/test/spec/ol/style.test.js +++ b/test/spec/ol/style.test.js @@ -40,6 +40,24 @@ describe('ol.style.Style', function() { }); }); + describe('#getGeometry', function() { + + it('returns whatever was passed to setGeometry', function() { + var style = new ol.style.Style(); + style.setGeometry('foo'); + expect(style.getGeometry()).to.eql('foo'); + var geom = new ol.geom.Point([1, 2]); + style.setGeometry(geom); + expect(style.getGeometry()).to.eql(geom); + var fn = function() { return geom; }; + style.setGeometry(fn); + expect(style.getGeometry()).to.eql(fn); + style.setGeometry(null); + expect(style.getGeometry()).to.eql(null); + }); + + }); + }); describe('ol.style.createStyleFunction()', function() {