diff --git a/examples/georss-flickr.html b/examples/georss-flickr.html index e2991466bd..7780bef6d0 100644 --- a/examples/georss-flickr.html +++ b/examples/georss-flickr.html @@ -28,9 +28,7 @@ // create a property style that reads the externalGraphic url from // the thumbail attribute of the rss item - style = new OpenLayers.Style({ - externalGraphic: "${thumbnail}", - pointRadius: 20}); + style = new OpenLayers.Style({externalGraphic: "${thumbnail}"}); // create a rule with a point symbolizer that will make the thumbnail // larger if the title of the rss item conatins "powder" @@ -41,7 +39,11 @@ symbolizer: {"Point": {pointRadius: 30}}}); rule.value2regex("*"); - style.addRules([rule]); + // If the above rule does not apply, use a smaller pointRadius. + var elseRule = new OpenLayers.Rule({ + symbolizer: {"Point": {pointRadius: 20}}}); + + style.addRules([rule, elseRule]); markerLayer = new OpenLayers.Layer.Vector("", {style: style}); map.addLayer(markerLayer); diff --git a/examples/tasmania/sld-tasmania.xml b/examples/tasmania/sld-tasmania.xml index d2df3bf24a..fb6616c61f 100644 --- a/examples/tasmania/sld-tasmania.xml +++ b/examples/tasmania/sld-tasmania.xml @@ -51,6 +51,12 @@ + + testRuleNameElse + title + Abstract + + @@ -113,7 +119,12 @@ - + + testRuleNameHoverElse + title + Abstract + + diff --git a/lib/OpenLayers/Format/SLD.js b/lib/OpenLayers/Format/SLD.js index 77dcf0c955..942f73b540 100644 --- a/lib/OpenLayers/Format/SLD.js +++ b/lib/OpenLayers/Format/SLD.js @@ -106,6 +106,7 @@ OpenLayers.Format.SLD = OpenLayers.Class(OpenLayers.Format.XML, { data = OpenLayers.Format.XML.prototype.read.apply(this, [data]); } + options = options || {}; OpenLayers.Util.applyDefaults(options, { withNamedLayer: false, overrideDefaultStyleKey: true @@ -206,7 +207,7 @@ OpenLayers.Format.SLD = OpenLayers.Class(OpenLayers.Format.XML, { if (filter && filter.length > 0) { var rule = this.parseFilter(filter[0]); } else { - // rule applies to all features + // rule applies to all features (no filter or ElseFilter) var rule = new OpenLayers.Rule(); } rule.name = name; @@ -218,7 +219,8 @@ OpenLayers.Format.SLD = OpenLayers.Class(OpenLayers.Format.XML, { xmlNode, this.sldns, "MinScaleDenominator" ); if (minScale && minScale.length > 0) { - rule.minScale = parseFloat(this.getChildValue(minScale[0])); + rule.minScaleDenominator = + parseFloat(this.getChildValue(minScale[0])); } // MaxScaleDenominator @@ -226,7 +228,8 @@ OpenLayers.Format.SLD = OpenLayers.Class(OpenLayers.Format.XML, { xmlNode, this.sldns, "MaxScaleDenominator" ); if (maxScale && maxScale.length > 0) { - rule.maxScale = parseFloat(this.getChildValue(maxScale[0])); + rule.maxScaleDenominator = + parseFloat(this.getChildValue(maxScale[0])); } // STYLES diff --git a/lib/OpenLayers/Rule.js b/lib/OpenLayers/Rule.js index 2214d0c2c9..c207688b92 100644 --- a/lib/OpenLayers/Rule.js +++ b/lib/OpenLayers/Rule.js @@ -28,21 +28,21 @@ OpenLayers.Rule = OpenLayers.Class({ symbolizer: null, /** - * APIProperty: minScale + * APIProperty: minScaleDenominator * {Number} or {String} minimum scale at which to draw the feature. * In the case of a String, this can be a combination of text and * propertyNames in the form "literal ${propertyName}" */ - minScale: null, + minScaleDenominator: null, /** - * APIProperty: maxScale + * APIProperty: maxScaleDenominator * {Number} or {String} maximum scale at which to draw the feature. * In the case of a String, this can be a combination of text and * propertyNames in the form "literal ${propertyName}" */ - maxScale: null, - + maxScaleDenominator: null, + /** * Constructor: OpenLayers.Rule * Creates a Rule. diff --git a/lib/OpenLayers/Style.js b/lib/OpenLayers/Style.js index e265cd79ec..a5f1dd920b 100644 --- a/lib/OpenLayers/Style.js +++ b/lib/OpenLayers/Style.js @@ -107,47 +107,75 @@ OpenLayers.Style = OpenLayers.Class({ * Returns: * {} hash of feature styles */ - createStyle: function(feature, baseStyle) { - if (!baseStyle) { - baseStyle = this.defaultStyle; - } - var style = OpenLayers.Util.extend({}, baseStyle); + createStyle: function(feature) { + var style = OpenLayers.Util.extend({}, this.defaultStyle); - var draw = true; + var rules = this.rules; + var draw = rules.length == 0 ? true : false; - for (var i=0; i OpenLayers.Style.createLiteral( - this.rules[i].minScale, feature); - } - if (draw && this.rules[i].maxScale) { - draw = scale < OpenLayers.Style.createLiteral( - this.rules[i].maxScale, feature); - } - + } + + // check if within minScale/maxScale bounds + if (rule.minScaleDenominator) { + applies = scale >= OpenLayers.Style.createLiteral( + rule.minScaleDenominator, feature); + } + if (applies && rule.maxScaleDenominator) { + applies = scale < OpenLayers.Style.createLiteral( + rule.maxScaleDenominator, feature); + } + + if (draw && rule.CLASS_NAME == "OpenLayers.Rule") { + // apply plain rules only if no other applied (ElseFilter) + applies = false; + } + + if (applies) { + draw = true; + // determine which symbolizer (Point, Line, Polygon) to use var symbolizerPrefix = feature.geometry ? this.getSymbolizerPrefix(feature.geometry) : OpenLayers.Style.SYMBOLIZER_PREFIXES[0]; - // now merge the style with the current style + // merge the style with the current style var symbolizer = this.rules[i].symbolizer[symbolizerPrefix]; OpenLayers.Util.extend(style, symbolizer); } } - style.display = draw ? "" : "none"; - // calculate literals for all styles in the propertyStyles cache + this.createLiterals(style, feature); + style.display = draw ? "" : "none"; + + return style; + }, + + /** + * Method: createLiterals + * creates literals for all style properties that have an entry in + * . + * + * Parameters: + * style - {Object} style to create literals for. Will be modified + * inline. + * feature - {} feature to take properties from + * + * Returns; + * {Object} the modified style + */ + createLiterals: function(style, feature) { for (var i in this.propertyStyles) { style[i] = OpenLayers.Style.createLiteral(style[i], feature); } - return style; }, diff --git a/tests/test_Style.html b/tests/test_Style.html index 1d5fd811ae..17d3184cba 100644 --- a/tests/test_Style.html +++ b/tests/test_Style.html @@ -15,7 +15,7 @@ } function test_Style_create(t) { - t.plan(5); + t.plan(10); var map = new OpenLayers.Map("map"); @@ -27,11 +27,21 @@ var style = new OpenLayers.Style(baseStyle); - var rule = new OpenLayers.Rule.FeatureId({ + var rule1 = new OpenLayers.Rule.FeatureId({ fids: ["1"], symbolizer: {"Point": {fillColor: "green"}}, - maxScale: 2000000}); - style.addRules([rule]); + maxScaleDenominator: 500000}); + var rule2 = new OpenLayers.Rule.FeatureId({ + fids: ["1"], + symbolizer: {"Point": {fillColor: "yellow"}}, + minScaleDenominator: 500000, + maxScaleDenominator: 1000000}); + var rule3 = new OpenLayers.Rule.FeatureId({ + fids: ["1"], + symbolizer: {"Point": {fillColor: "red"}}, + minScaleDenominator: 1000000, + maxScaleDenominator: 2500000}); + style.addRules([rule1, rule2, rule3]); var feature = new OpenLayers.Feature.Vector( new OpenLayers.Geometry.Point(3,5), @@ -45,24 +55,37 @@ map.addLayer(layer); map.setBaseLayer(layer); - map.setCenter(new OpenLayers.LonLat(3,5), 8); - // at this scale, the feature should be visible + map.setCenter(new OpenLayers.LonLat(3,5), 10); + + // at this scale, the feature should be green var createdStyle = style.createStyle(feature); t.eq(createdStyle.externalGraphic, "barbar.png", "Calculated property style correctly."); t.eq(createdStyle.display, "", "Feature is visible at scale "+map.getScale()); + t.eq(createdStyle.fillColor, "green", "Point symbolizer from rule applied correctly."); + + map.setCenter(new OpenLayers.LonLat(3,5), 9); + // at this scale, the feature should be red + createdStyle = style.createStyle(feature); + t.eq(createdStyle.display, "", "Feature is visible at scale "+map.getScale()); + t.eq(createdStyle.fillColor, "yellow", "Point symbolizer from rule applied correctly."); + + map.setCenter(new OpenLayers.LonLat(3,5), 8); + // at this scale, the feature should be yellow + createdStyle = style.createStyle(feature); + t.eq(createdStyle.display, "", "Feature is visible at scale "+map.getScale()); + t.eq(createdStyle.fillColor, "red", "Point symbolizer from rule applied correctly."); map.setCenter(new OpenLayers.LonLat(3,5), 7); // at this scale, the feature should be invisible createdStyle = style.createStyle(feature); t.eq(createdStyle.display, "none", "Feature is invisible at scale "+map.getScale()); - t.eq(createdStyle.fillColor, "green", "Point symbolizer from rule for fid=\"1\" applied correctly."); + t.eq(createdStyle.fillColor, baseStyle.fillColor, "Point symbolizer from base style applied correctly."); feature.fid = "2"; // now the rule should not apply createdStyle = style.createStyle(feature); t.eq(createdStyle.fillColor, baseStyle.fillColor, "Correct style for rule that does not apply to fid=\"2\"."); - } function test_Style_destroy(t) {