From 60f18747664067388830c2c02aa34949bafcd7cd Mon Sep 17 00:00:00 2001 From: Antoine Abt Date: Thu, 10 Jul 2014 12:11:02 +0200 Subject: [PATCH 1/5] Give precedence to feature style --- externs/olx.js | 24 ++--- src/ol/feature.js | 96 ------------------- src/ol/featureoverlay.js | 21 ++-- src/ol/interaction/drawinteraction.js | 2 +- src/ol/interaction/modifyinteraction.js | 2 +- src/ol/interaction/selectinteraction.js | 2 +- src/ol/layer/vectorlayer.js | 20 ++-- .../canvas/canvasvectorlayerrenderer.js | 11 +-- src/ol/source/imagevectorsource.js | 10 +- src/ol/style/defaultsstyle.js | 43 +++++++++ src/ol/style/style.js | 46 +++++++++ test/spec/ol/feature.test.js | 29 ------ test/spec/ol/layer/vectorlayer.test.js | 10 +- test/spec/ol/style.test.js | 32 +++++++ 14 files changed, 172 insertions(+), 176 deletions(-) create mode 100644 src/ol/style/defaultsstyle.js create mode 100644 test/spec/ol/style.test.js diff --git a/externs/olx.js b/externs/olx.js index e61df05584..854be69916 100644 --- a/externs/olx.js +++ b/externs/olx.js @@ -1662,7 +1662,7 @@ olx.interaction.DragZoomOptions.prototype.style; * snapTolerance: (number|undefined), * type: ol.geom.GeometryType, * minPointsPerRing: (number|undefined), - * style: (ol.style.Style|Array.|ol.feature.StyleFunction|undefined), + * style: (ol.style.Style|Array.|ol.style.StyleFunction|undefined), * geometryName: (string|undefined), * condition: (ol.events.ConditionType|undefined)}} * @api @@ -1709,7 +1709,7 @@ olx.interaction.DrawOptions.prototype.minPointsPerRing; /** * Style for sketch features. - * @type {ol.style.Style|Array.|ol.feature.StyleFunction|undefined} + * @type {ol.style.Style|Array.|ol.style.StyleFunction|undefined} */ olx.interaction.DrawOptions.prototype.style; @@ -1790,7 +1790,7 @@ olx.interaction.KeyboardZoomOptions.prototype.delta; /** * @typedef {{deleteCondition: (ol.events.ConditionType|undefined), * pixelTolerance: (number|undefined), - * style: (ol.style.Style|Array.|ol.feature.StyleFunction|undefined), + * style: (ol.style.Style|Array.|ol.style.StyleFunction|undefined), * features: ol.Collection}} * @api */ @@ -1817,7 +1817,7 @@ olx.interaction.ModifyOptions.prototype.pixelTolerance; /** * FeatureOverlay style. - * @type {ol.style.Style|Array.|ol.feature.StyleFunction|undefined} + * @type {ol.style.Style|Array.|ol.style.StyleFunction|undefined} */ olx.interaction.ModifyOptions.prototype.style; @@ -1875,7 +1875,7 @@ olx.interaction.PinchZoomOptions.prototype.duration; * @typedef {{addCondition: (ol.events.ConditionType|undefined), * condition: (ol.events.ConditionType|undefined), * layers: (Array.|function(ol.layer.Layer): boolean|undefined), - * style: (ol.style.Style|Array.|ol.feature.StyleFunction|undefined), + * style: (ol.style.Style|Array.|ol.style.StyleFunction|undefined), * removeCondition: (ol.events.ConditionType|undefined), * toggleCondition: (ol.events.ConditionType|undefined)}} * @api @@ -1920,7 +1920,7 @@ olx.interaction.SelectOptions.prototype.layers; /** * Style for the selected features (those in the FeatureOverlay). - * @type {ol.style.Style|Array.|ol.feature.StyleFunction|undefined} + * @type {ol.style.Style|Array.|ol.style.StyleFunction|undefined} */ olx.interaction.SelectOptions.prototype.style; @@ -2400,7 +2400,7 @@ olx.layer.TileOptions.prototype.useInterimTilesOnError; * opacity: (number|undefined), * saturation: (number|undefined), * source: ol.source.Vector, - * style: (ol.style.Style|Array.|ol.feature.StyleFunction|undefined), + * style: (ol.style.Style|Array.|ol.style.StyleFunction|undefined), * visible: (boolean|undefined)}} * @api */ @@ -2474,7 +2474,7 @@ olx.layer.VectorOptions.prototype.source; /** * Layer style. - * @type {ol.style.Style|Array.|ol.feature.StyleFunction|undefined} + * @type {ol.style.Style|Array.|ol.style.StyleFunction|undefined} */ olx.layer.VectorOptions.prototype.style; @@ -2489,7 +2489,7 @@ olx.layer.VectorOptions.prototype.visible; /** * @typedef {{features: (Array.|ol.Collection|undefined), * map: (ol.Map|undefined), - * style: (ol.style.Style|Array.|ol.feature.StyleFunction|undefined)}} + * style: (ol.style.Style|Array.|ol.style.StyleFunction|undefined)}} * @api */ olx.FeatureOverlayOptions; @@ -2511,7 +2511,7 @@ olx.FeatureOverlayOptions.prototype.map; /** * Feature style. - * @type {ol.style.Style|Array.|ol.feature.StyleFunction|undefined} + * @type {ol.style.Style|Array.|ol.style.StyleFunction|undefined} */ olx.FeatureOverlayOptions.prototype.style; @@ -3529,7 +3529,7 @@ olx.source.ImageCanvasOptions.prototype.state; * ratio: (number|undefined), * resolutions: (Array.|undefined), * source: ol.source.Vector, - * style: (ol.style.Style|Array.|ol.feature.StyleFunction|undefined)}} + * style: (ol.style.Style|Array.|ol.style.StyleFunction|undefined)}} * @api */ olx.source.ImageVectorOptions; @@ -3589,7 +3589,7 @@ olx.source.ImageVectorOptions.prototype.source; /** * Style to use when rendering features to the canvas. - * @type {ol.style.Style|Array.|ol.feature.StyleFunction|undefined} + * @type {ol.style.Style|Array.|ol.style.StyleFunction|undefined} */ olx.source.ImageVectorOptions.prototype.style; diff --git a/src/ol/feature.js b/src/ol/feature.js index 42b9466416..fd48539f50 100644 --- a/src/ol/feature.js +++ b/src/ol/feature.js @@ -291,69 +291,6 @@ ol.Feature.prototype.setGeometryName = function(name) { ol.feature.FeatureStyleFunction; -/** - * Default style function for features. - * @param {number} resolution Resolution. - * @return {Array.} Style. - * @this {ol.Feature} - */ -ol.feature.defaultFeatureStyleFunction = function(resolution) { - var fill = new ol.style.Fill({ - color: 'rgba(255,255,255,0.4)' - }); - var stroke = new ol.style.Stroke({ - color: '#3399CC', - width: 1.25 - }); - var styles = [ - new ol.style.Style({ - image: new ol.style.Circle({ - fill: fill, - stroke: stroke, - radius: 5 - }), - fill: fill, - stroke: stroke - }) - ]; - - // now that we've run it the first time, - // replace the function with a constant version - ol.feature.defaultFeatureStyleFunction = - /** @type {function(this:ol.Feature):Array.} */( - function(resolution) { - return styles; - }); - - return styles; -}; - - -/** - * A function that takes an {@link ol.Feature} and a `{number}` representing - * the view's resolution. The function should return an array of - * {@link ol.style.Style}. This way e.g. a vector layer can be styled. - * - * @typedef {function(ol.Feature, number): Array.} - * @api - */ -ol.feature.StyleFunction; - - -/** - * @param {ol.Feature} feature Feature. - * @param {number} resolution Resolution. - * @return {Array.} Style. - */ -ol.feature.defaultStyleFunction = function(feature, resolution) { - var featureStyleFunction = feature.getStyleFunction(); - if (!goog.isDef(featureStyleFunction)) { - featureStyleFunction = ol.feature.defaultFeatureStyleFunction; - } - return featureStyleFunction.call(feature, resolution); -}; - - /** * Convert the provided object into a feature style function. Functions passed * through unchanged. Arrays of ol.style.Style or single style objects wrapped @@ -388,39 +325,6 @@ ol.feature.createFeatureStyleFunction = function(obj) { }; -/** - * Convert the provided object into a style function. Functions passed through - * unchanged. Arrays of ol.style.Style or single style objects wrapped in a - * new style function. - * @param {ol.feature.StyleFunction|Array.|ol.style.Style} obj - * A style function, a single style, or an array of styles. - * @return {ol.feature.StyleFunction} A style function. - */ -ol.feature.createStyleFunction = function(obj) { - /** - * @type {ol.feature.StyleFunction} - */ - var styleFunction; - - if (goog.isFunction(obj)) { - styleFunction = /** @type {ol.feature.StyleFunction} */ (obj); - } else { - /** - * @type {Array.} - */ - var styles; - if (goog.isArray(obj)) { - styles = obj; - } else { - goog.asserts.assertInstanceof(obj, ol.style.Style); - styles = [obj]; - } - styleFunction = goog.functions.constant(styles); - } - return styleFunction; -}; - - /** * Default styles for editing features. * @return {Object.>} Styles diff --git a/src/ol/featureoverlay.js b/src/ol/featureoverlay.js index d955ee3251..e19c922b87 100644 --- a/src/ol/featureoverlay.js +++ b/src/ol/featureoverlay.js @@ -8,9 +8,9 @@ goog.require('goog.object'); goog.require('ol.Collection'); goog.require('ol.CollectionEventType'); goog.require('ol.Feature'); -goog.require('ol.feature'); goog.require('ol.render.EventType'); goog.require('ol.renderer.vector'); +goog.require('ol.style.defaults'); @@ -63,19 +63,18 @@ ol.FeatureOverlay = function(opt_options) { /** * @private - * @type {ol.style.Style|Array.|ol.feature.StyleFunction} + * @type {ol.style.Style|Array.|ol.style.StyleFunction} */ this.style_ = null; /** * @private - * @type {ol.feature.StyleFunction|undefined} + * @type {ol.style.StyleFunction|undefined} */ this.styleFunction_ = undefined; - if (goog.isDef(options.style)) { - this.setStyle(options.style); - } + this.setStyle(goog.isDef(options.style) ? + options.style : ol.style.defaults.styleFunction); if (goog.isDef(options.features)) { if (goog.isArray(options.features)) { @@ -169,7 +168,7 @@ ol.FeatureOverlay.prototype.handleMapPostCompose_ = function(event) { } var styleFunction = this.styleFunction_; if (!goog.isDef(styleFunction)) { - styleFunction = ol.feature.defaultStyleFunction; + styleFunction = ol.style.defaults.styleFunction; } var replayGroup = /** @type {ol.render.IReplayGroup} */ (event.replayGroup); @@ -270,13 +269,13 @@ ol.FeatureOverlay.prototype.setMap = function(map) { * Set the style for features. This can be a single style object, an array * of styles, or a function that takes a feature and resolution and returns * an array of styles. - * @param {ol.style.Style|Array.|ol.feature.StyleFunction} style + * @param {ol.style.Style|Array.|ol.style.StyleFunction} style * Overlay style. * @api */ ol.FeatureOverlay.prototype.setStyle = function(style) { this.style_ = style; - this.styleFunction_ = ol.feature.createStyleFunction(style); + this.styleFunction_ = ol.style.createStyleFunction(style); this.render_(); }; @@ -284,7 +283,7 @@ ol.FeatureOverlay.prototype.setStyle = function(style) { /** * Get the style for features. This returns whatever was passed to the `style` * option at construction or to the `setStyle` method. - * @return {ol.style.Style|Array.|ol.feature.StyleFunction} + * @return {ol.style.Style|Array.|ol.style.StyleFunction} * Overlay style. * @api */ @@ -295,7 +294,7 @@ ol.FeatureOverlay.prototype.getStyle = function() { /** * Get the style function. - * @return {ol.feature.StyleFunction|undefined} Style function. + * @return {ol.style.StyleFunction|undefined} Style function. * @api */ ol.FeatureOverlay.prototype.getStyleFunction = function() { diff --git a/src/ol/interaction/drawinteraction.js b/src/ol/interaction/drawinteraction.js index d2ab9de4cc..efef4bb5a7 100644 --- a/src/ol/interaction/drawinteraction.js +++ b/src/ol/interaction/drawinteraction.js @@ -205,7 +205,7 @@ goog.inherits(ol.interaction.Draw, ol.interaction.Pointer); /** - * @return {ol.feature.StyleFunction} Styles. + * @return {ol.style.StyleFunction} Styles. */ ol.interaction.Draw.getDefaultStyleFunction = function() { var styles = ol.feature.createDefaultEditingStyles(); diff --git a/src/ol/interaction/modifyinteraction.js b/src/ol/interaction/modifyinteraction.js index 3d66b33c2d..28066d44cf 100644 --- a/src/ol/interaction/modifyinteraction.js +++ b/src/ol/interaction/modifyinteraction.js @@ -769,7 +769,7 @@ ol.interaction.Modify.prototype.updateSegmentIndices_ = function( /** - * @return {ol.feature.StyleFunction} Styles. + * @return {ol.style.StyleFunction} Styles. */ ol.interaction.Modify.getDefaultStyleFunction = function() { var style = ol.feature.createDefaultEditingStyles(); diff --git a/src/ol/interaction/selectinteraction.js b/src/ol/interaction/selectinteraction.js index d9edae5165..752d17f5ac 100644 --- a/src/ol/interaction/selectinteraction.js +++ b/src/ol/interaction/selectinteraction.js @@ -204,7 +204,7 @@ ol.interaction.Select.prototype.setMap = function(map) { /** - * @return {ol.feature.StyleFunction} Styles. + * @return {ol.style.StyleFunction} Styles. */ ol.interaction.Select.getDefaultStyleFunction = function() { var styles = ol.feature.createDefaultEditingStyles(); diff --git a/src/ol/layer/vectorlayer.js b/src/ol/layer/vectorlayer.js index 90aae8bc6d..6a45fccb42 100644 --- a/src/ol/layer/vectorlayer.js +++ b/src/ol/layer/vectorlayer.js @@ -1,8 +1,9 @@ goog.provide('ol.layer.Vector'); goog.require('goog.object'); -goog.require('ol.feature'); goog.require('ol.layer.Layer'); +goog.require('ol.style.Style'); +goog.require('ol.style.defaults'); /** @@ -39,21 +40,20 @@ ol.layer.Vector = function(opt_options) { /** * User provided style. - * @type {ol.style.Style|Array.|ol.feature.StyleFunction} + * @type {ol.style.Style|Array.|ol.style.StyleFunction} * @private */ this.style_ = null; /** * Style function for use within the library. - * @type {ol.feature.StyleFunction|undefined} + * @type {ol.style.StyleFunction|undefined} * @private */ this.styleFunction_ = undefined; - if (goog.isDef(options.style)) { - this.setStyle(options.style); - } + this.setStyle(goog.isDefAndNotNull(options.style) ? + options.style : ol.style.defaults.styleFunction); }; goog.inherits(ol.layer.Vector, ol.layer.Layer); @@ -72,7 +72,7 @@ ol.layer.Vector.prototype.getRenderOrder = function() { /** * Get the style for features. This returns whatever was passed to the `style` * option at construction or to the `setStyle` method. - * @return {ol.style.Style|Array.|ol.feature.StyleFunction} + * @return {ol.style.Style|Array.|ol.style.StyleFunction} * Layer style. * @api */ @@ -83,7 +83,7 @@ ol.layer.Vector.prototype.getStyle = function() { /** * Get the style function. - * @return {ol.feature.StyleFunction|undefined} Layer style function. + * @return {ol.style.StyleFunction|undefined} Layer style function. * @api */ ol.layer.Vector.prototype.getStyleFunction = function() { @@ -104,12 +104,12 @@ ol.layer.Vector.prototype.setRenderOrder = function(renderOrder) { * Set the style for features. This can be a single style object, an array * of styles, or a function that takes a feature and resolution and returns * an array of styles. - * @param {ol.style.Style|Array.|ol.feature.StyleFunction} style + * @param {ol.style.Style|Array.|ol.style.StyleFunction} style * Layer style. * @api */ ol.layer.Vector.prototype.setStyle = function(style) { this.style_ = style; - this.styleFunction_ = ol.feature.createStyleFunction(style); + this.styleFunction_ = ol.style.createStyleFunction(style); this.dispatchChangeEvent(); }; diff --git a/src/ol/renderer/canvas/canvasvectorlayerrenderer.js b/src/ol/renderer/canvas/canvasvectorlayerrenderer.js index 9160be7192..83c764876f 100644 --- a/src/ol/renderer/canvas/canvasvectorlayerrenderer.js +++ b/src/ol/renderer/canvas/canvasvectorlayerrenderer.js @@ -6,7 +6,6 @@ goog.require('goog.events'); goog.require('ol.ViewHint'); goog.require('ol.dom'); goog.require('ol.extent'); -goog.require('ol.feature'); goog.require('ol.layer.Vector'); goog.require('ol.render.EventType'); goog.require('ol.render.canvas.ReplayGroup'); @@ -155,7 +154,7 @@ ol.renderer.canvas.VectorLayer.prototype.handleImageChange_ = ol.renderer.canvas.VectorLayer.prototype.prepareFrame = function(frameState, layerState) { - var vectorLayer = this.getLayer(); + var vectorLayer = /** @type {ol.layer.Vector} */ (this.getLayer()); goog.asserts.assertInstanceof(vectorLayer, ol.layer.Vector); var vectorSource = vectorLayer.getSource(); goog.asserts.assertInstanceof(vectorSource, ol.source.Vector); @@ -202,10 +201,6 @@ ol.renderer.canvas.VectorLayer.prototype.prepareFrame = this.dirty_ = false; - var styleFunction = vectorLayer.getStyleFunction(); - if (!goog.isDef(styleFunction)) { - styleFunction = ol.feature.defaultStyleFunction; - } var replayGroup = new ol.render.canvas.ReplayGroup( ol.renderer.vector.getTolerance(resolution, pixelRatio), extent, @@ -217,6 +212,8 @@ ol.renderer.canvas.VectorLayer.prototype.prepareFrame = * @this {ol.renderer.canvas.VectorLayer} */ function(feature) { + var styleFunction = feature.getStyleFunction() || + vectorLayer.getStyleFunction(); goog.asserts.assert(goog.isDef(styleFunction)); var dirty = this.renderFeature( feature, resolution, pixelRatio, styleFunction, replayGroup); @@ -252,7 +249,7 @@ ol.renderer.canvas.VectorLayer.prototype.prepareFrame = * @param {ol.Feature} feature Feature. * @param {number} resolution Resolution. * @param {number} pixelRatio Pixel ratio. - * @param {ol.feature.StyleFunction} styleFunction Style function. + * @param {ol.style.StyleFunction} styleFunction Style function. * @param {ol.render.canvas.ReplayGroup} replayGroup Replay group. * @return {boolean} `true` if an image is loading. */ diff --git a/src/ol/source/imagevectorsource.js b/src/ol/source/imagevectorsource.js index d444c51762..81e1703c47 100644 --- a/src/ol/source/imagevectorsource.js +++ b/src/ol/source/imagevectorsource.js @@ -6,11 +6,11 @@ goog.require('goog.events.EventType'); goog.require('goog.vec.Mat4'); goog.require('ol.dom'); goog.require('ol.extent'); -goog.require('ol.feature'); goog.require('ol.render.canvas.ReplayGroup'); goog.require('ol.renderer.vector'); goog.require('ol.source.ImageCanvas'); goog.require('ol.source.Vector'); +goog.require('ol.style.defaults'); goog.require('ol.vec.Mat4'); @@ -42,11 +42,11 @@ ol.source.ImageVector = function(options) { /** * @private - * @type {!ol.feature.StyleFunction} + * @type {!ol.style.StyleFunction} */ - this.styleFunction_ = goog.isDef(options.style) ? - ol.feature.createStyleFunction(options.style) : - ol.feature.defaultStyleFunction; + this.styleFunction_ = goog.isDefAndNotNull(options.style) ? + ol.style.createStyleFunction(options.style) : + ol.style.defaults.styleFunction; /** * @private diff --git a/src/ol/style/defaultsstyle.js b/src/ol/style/defaultsstyle.js new file mode 100644 index 0000000000..67356e56a0 --- /dev/null +++ b/src/ol/style/defaultsstyle.js @@ -0,0 +1,43 @@ +goog.provide('ol.style.defaults'); + +goog.require('ol.style.Circle'); +goog.require('ol.style.Fill'); +goog.require('ol.style.Stroke'); +goog.require('ol.style.Style'); + + +/** + * @param {ol.Feature} feature Feature. + * @param {number} resolution Resolution. + * @return {Array.} Style. + */ +ol.style.defaults.styleFunction = function(feature, resolution) { + var fill = new ol.style.Fill({ + color: 'rgba(255,255,255,0.4)' + }); + var stroke = new ol.style.Stroke({ + color: '#3399CC', + width: 1.25 + }); + var styles = [ + new ol.style.Style({ + image: new ol.style.Circle({ + fill: fill, + stroke: stroke, + radius: 5 + }), + fill: fill, + stroke: stroke + }) + ]; + + // now that we've run it the first time, + // replace the function with a constant version + ol.style.defaults.styleFunction = + /** @type {function(this:ol.Feature):Array.} */( + function(resolution) { + return styles; + }); + + return styles; +}; diff --git a/src/ol/style/style.js b/src/ol/style/style.js index 2f84cbe1ca..56f47263f9 100644 --- a/src/ol/style/style.js +++ b/src/ol/style/style.js @@ -1,5 +1,7 @@ goog.provide('ol.style.Style'); +goog.require('goog.asserts'); +goog.require('goog.functions'); goog.require('ol.style.Fill'); goog.require('ol.style.Image'); @@ -93,3 +95,47 @@ ol.style.Style.prototype.getText = function() { ol.style.Style.prototype.getZIndex = function() { return this.zIndex_; }; + + +/** + * A function that takes an {@link ol.Feature} and a `{number}` representing + * the view's resolution. The function should return an array of + * {@link ol.style.Style}. This way e.g. a vector layer can be styled. + * + * @typedef {function(ol.Feature, number): Array.} + * @api + */ +ol.style.StyleFunction; + + +/** + * Convert the provided object into a style function. Functions passed through + * unchanged. Arrays of ol.style.Style or single style objects wrapped in a + * new style function. + * @param {ol.style.StyleFunction|Array.|ol.style.Style} obj + * A style function, a single style, or an array of styles. + * @return {ol.style.StyleFunction} A style function. + */ +ol.style.createStyleFunction = function(obj) { + /** + * @type {ol.style.StyleFunction} + */ + var styleFunction; + + if (goog.isFunction(obj)) { + styleFunction = /** @type {ol.style.StyleFunction} */ (obj); + } else { + /** + * @type {Array.} + */ + var styles; + if (goog.isArray(obj)) { + styles = obj; + } else { + goog.asserts.assertInstanceof(obj, ol.style.Style); + styles = [obj]; + } + styleFunction = goog.functions.constant(styles); + } + return styleFunction; +}; diff --git a/test/spec/ol/feature.test.js b/test/spec/ol/feature.test.js index 89cc2330bc..fefcec6c08 100644 --- a/test/spec/ol/feature.test.js +++ b/test/spec/ol/feature.test.js @@ -411,35 +411,6 @@ describe('ol.Feature', function() { }); -describe('ol.feature.createStyleFunction()', function() { - var style = new ol.style.Style(); - - it('creates a style function from a single style', function() { - var styleFunction = ol.feature.createStyleFunction(style); - expect(styleFunction()).to.eql([style]); - }); - - it('creates a style function from an array of styles', function() { - var styleFunction = ol.feature.createStyleFunction([style]); - expect(styleFunction()).to.eql([style]); - }); - - it('passes through a function', function() { - var original = function() { - return [style]; - }; - var styleFunction = ol.feature.createStyleFunction(original); - expect(styleFunction).to.be(original); - }); - - it('throws on (some) unexpected input', function() { - expect(function() { - ol.feature.createStyleFunction({bogus: 'input'}); - }).to.throwException(); - }); - -}); - describe('ol.feature.createFeatureStyleFunction()', function() { var style = new ol.style.Style(); diff --git a/test/spec/ol/layer/vectorlayer.test.js b/test/spec/ol/layer/vectorlayer.test.js index f00c97ba41..3aba92bed9 100644 --- a/test/spec/ol/layer/vectorlayer.test.js +++ b/test/spec/ol/layer/vectorlayer.test.js @@ -1,5 +1,7 @@ goog.provide('ol.test.layer.Vector'); +goog.require('ol.feature'); + describe('ol.layer.Vector', function() { describe('constructor', function() { @@ -74,9 +76,10 @@ describe('ol.layer.Vector', function() { var layer = new ol.layer.Vector({ source: source }); - expect(layer.getStyleFunction()).to.be(undefined); + expect(layer.getStyleFunction()).to.be(ol.style.defaults.styleFunction); layer.setStyle(style); - expect(layer.getStyleFunction()).to.be.a('function'); + expect(layer.getStyleFunction()).not.to.be( + ol.feature.defaultStyleFunction); }); }); @@ -91,7 +94,7 @@ describe('ol.layer.Vector', function() { source: source }); - expect(layer.getStyle()).to.be(null); + expect(layer.getStyle()).to.be(ol.style.defaults.styleFunction); layer.setStyle(style); expect(layer.getStyle()).to.be(style); @@ -115,3 +118,4 @@ goog.require('ol.layer.Layer'); goog.require('ol.layer.Vector'); goog.require('ol.source.Vector'); goog.require('ol.style.Style'); +goog.require('ol.style.defaults'); diff --git a/test/spec/ol/style.test.js b/test/spec/ol/style.test.js new file mode 100644 index 0000000000..17eae20b5e --- /dev/null +++ b/test/spec/ol/style.test.js @@ -0,0 +1,32 @@ +goog.provide('ol.test.style.Style'); + +describe('ol.style.createStyleFunction()', function() { + var style = new ol.style.Style(); + + it('creates a style function from a single style', function() { + var styleFunction = ol.style.createStyleFunction(style); + expect(styleFunction()).to.eql([style]); + }); + + it('creates a style function from an array of styles', function() { + var styleFunction = ol.style.createStyleFunction([style]); + expect(styleFunction()).to.eql([style]); + }); + + it('passes through a function', function() { + var original = function() { + return [style]; + }; + var styleFunction = ol.style.createStyleFunction(original); + expect(styleFunction).to.be(original); + }); + + it('throws on (some) unexpected input', function() { + expect(function() { + ol.style.createStyleFunction({bogus: 'input'}); + }).to.throwException(); + }); + +}); + +goog.require('ol.style.Style'); From b7b5de659b461fd207d644d18d2cc4ede06fd42d Mon Sep 17 00:00:00 2001 From: Antoine Abt Date: Fri, 11 Jul 2014 09:33:24 +0200 Subject: [PATCH 2/5] Distinct style function types --- .../canvas/canvasvectorlayerrenderer.js | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/src/ol/renderer/canvas/canvasvectorlayerrenderer.js b/src/ol/renderer/canvas/canvasvectorlayerrenderer.js index 83c764876f..a2a1b2706b 100644 --- a/src/ol/renderer/canvas/canvasvectorlayerrenderer.js +++ b/src/ol/renderer/canvas/canvasvectorlayerrenderer.js @@ -212,12 +212,17 @@ ol.renderer.canvas.VectorLayer.prototype.prepareFrame = * @this {ol.renderer.canvas.VectorLayer} */ function(feature) { - var styleFunction = feature.getStyleFunction() || - vectorLayer.getStyleFunction(); - goog.asserts.assert(goog.isDef(styleFunction)); - var dirty = this.renderFeature( - feature, resolution, pixelRatio, styleFunction, replayGroup); - this.dirty_ = this.dirty_ || dirty; + var styles; + if (goog.isDef(feature.getStyleFunction())) { + styles = feature.getStyleFunction().call(feature, resolution); + } else if (goog.isDef(vectorLayer.getStyleFunction())) { + styles = vectorLayer.getStyleFunction()(feature, resolution); + } + if (goog.isDefAndNotNull(styles)) { + var dirty = this.renderFeature( + feature, resolution, pixelRatio, styles, replayGroup); + this.dirty_ = this.dirty_ || dirty; + } }; if (!goog.isNull(vectorLayerRenderOrder)) { /** @type {Array.} */ @@ -249,13 +254,12 @@ ol.renderer.canvas.VectorLayer.prototype.prepareFrame = * @param {ol.Feature} feature Feature. * @param {number} resolution Resolution. * @param {number} pixelRatio Pixel ratio. - * @param {ol.style.StyleFunction} styleFunction Style function. + * @param {Array.} styles Array of styles * @param {ol.render.canvas.ReplayGroup} replayGroup Replay group. * @return {boolean} `true` if an image is loading. */ ol.renderer.canvas.VectorLayer.prototype.renderFeature = - function(feature, resolution, pixelRatio, styleFunction, replayGroup) { - var styles = styleFunction(feature, resolution); + function(feature, resolution, pixelRatio, styles, replayGroup) { if (!goog.isDefAndNotNull(styles)) { return false; } From c1d49a8cefd6ac76c7095186e1831aeaca8318fc Mon Sep 17 00:00:00 2001 From: Andreas Hocevar Date: Thu, 24 Jul 2014 14:31:12 +0200 Subject: [PATCH 3/5] Update to use the correct default style function namespace --- test/spec/ol/layer/vectorlayer.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/spec/ol/layer/vectorlayer.test.js b/test/spec/ol/layer/vectorlayer.test.js index 3aba92bed9..d3eb586a7f 100644 --- a/test/spec/ol/layer/vectorlayer.test.js +++ b/test/spec/ol/layer/vectorlayer.test.js @@ -79,7 +79,7 @@ describe('ol.layer.Vector', function() { expect(layer.getStyleFunction()).to.be(ol.style.defaults.styleFunction); layer.setStyle(style); expect(layer.getStyleFunction()).not.to.be( - ol.feature.defaultStyleFunction); + ol.style.defaults.styleFunction); }); }); From 16cdd35f6dc59f3618714708d9bb658e971e3ed3 Mon Sep 17 00:00:00 2001 From: Andreas Hocevar Date: Thu, 24 Jul 2014 14:37:45 +0200 Subject: [PATCH 4/5] Test to make sure that feature styles take prececence --- .../canvas/canvasvectorlayerrenderer.test.js | 72 +++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 test/spec/ol/renderer/canvas/canvasvectorlayerrenderer.test.js diff --git a/test/spec/ol/renderer/canvas/canvasvectorlayerrenderer.test.js b/test/spec/ol/renderer/canvas/canvasvectorlayerrenderer.test.js new file mode 100644 index 0000000000..ada7c28f77 --- /dev/null +++ b/test/spec/ol/renderer/canvas/canvasvectorlayerrenderer.test.js @@ -0,0 +1,72 @@ +goog.provide('ol.test.renderer.canvas.VectorLayer'); + +describe('ol.renderer.canvas.VectorLayer', function() { + + describe('constructor', function() { + + it('creates a new instance', function() { + var map = new ol.Map({ + target: document.createElement('div') + }); + var layer = new ol.layer.Vector({ + source: new ol.source.Vector() + }); + var renderer = new ol.renderer.canvas.VectorLayer(map.getRenderer(), + layer); + expect(renderer).to.be.a(ol.renderer.canvas.VectorLayer); + }); + + it('gives precedence to feature styles over layer styles', function() { + var target = document.createElement('div'); + target.style.width = '256px'; + target.style.height = '256px'; + document.body.appendChild(target); + var map = new ol.Map({ + view: new ol.View({ + center: [0, 0], + zoom: 0 + }), + target: target + }); + var layerStyle = [new ol.style.Style({ + text: new ol.style.Text({ + text: 'layer' + }) + })]; + var featureStyle = [new ol.style.Style({ + text: new ol.style.Text({ + text: 'feature' + }) + })]; + var feature1 = new ol.Feature(new ol.geom.Point([0, 0])); + var feature2 = new ol.Feature(new ol.geom.Point([0, 0])); + feature2.setStyle(featureStyle); + var layer = new ol.layer.Vector({ + source: new ol.source.Vector({ + features: [feature1, feature2] + }), + style: layerStyle + }); + map.addLayer(layer); + var spy = sinon.spy(map.getRenderer().getLayerRenderer(layer), + 'renderFeature'); + map.renderSync(); + expect(spy.getCall(0).args[3]).to.be(layerStyle); + expect(spy.getCall(1).args[3]).to.be(featureStyle); + document.body.removeChild(target); + }); + + }); + +}); + + +goog.require('ol.Feature'); +goog.require('ol.Map'); +goog.require('ol.View'); +goog.require('ol.geom.Point'); +goog.require('ol.layer.Vector'); +goog.require('ol.renderer.canvas.VectorLayer'); +goog.require('ol.source.Vector'); +goog.require('ol.style.Style'); +goog.require('ol.style.Text'); From 4b8ceca8eba4e9ff62ef5f4d20be650d8ace34b3 Mon Sep 17 00:00:00 2001 From: Antoine Abt Date: Fri, 25 Jul 2014 09:50:53 +0200 Subject: [PATCH 5/5] Move defaults style into `style.js` --- src/ol/featureoverlay.js | 6 ++-- src/ol/layer/vectorlayer.js | 3 +- src/ol/source/imagevectorsource.js | 4 +-- src/ol/style/defaultsstyle.js | 43 -------------------------- src/ol/style/style.js | 39 +++++++++++++++++++++++ test/spec/ol/layer/vectorlayer.test.js | 7 ++--- 6 files changed, 48 insertions(+), 54 deletions(-) delete mode 100644 src/ol/style/defaultsstyle.js diff --git a/src/ol/featureoverlay.js b/src/ol/featureoverlay.js index e19c922b87..09b7151342 100644 --- a/src/ol/featureoverlay.js +++ b/src/ol/featureoverlay.js @@ -10,7 +10,7 @@ goog.require('ol.CollectionEventType'); goog.require('ol.Feature'); goog.require('ol.render.EventType'); goog.require('ol.renderer.vector'); -goog.require('ol.style.defaults'); +goog.require('ol.style.Style'); @@ -74,7 +74,7 @@ ol.FeatureOverlay = function(opt_options) { this.styleFunction_ = undefined; this.setStyle(goog.isDef(options.style) ? - options.style : ol.style.defaults.styleFunction); + options.style : ol.style.defaultStyleFunction); if (goog.isDef(options.features)) { if (goog.isArray(options.features)) { @@ -168,7 +168,7 @@ ol.FeatureOverlay.prototype.handleMapPostCompose_ = function(event) { } var styleFunction = this.styleFunction_; if (!goog.isDef(styleFunction)) { - styleFunction = ol.style.defaults.styleFunction; + styleFunction = ol.style.defaultStyleFunction; } var replayGroup = /** @type {ol.render.IReplayGroup} */ (event.replayGroup); diff --git a/src/ol/layer/vectorlayer.js b/src/ol/layer/vectorlayer.js index 6a45fccb42..e7a9561967 100644 --- a/src/ol/layer/vectorlayer.js +++ b/src/ol/layer/vectorlayer.js @@ -3,7 +3,6 @@ goog.provide('ol.layer.Vector'); goog.require('goog.object'); goog.require('ol.layer.Layer'); goog.require('ol.style.Style'); -goog.require('ol.style.defaults'); /** @@ -53,7 +52,7 @@ ol.layer.Vector = function(opt_options) { this.styleFunction_ = undefined; this.setStyle(goog.isDefAndNotNull(options.style) ? - options.style : ol.style.defaults.styleFunction); + options.style : ol.style.defaultStyleFunction); }; goog.inherits(ol.layer.Vector, ol.layer.Layer); diff --git a/src/ol/source/imagevectorsource.js b/src/ol/source/imagevectorsource.js index 81e1703c47..c73a0c8895 100644 --- a/src/ol/source/imagevectorsource.js +++ b/src/ol/source/imagevectorsource.js @@ -10,7 +10,7 @@ goog.require('ol.render.canvas.ReplayGroup'); goog.require('ol.renderer.vector'); goog.require('ol.source.ImageCanvas'); goog.require('ol.source.Vector'); -goog.require('ol.style.defaults'); +goog.require('ol.style.Style'); goog.require('ol.vec.Mat4'); @@ -46,7 +46,7 @@ ol.source.ImageVector = function(options) { */ this.styleFunction_ = goog.isDefAndNotNull(options.style) ? ol.style.createStyleFunction(options.style) : - ol.style.defaults.styleFunction; + ol.style.defaultStyleFunction; /** * @private diff --git a/src/ol/style/defaultsstyle.js b/src/ol/style/defaultsstyle.js deleted file mode 100644 index 67356e56a0..0000000000 --- a/src/ol/style/defaultsstyle.js +++ /dev/null @@ -1,43 +0,0 @@ -goog.provide('ol.style.defaults'); - -goog.require('ol.style.Circle'); -goog.require('ol.style.Fill'); -goog.require('ol.style.Stroke'); -goog.require('ol.style.Style'); - - -/** - * @param {ol.Feature} feature Feature. - * @param {number} resolution Resolution. - * @return {Array.} Style. - */ -ol.style.defaults.styleFunction = function(feature, resolution) { - var fill = new ol.style.Fill({ - color: 'rgba(255,255,255,0.4)' - }); - var stroke = new ol.style.Stroke({ - color: '#3399CC', - width: 1.25 - }); - var styles = [ - new ol.style.Style({ - image: new ol.style.Circle({ - fill: fill, - stroke: stroke, - radius: 5 - }), - fill: fill, - stroke: stroke - }) - ]; - - // now that we've run it the first time, - // replace the function with a constant version - ol.style.defaults.styleFunction = - /** @type {function(this:ol.Feature):Array.} */( - function(resolution) { - return styles; - }); - - return styles; -}; diff --git a/src/ol/style/style.js b/src/ol/style/style.js index 56f47263f9..b2aa63dabb 100644 --- a/src/ol/style/style.js +++ b/src/ol/style/style.js @@ -2,8 +2,10 @@ goog.provide('ol.style.Style'); goog.require('goog.asserts'); goog.require('goog.functions'); +goog.require('ol.style.Circle'); goog.require('ol.style.Fill'); goog.require('ol.style.Image'); +goog.require('ol.style.Stroke'); @@ -139,3 +141,40 @@ ol.style.createStyleFunction = function(obj) { } return styleFunction; }; + + +/** + * @param {ol.Feature} feature Feature. + * @param {number} resolution Resolution. + * @return {Array.} Style. + */ +ol.style.defaultStyleFunction = function(feature, resolution) { + var fill = new ol.style.Fill({ + color: 'rgba(255,255,255,0.4)' + }); + var stroke = new ol.style.Stroke({ + color: '#3399CC', + width: 1.25 + }); + var styles = [ + new ol.style.Style({ + image: new ol.style.Circle({ + fill: fill, + stroke: stroke, + radius: 5 + }), + fill: fill, + stroke: stroke + }) + ]; + + // now that we've run it the first time, + // replace the function with a constant version + ol.style.defaultStyleFunction = + /** @type {function(this:ol.Feature):Array.} */( + function(resolution) { + return styles; + }); + + return styles; +}; diff --git a/test/spec/ol/layer/vectorlayer.test.js b/test/spec/ol/layer/vectorlayer.test.js index d3eb586a7f..92e1d790b7 100644 --- a/test/spec/ol/layer/vectorlayer.test.js +++ b/test/spec/ol/layer/vectorlayer.test.js @@ -76,10 +76,10 @@ describe('ol.layer.Vector', function() { var layer = new ol.layer.Vector({ source: source }); - expect(layer.getStyleFunction()).to.be(ol.style.defaults.styleFunction); + expect(layer.getStyleFunction()).to.be(ol.style.defaultStyleFunction); layer.setStyle(style); expect(layer.getStyleFunction()).not.to.be( - ol.style.defaults.styleFunction); + ol.style.defaultStyleFunction); }); }); @@ -94,7 +94,7 @@ describe('ol.layer.Vector', function() { source: source }); - expect(layer.getStyle()).to.be(ol.style.defaults.styleFunction); + expect(layer.getStyle()).to.be(ol.style.defaultStyleFunction); layer.setStyle(style); expect(layer.getStyle()).to.be(style); @@ -118,4 +118,3 @@ goog.require('ol.layer.Layer'); goog.require('ol.layer.Vector'); goog.require('ol.source.Vector'); goog.require('ol.style.Style'); -goog.require('ol.style.defaults');