diff --git a/examples/getfeatureinfo.js b/examples/getfeatureinfo.js index 02f3bc06ee..4aa02f14e1 100644 --- a/examples/getfeatureinfo.js +++ b/examples/getfeatureinfo.js @@ -6,7 +6,7 @@ goog.require('ol.layer.Vector'); goog.require('ol.parser.GeoJSON'); goog.require('ol.source.TiledWMS'); goog.require('ol.source.Vector'); -goog.require('ol.style.Polygon'); +goog.require('ol.style.Fill'); goog.require('ol.style.Rule'); goog.require('ol.style.Style'); @@ -26,8 +26,8 @@ var vector = new ol.layer.Vector({ style: new ol.style.Style({rules: [ new ol.style.Rule({ symbolizers: [ - new ol.style.Polygon({ - strokeColor: '#bada55' + new ol.style.Fill({ + color: '#bada55' }) ] }) diff --git a/examples/gml.js b/examples/gml.js index feea798c01..42fc8ed276 100644 --- a/examples/gml.js +++ b/examples/gml.js @@ -6,7 +6,7 @@ goog.require('ol.layer.Vector'); goog.require('ol.parser.ogc.GML_v3'); goog.require('ol.source.MapQuestOpenAerial'); goog.require('ol.source.Vector'); -goog.require('ol.style.Polygon'); +goog.require('ol.style.Fill'); goog.require('ol.style.Rule'); goog.require('ol.style.Style'); @@ -22,8 +22,8 @@ var vector = new ol.layer.Vector({ style: new ol.style.Style({rules: [ new ol.style.Rule({ symbolizers: [ - new ol.style.Polygon({ - strokeColor: '#bada55' + new ol.style.Fill({ + color: '#bada55' }) ] }) diff --git a/examples/kml-timezones.js b/examples/kml-timezones.js index 12999a4770..f5b93ee1e6 100644 --- a/examples/kml-timezones.js +++ b/examples/kml-timezones.js @@ -7,8 +7,9 @@ goog.require('ol.layer.Vector'); goog.require('ol.parser.KML'); goog.require('ol.source.Stamen'); goog.require('ol.source.Vector'); -goog.require('ol.style.Polygon'); +goog.require('ol.style.Fill'); goog.require('ol.style.Rule'); +goog.require('ol.style.Stroke'); goog.require('ol.style.Style'); @@ -43,10 +44,12 @@ ol.expr.register('getOpacity', function() { var style = new ol.style.Style({rules: [ new ol.style.Rule({ symbolizers: [ - new ol.style.Polygon({ - strokeColor: '#ffffff', - fillColor: '#ffff33', - fillOpacity: ol.expr.parse('getOpacity()') + new ol.style.Fill({ + color: '#ffff33', + opacity: ol.expr.parse('getOpacity()') + }), + new ol.style.Stroke({ + color: '#ffffff', }) ] }) diff --git a/examples/style-rules.js b/examples/style-rules.js index dfd822b6e4..7a573935cf 100644 --- a/examples/style-rules.js +++ b/examples/style-rules.js @@ -7,9 +7,10 @@ goog.require('ol.layer.Vector'); goog.require('ol.parser.GeoJSON'); goog.require('ol.proj'); goog.require('ol.source.Vector'); -goog.require('ol.style.Line'); +goog.require('ol.style.Fill'); goog.require('ol.style.Rule'); goog.require('ol.style.Shape'); +goog.require('ol.style.Stroke'); goog.require('ol.style.Style'); goog.require('ol.style.Text'); @@ -18,25 +19,25 @@ var style = new ol.style.Style({rules: [ new ol.style.Rule({ filter: 'where == "outer"', symbolizers: [ - new ol.style.Line({ - strokeColor: ol.expr.parse('color'), - strokeWidth: 4, - strokeOpacity: 1 + new ol.style.Stroke({ + color: ol.expr.parse('color'), + width: 4, + opacity: 1 }) ] }), new ol.style.Rule({ filter: 'where == "inner"', symbolizers: [ - new ol.style.Line({ - strokeColor: '#013', - strokeWidth: 4, - strokeOpacity: 1 + new ol.style.Stroke({ + color: '#013', + width: 4, + opacity: 1 }), - new ol.style.Line({ - strokeColor: ol.expr.parse('color'), - strokeWidth: 2, - strokeOpacity: 1 + new ol.style.Stroke({ + color: ol.expr.parse('color'), + width: 2, + opacity: 1 }) ] }), @@ -45,7 +46,7 @@ var style = new ol.style.Style({rules: [ symbolizers: [ new ol.style.Shape({ size: 40, - fillColor: '#013' + fill: new ol.style.Fill({color: '#013'}) }), new ol.style.Text({ color: '#bada55', diff --git a/examples/topojson.js b/examples/topojson.js index d960151b43..9f172aecf8 100644 --- a/examples/topojson.js +++ b/examples/topojson.js @@ -6,8 +6,9 @@ goog.require('ol.layer.Vector'); goog.require('ol.parser.TopoJSON'); goog.require('ol.source.TileJSON'); goog.require('ol.source.Vector'); -goog.require('ol.style.Polygon'); +goog.require('ol.style.Fill'); goog.require('ol.style.Rule'); +goog.require('ol.style.Stroke'); goog.require('ol.style.Style'); @@ -25,12 +26,14 @@ var vector = new ol.layer.Vector({ style: new ol.style.Style({rules: [ new ol.style.Rule({ symbolizers: [ - new ol.style.Polygon({ - fillColor: '#BADA55', - fillOpacity: 0.5, - strokeColor: '#FFF', - strokeOpacity: 1, - strokeWidth: 1.5 + new ol.style.Fill({ + color: '#BADA55', + opacity: 0.5 + }), + new ol.style.Stroke({ + color: '#FFF', + opacity: 1, + width: 1.5 }) ] }) diff --git a/examples/vector-layer.js b/examples/vector-layer.js index 6d0ba24ba4..84a6125544 100644 --- a/examples/vector-layer.js +++ b/examples/vector-layer.js @@ -7,8 +7,9 @@ goog.require('ol.layer.Vector'); goog.require('ol.parser.GeoJSON'); goog.require('ol.source.MapQuestOpenAerial'); goog.require('ol.source.Vector'); -goog.require('ol.style.Polygon'); +goog.require('ol.style.Fill'); goog.require('ol.style.Rule'); +goog.require('ol.style.Stroke'); goog.require('ol.style.Style'); goog.require('ol.style.Text'); @@ -30,11 +31,13 @@ var vector = new ol.layer.Vector({ style: new ol.style.Style({rules: [ new ol.style.Rule({ symbolizers: [ - new ol.style.Polygon({ - strokeColor: '#319FD3', - strokeOpacity: 1, - fillColor: '#ffffff', - fillOpacity: 0.6 + new ol.style.Fill({ + color: '#ffffff', + opacity: 0.6 + }), + new ol.style.Stroke({ + color: '#319FD3', + opacity: 1 }) ] }), diff --git a/src/objectliterals.jsdoc b/src/objectliterals.jsdoc index d6cf8de273..8bef3bb5b5 100644 --- a/src/objectliterals.jsdoc +++ b/src/objectliterals.jsdoc @@ -612,23 +612,9 @@ */ /** - * @typedef {Object} ol.style.LineOptions - * @property {string|ol.expr.Expression|undefined} strokeColor Stroke - * color as hex color code. - * @property {number|ol.expr.Expression|undefined} strokeOpacity Stroke - * opacity (0-1). - * @property {number|ol.expr.Expression|undefined} strokeWidth Stroke - * width in pixels. - */ - -/** - * @typedef {Object} ol.style.PolygonOptions - * @property {string|ol.expr.Expression|undefined} fillColor Fill color as - * hex color code. - * @property {string|ol.expr.Expression|undefined} strokeColor Stroke - * color as hex color code. - * @property {number|ol.expr.Expression|undefined} strokeWidth Stroke - * width in pixels. + * @typedef {Object} ol.style.FillOptions + * @property {string|ol.expr.Expression|undefined} color Fill color as hex color + * code. * @property {number|ol.expr.Expression|undefined} opacity Opacity (0-1). */ @@ -642,16 +628,16 @@ * @typedef {Object} ol.style.ShapeOptions * @property {ol.style.ShapeType|undefined} type Type. * @property {number|ol.expr.Expression|undefined} size Size in pixels. - * @property {string|ol.expr.Expression|undefined} fillColor Fill color as - * hex color code. - * @property {number|ol.expr.Expression|undefined} fillOpacity Fill opacity - * (0-1). - * @property {string|ol.expr.Expression|undefined} strokeColor Stroke - * color as hex color code. - * @property {number|ol.expr.Expression|undefined} strokeOpacity Stroke opacity - * (0-1). - * @property {number|ol.expr.Expression|undefined} strokeWidth Stroke - * width in pixels. + * @property {ol.style.Fill|undefined} fill Fill symbolizer for shape. + * @property {ol.style.Stroke|undefined} stroke Stroke symbolizer for shape. + */ + +/** + * @typedef {Object} ol.style.StrokeOptions + * @property {string|ol.expr.Expression|undefined} color Stroke color as hex + * color code. + * @property {number|ol.expr.Expression|undefined} opacity Stroke opacity (0-1). + * @property {number|ol.expr.Expression|undefined} width Stroke width in pixels. */ /** diff --git a/src/ol/feature.js b/src/ol/feature.js index 8c4b5c4b4a..24de9c40e3 100644 --- a/src/ol/feature.js +++ b/src/ol/feature.js @@ -84,18 +84,11 @@ ol.Feature.prototype.getGeometry = function() { /** - * @return {Array.} Symbolizer literals. + * Get any symbolizers set directly on the feature. + * @return {Array.} Symbolizers (or null if none). */ -ol.Feature.prototype.getSymbolizerLiterals = function() { - var symbolizerLiterals = null; - if (!goog.isNull(this.symbolizers_)) { - var numSymbolizers = this.symbolizers_.length; - symbolizerLiterals = new Array(numSymbolizers); - for (var i = 0; i < numSymbolizers; ++i) { - symbolizerLiterals[i] = this.symbolizers_[i].createLiteral(this); - } - } - return symbolizerLiterals; +ol.Feature.prototype.getSymbolizers = function() { + return this.symbolizers_; }; diff --git a/src/ol/layer/vectorlayer.js b/src/ol/layer/vectorlayer.js index 2098cab13a..06c4a82e30 100644 --- a/src/ol/layer/vectorlayer.js +++ b/src/ol/layer/vectorlayer.js @@ -384,39 +384,50 @@ ol.layer.Vector.prototype.groupFeaturesBySymbolizerLiteral = var uniqueLiterals = {}, featuresBySymbolizer = [], style = this.style_, - i, j, l, feature, literals, numLiterals, literal, uniqueLiteral, key, - item; + i, j, l, feature, geom, type, symbolizers, literals, numLiterals, literal, + uniqueLiteral, key, item; for (i in features) { feature = features[i]; - literals = feature.getSymbolizerLiterals(); - if (goog.isNull(literals)) { - literals = goog.isNull(style) ? - ol.style.Style.applyDefaultStyle(feature) : - style.apply(feature); - } - numLiterals = literals.length; - for (j = 0; j < numLiterals; ++j) { - literal = literals[j]; - for (l in uniqueLiterals) { - uniqueLiteral = featuresBySymbolizer[uniqueLiterals[l]][1]; - if (literal.equals(uniqueLiteral)) { - literal = uniqueLiteral; - break; + geom = feature.getGeometry(); + if (geom) { + type = geom.getType(); + // feature level symbolizers take precedence + symbolizers = feature.getSymbolizers(); + if (!goog.isNull(symbolizers)) { + literals = ol.style.Style.createLiterals( + symbolizers, type, feature); + } else { + if (!goog.isNull(style)) { + // layer style second + literals = style.apply(feature); + } else { + literals = ol.style.Style.applyDefaultStyle(feature); } } - key = goog.getUid(literal); - if (!goog.object.containsKey(uniqueLiterals, key)) { - uniqueLiterals[key] = featuresBySymbolizer.length; - featuresBySymbolizer.push([ - /** @type {Array.} */ ([]), - /** @type {ol.style.Literal} */ (literal), - /** @type {Array} */ ([]) - ]); - } - item = featuresBySymbolizer[uniqueLiterals[key]]; - item[0].push(feature); - if (literal instanceof ol.style.TextLiteral) { - item[2].push(literals[j].text); + numLiterals = literals.length; + for (j = 0; j < numLiterals; ++j) { + literal = literals[j]; + for (l in uniqueLiterals) { + uniqueLiteral = featuresBySymbolizer[uniqueLiterals[l]][1]; + if (literal.equals(uniqueLiteral)) { + literal = uniqueLiteral; + break; + } + } + key = goog.getUid(literal); + if (!goog.object.containsKey(uniqueLiterals, key)) { + uniqueLiterals[key] = featuresBySymbolizer.length; + featuresBySymbolizer.push([ + /** @type {Array.} */ ([]), + /** @type {ol.style.Literal} */ (literal), + /** @type {Array} */ ([]) + ]); + } + item = featuresBySymbolizer[uniqueLiterals[key]]; + item[0].push(feature); + if (literal instanceof ol.style.TextLiteral) { + item[2].push(literals[j].text); + } } } } diff --git a/src/ol/parser/kml.js b/src/ol/parser/kml.js index 7242762bea..a6bd046b59 100644 --- a/src/ol/parser/kml.js +++ b/src/ol/parser/kml.js @@ -27,11 +27,9 @@ goog.require('ol.parser.DomFeatureParser'); goog.require('ol.parser.ReadFeaturesOptions'); goog.require('ol.parser.StringFeatureParser'); goog.require('ol.parser.XML'); +goog.require('ol.style.Fill'); goog.require('ol.style.Icon'); -goog.require('ol.style.Line'); -goog.require('ol.style.LineLiteral'); -goog.require('ol.style.Polygon'); -goog.require('ol.style.PolygonLiteral'); +goog.require('ol.style.Stroke'); @@ -338,48 +336,48 @@ ol.parser.KML = function(opt_options) { } }, 'LineStyle': function(node, obj) { - var symbolizer = {}; - this.readChildNodes(node, symbolizer); - if (symbolizer.color) { - symbolizer.strokeColor = symbolizer.color.color; - symbolizer.strokeOpacity = symbolizer.color.opacity; + var style = {}; // from KML + var options = {}; // for ol.style.Stroke + this.readChildNodes(node, style); + if (style.color) { + options.color = style.color.color; + options.opacity = style.color.opacity; } - if (symbolizer.width) { - symbolizer.strokeWidth = parseFloat(symbolizer.width); + if (style.width) { + options.width = parseFloat(style.width); } - delete symbolizer.color; - delete symbolizer.width; obj['ids'].push(node.getAttribute('id')); - obj['symbolizers'].push(new ol.style.Line(symbolizer)); + obj['symbolizers'].push(new ol.style.Stroke(options)); }, 'PolyStyle': function(node, obj) { var style = {}; // from KML - var symbolizer = {}; // for ol.style.Polygon + var options = {}; // for ol.style.Fill this.readChildNodes(node, style); // check if poly has fill if (!(style.fill === '0' || style.fill === 'false')) { if (style.color) { - symbolizer.fillColor = style.color.color; - symbolizer.fillOpacity = style.color.opacity; + options.color = style.color.color; + options.opacity = style.color.opacity; } else { // KML defaults - symbolizer.fillColor = '#ffffff'; - symbolizer.fillOpacity = 1; + options.color = '#ffffff'; + options.opacity = 1; } + obj['symbolizers'].push(new ol.style.Fill(options)); } // check if poly has stroke if (!(style.outline === '0' || style.outline === 'false')) { if (style.color) { - symbolizer.strokeColor = style.color.color; - symbolizer.strokeOpacity = style.color.opacity; + options.color = style.color.color; + options.opacity = style.color.opacity; } else { // KML defaults - symbolizer.strokeColor = '#ffffff'; - symbolizer.strokeOpacity = 1; + options.color = '#ffffff'; + options.opacity = 1; } + obj['symbolizers'].push(new ol.style.Stroke(options)); } obj['ids'].push(node.getAttribute('id')); - obj['symbolizers'].push(new ol.style.Polygon(symbolizer)); }, 'fill': function(node, obj) { obj.fill = this.getChildValue(node); @@ -418,19 +416,19 @@ ol.parser.KML = function(opt_options) { }; }, 'IconStyle': function(node, obj) { - var symbolizer = {}; - this.readChildNodes(node, symbolizer); - var scale = symbolizer.scale || 1; + var style = {}; // from KML + var options = {}; // for ol.style.Icon + this.readChildNodes(node, style); + var scale = style.scale || 1; // set default width and height of icon var width = 32 * scale; var height = 32 * scale; var x, y; - delete symbolizer.scale; - if (goog.isDef(symbolizer.icon)) { - var href = symbolizer.icon.href; + if (goog.isDef(style.icon)) { + var href = style.icon.href; if (goog.isDef(href)) { - var w = symbolizer.icon.w; - var h = symbolizer.icon.h; + var w = style.icon.w; + var h = style.icon.h; // Settings for Google specific icons that are 64x64 // We set the width and height to 64 and halve the // scale to prevent icons from being too big @@ -463,45 +461,42 @@ ol.parser.KML = function(opt_options) { if (matches) { var palette = matches[1]; var file_extension = matches[2]; - x = symbolizer.icon.x; - y = symbolizer.icon.y; + x = style.icon.x; + y = style.icon.y; var posX = x ? x / 32 : 0; var posY = y ? (7 - y / 32) : 7; var pos = posY * 8 + posX; href = 'http://maps.google.com/mapfiles/kml/pal' + palette + '/icon' + pos + file_extension; } - symbolizer.opacity = 1; - symbolizer.url = href; + options.opacity = 1; + options.url = href; } } - if (goog.isDef(symbolizer.hotSpot)) { - x = symbolizer.hotSpot.x; - y = symbolizer.hotSpot.y; - var xUnits = symbolizer.hotSpot.xunits, - yUnits = symbolizer.hotSpot.yunits; + if (goog.isDef(style.hotSpot)) { + x = style.hotSpot.x; + y = style.hotSpot.y; + var xUnits = style.hotSpot.xunits, + yUnits = style.hotSpot.yunits; if (xUnits === 'pixels') { - symbolizer.graphicXOffset = -x * scale; + options.xOffset = -x * scale; } else if (xUnits === 'insetPixels') { - symbolizer.graphicXOffset = -width + (x * scale); + options.xOffset = -width + (x * scale); } else if (xUnits === 'fraction') { - symbolizer.graphicXOffset = -width * x; + options.xOffset = -width * x; } if (yUnits == 'pixels') { - symbolizer.graphicYOffset = -height + (y * scale) + 1; + options.yOffset = -height + (y * scale) + 1; } else if (yUnits == 'insetPixels') { - symbolizer.graphicYOffset = -(y * scale) + 1; + options.yOffset = -(y * scale) + 1; } else if (yUnits == 'fraction') { - symbolizer.graphicYOffset = -height * (1 - y) + 1; + options.yOffset = -height * (1 - y) + 1; } } - symbolizer.width = width; - symbolizer.height = height; - delete symbolizer.scale; - delete symbolizer.icon; - delete symbolizer.hotSpot; + options.width = width; + options.height = height; obj['ids'].push(node.getAttribute('id')); - obj['symbolizers'].push(new ol.style.Icon(symbolizer)); + obj['symbolizers'].push(new ol.style.Icon(options)); }, 'color': function(node, obj) { var kmlColor = this.getChildValue(node); @@ -611,31 +606,27 @@ ol.parser.KML = function(opt_options) { } return node; }, - '_symbolizer': function(symbolizerObj) { - var symbolizer = symbolizerObj.symbolizer; + '_symbolizer': function(obj) { + var symbolizer = obj.symbolizer; if (symbolizer instanceof ol.style.Icon) { - return this.writeNode('IconStyle', symbolizerObj); - } else if (symbolizer instanceof ol.style.Line || - symbolizer instanceof ol.style.LineLiteral) { - return this.writeNode('LineStyle', symbolizerObj); - } else if (symbolizer instanceof ol.style.Polygon || - symbolizer instanceof ol.style.PolygonLiteral) { - return this.writeNode('PolyStyle', symbolizerObj); + return this.writeNode('IconStyle', obj); + } else if (symbolizer instanceof ol.style.Stroke) { + return this.writeNode('LineStyle', obj); + } else if (symbolizer instanceof ol.style.Fill) { + return this.writeNode('PolyStyle', obj); } }, - 'PolyStyle': function(symbolizerObj) { + 'PolyStyle': function(obj) { /** - * There is not a 1:1 mapping between KML PolyStyle and - * ol.style.Polygon. In KML, if a PolyStyle has 1 + * In KML, if a PolyStyle has 1 * then the "current" LineStyle is used to stroke the polygon. */ var node = this.createElementNS('PolyStyle'); - if (symbolizerObj.id) { - this.setAttributeNS(node, null, 'id', symbolizerObj.id); + if (obj.id) { + this.setAttributeNS(node, null, 'id', obj.id); } - var symbolizer = symbolizerObj.symbolizer; - var literal = symbolizer instanceof ol.style.PolygonLiteral ? - symbolizer : symbolizer.createLiteral(); + var literal = obj.symbolizer.createLiteral( + ol.geom.GeometryType.POLYGON); var color, opacity; if (literal.fillOpacity !== 0) { this.writeNode('fill', '1', null, node); @@ -669,14 +660,13 @@ ol.parser.KML = function(opt_options) { node.appendChild(this.createTextNode(outline)); return node; }, - 'LineStyle': function(symbolizerObj) { + 'LineStyle': function(obj) { var node = this.createElementNS('LineStyle'); - if (symbolizerObj.id) { - this.setAttributeNS(node, null, 'id', symbolizerObj.id); + if (obj.id) { + this.setAttributeNS(node, null, 'id', obj.id); } - var symbolizer = symbolizerObj.symbolizer; - var literal = symbolizer instanceof ol.style.LineLiteral ? - symbolizer : symbolizer.createLiteral(); + var literal = obj.symbolizer.createLiteral( + ol.geom.GeometryType.LINESTRING); this.writeNode('color', { color: literal.strokeColor.substring(1), opacity: literal.strokeOpacity @@ -698,10 +688,11 @@ ol.parser.KML = function(opt_options) { node.appendChild(this.createTextNode(width)); return node; }, - 'IconStyle': function(symbolizerObj) { + 'IconStyle': function(obj) { var node = this.createElementNS('IconStyle'); - this.setAttributeNS(node, null, 'id', symbolizerObj.id); - this.writeNode('Icon', symbolizerObj.symbolizer.createLiteral().url, + this.setAttributeNS(node, null, 'id', obj.id); + this.writeNode('Icon', + obj.symbolizer.createLiteral(ol.geom.GeometryType.POINT).url, null, node); return node; }, @@ -723,12 +714,14 @@ ol.parser.KML = function(opt_options) { } this.writeNode('name', feature, null, node); this.writeNode('description', feature, null, node); - var literals = feature.getSymbolizerLiterals(); if (goog.isDef(feature.get('styleUrl'))) { this.writeNode('styleUrl', feature, null, node); - } else if (goog.isDefAndNotNull(literals)) { + } else { // inline style - this.writeNode('_style', {symbolizers: literals}, null, node); + var symbolizers = feature.getSymbolizers(); + if (!goog.isNull(symbolizers)) { + this.writeNode('_style', {symbolizers: symbolizers}, null, node); + } } this.writeNode('_geometry', feature.getGeometry(), null, node); return node; @@ -995,14 +988,13 @@ ol.parser.KML.prototype.read = function(data, opt_callback) { * @private * @param {ol.Feature} feature The feature to apply the style to. * @param {Array} styles The style list to search in. - * @param {Array=} opt_symbolizers Optional symbolizers. + * @param {Array.=} opt_symbolizers Optional symbolizers. */ ol.parser.KML.prototype.applyStyle_ = function(feature, styles, opt_symbolizers) { var symbolizers = opt_symbolizers; var i, ii; - if (feature.get('styleUrl') && - feature.getSymbolizerLiterals() === null) { + if (feature.get('styleUrl') && feature.getSymbolizers() === null) { var styleUrl = feature.get('styleUrl'); styleUrl = styleUrl.substring(styleUrl.indexOf('#') + 1); // look for the style and set in the feature @@ -1016,14 +1008,6 @@ ol.parser.KML.prototype.applyStyle_ = function(feature, styles, } } if (goog.isDef(symbolizers)) { - var geom = feature.getGeometry(); - if (geom && geom instanceof ol.geom.LineString) { - for (i = 0, ii = symbolizers.length; i < ii; i++) { - if (symbolizers[i] instanceof ol.style.Polygon) { - symbolizers.splice(i, 1); - } - } - } feature.setSymbolizers(symbolizers); } }; diff --git a/src/ol/style.exports b/src/ol/style.exports index d2e83eb60b..f93e92d367 100644 --- a/src/ol/style.exports +++ b/src/ol/style.exports @@ -1,8 +1,8 @@ +@exportClass ol.style.Fill ol.style.FillOptions @exportClass ol.style.Icon ol.style.IconOptions -@exportClass ol.style.Line ol.style.LineOptions -@exportClass ol.style.Polygon ol.style.PolygonOptions @exportClass ol.style.Rule ol.style.RuleOptions @exportClass ol.style.Shape ol.style.ShapeOptions +@exportClass ol.style.Stroke ol.style.StrokeOptions @exportClass ol.style.Style ol.style.StyleOptions @exportClass ol.style.Text ol.style.TextOptions @exportSymbol ol.style.IconType diff --git a/src/ol/style/fillsymbolizer.js b/src/ol/style/fillsymbolizer.js new file mode 100644 index 0000000000..9b734a76d8 --- /dev/null +++ b/src/ol/style/fillsymbolizer.js @@ -0,0 +1,117 @@ +goog.provide('ol.style.Fill'); + +goog.require('goog.asserts'); +goog.require('ol.geom.GeometryType'); +goog.require('ol.expr'); +goog.require('ol.expr.Expression'); +goog.require('ol.expr.Literal'); +goog.require('ol.style.PolygonLiteral'); +goog.require('ol.style.Symbolizer'); + + + +/** + * @constructor + * @extends {ol.style.Symbolizer} + * @param {ol.style.FillOptions=} opt_options Polygon options. + */ +ol.style.Fill = function(opt_options) { + goog.base(this); + var options = opt_options || {}; + + /** + * @type {ol.expr.Expression} + * @private + */ + this.color_ = !goog.isDefAndNotNull(options.color) ? + new ol.expr.Literal(ol.style.FillDefaults.color) : + (options.color instanceof ol.expr.Expression) ? + options.color : new ol.expr.Literal(options.color); + + /** + * @type {ol.expr.Expression} + * @private + */ + this.opacity_ = !goog.isDefAndNotNull(options.opacity) ? + new ol.expr.Literal(ol.style.FillDefaults.opacity) : + (options.opacity instanceof ol.expr.Expression) ? + options.opacity : new ol.expr.Literal(options.opacity); + +}; +goog.inherits(ol.style.Fill, ol.style.Symbolizer); + + +/** + * @inheritDoc + * @return {ol.style.PolygonLiteral} Literal shape symbolizer. + */ +ol.style.Fill.prototype.createLiteral = function(type, opt_feature) { + var literal = null; + + if (type === ol.geom.GeometryType.POLYGON || + type === ol.geom.GeometryType.MULTIPOLYGON) { + + var color = ol.expr.evaluateFeature(this.color_, opt_feature); + goog.asserts.assertString( + color, 'color must be a string'); + + var opacity = ol.expr.evaluateFeature(this.opacity_, opt_feature); + goog.asserts.assertNumber( + opacity, 'color must be a number'); + + literal = new ol.style.PolygonLiteral({ + fillColor: color, + fillOpacity: opacity + }); + } + + return literal; +}; + + +/** + * Get the fill color. + * @return {ol.expr.Expression} Fill color. + */ +ol.style.Fill.prototype.getColor = function() { + return this.color_; +}; + + +/** + * Get the fill opacity. + * @return {ol.expr.Expression} Fill opacity. + */ +ol.style.Fill.prototype.getOpacity = function() { + return this.opacity_; +}; + + +/** + * Set the fill color. + * @param {ol.expr.Expression} color Fill color. + */ +ol.style.Fill.prototype.setColor = function(color) { + goog.asserts.assertInstanceof(color, ol.expr.Expression); + this.color_ = color; +}; + + +/** + * Set the fill opacity. + * @param {ol.expr.Expression} opacity Fill opacity. + */ +ol.style.Fill.prototype.setOpacity = function(opacity) { + goog.asserts.assertInstanceof(opacity, ol.expr.Expression); + this.opacity_ = opacity; +}; + + +/** + * @typedef {{fillColor: (string), + * fillOpacity: (number)}} + */ +ol.style.FillDefaults = { + color: '#ffffff', + opacity: 0.4 +}; diff --git a/src/ol/style/iconsymbolizer.js b/src/ol/style/iconsymbolizer.js index b48564217a..e5036091ea 100644 --- a/src/ol/style/iconsymbolizer.js +++ b/src/ol/style/iconsymbolizer.js @@ -1,6 +1,7 @@ goog.provide('ol.style.Icon'); goog.require('goog.asserts'); +goog.require('ol.geom.GeometryType'); goog.require('ol.expr'); goog.require('ol.expr.Expression'); goog.require('ol.expr.Literal'); @@ -70,7 +71,7 @@ ol.style.Icon = function(options) { * @inheritDoc * @return {ol.style.IconLiteral} Literal shape symbolizer. */ -ol.style.Icon.prototype.createLiteral = function(opt_feature) { +ol.style.Icon.prototype.createLiteral = function(type, opt_feature) { var url = ol.expr.evaluateFeature(this.url_, opt_feature); goog.asserts.assertString(url, 'url must be a string'); @@ -200,10 +201,10 @@ ol.style.Icon.prototype.setWidth = function(width) { /** - * @type {ol.style.IconLiteral} + * @typedef {{opacity: (number), + * rotation: (number)}} */ -ol.style.IconDefaults = new ol.style.IconLiteral({ - url: '#', +ol.style.IconDefaults = { opacity: 1, rotation: 0 -}); +}; diff --git a/src/ol/style/linesymbolizer.js b/src/ol/style/linesymbolizer.js deleted file mode 100644 index daf9cfd660..0000000000 --- a/src/ol/style/linesymbolizer.js +++ /dev/null @@ -1,143 +0,0 @@ -goog.provide('ol.style.Line'); - -goog.require('goog.asserts'); -goog.require('ol.expr'); -goog.require('ol.expr.Expression'); -goog.require('ol.expr.Literal'); -goog.require('ol.style.LineLiteral'); -goog.require('ol.style.Symbolizer'); -goog.require('ol.style.Literal'); - - - -/** - * @constructor - * @extends {ol.style.Symbolizer} - * @param {ol.style.LineOptions} options Line options. - */ -ol.style.Line = function(options) { - goog.base(this); - - /** - * @type {ol.expr.Expression} - * @private - */ - this.strokeColor_ = !goog.isDef(options.strokeColor) ? - new ol.expr.Literal(ol.style.LineDefaults.strokeColor) : - (options.strokeColor instanceof ol.expr.Expression) ? - options.strokeColor : new ol.expr.Literal(options.strokeColor); - - /** - * @type {ol.expr.Expression} - * @private - */ - this.strokeOpacity_ = !goog.isDef(options.strokeOpacity) ? - new ol.expr.Literal(ol.style.LineDefaults.strokeOpacity) : - (options.strokeOpacity instanceof ol.expr.Expression) ? - options.strokeOpacity : new ol.expr.Literal(options.strokeOpacity); - - /** - * @type {ol.expr.Expression} - * @private - */ - this.strokeWidth_ = !goog.isDef(options.strokeWidth) ? - new ol.expr.Literal(ol.style.LineDefaults.strokeWidth) : - (options.strokeWidth instanceof ol.expr.Expression) ? - options.strokeWidth : new ol.expr.Literal(options.strokeWidth); - -}; -goog.inherits(ol.style.Line, ol.style.Symbolizer); - - -/** - * @inheritDoc - * @return {ol.style.LineLiteral} Literal line symbolizer. - */ -ol.style.Line.prototype.createLiteral = function(opt_feature) { - - var strokeColor = ol.expr.evaluateFeature( - this.strokeColor_, opt_feature); - goog.asserts.assertString(strokeColor, 'strokeColor must be a string'); - - var strokeOpacity = ol.expr.evaluateFeature( - this.strokeOpacity_, opt_feature); - goog.asserts.assertNumber(strokeOpacity, 'strokeOpacity must be a number'); - - var strokeWidth = ol.expr.evaluateFeature( - this.strokeWidth_, opt_feature); - goog.asserts.assertNumber(strokeWidth, 'strokeWidth must be a number'); - - - return new ol.style.LineLiteral({ - strokeColor: strokeColor, - strokeOpacity: strokeOpacity, - strokeWidth: strokeWidth - }); -}; - - -/** - * Get the stroke color. - * @return {ol.expr.Expression} Stroke color. - */ -ol.style.Line.prototype.getStrokeColor = function() { - return this.strokeColor_; -}; - - -/** - * Get the stroke opacity. - * @return {ol.expr.Expression} Stroke opacity. - */ -ol.style.Line.prototype.getStrokeOpacity = function() { - return this.strokeOpacity_; -}; - - -/** - * Get the stroke width. - * @return {ol.expr.Expression} Stroke width. - */ -ol.style.Line.prototype.getStrokeWidth = function() { - return this.strokeWidth_; -}; - - -/** - * Set the stroke color. - * @param {ol.expr.Expression} strokeColor Stroke color. - */ -ol.style.Line.prototype.setStrokeColor = function(strokeColor) { - goog.asserts.assertInstanceof(strokeColor, ol.expr.Expression); - this.strokeColor_ = strokeColor; -}; - - -/** - * Set the stroke opacity. - * @param {ol.expr.Expression} strokeOpacity Stroke opacity. - */ -ol.style.Line.prototype.setStrokeOpacity = function(strokeOpacity) { - goog.asserts.assertInstanceof(strokeOpacity, ol.expr.Expression); - this.strokeOpacity_ = strokeOpacity; -}; - - -/** - * Set the stroke width. - * @param {ol.expr.Expression} strokeWidth Stroke width. - */ -ol.style.Line.prototype.setStrokeWidth = function(strokeWidth) { - goog.asserts.assertInstanceof(strokeWidth, ol.expr.Expression); - this.strokeWidth_ = strokeWidth; -}; - - -/** - * @type {ol.style.LineLiteral} - */ -ol.style.LineDefaults = new ol.style.LineLiteral({ - strokeColor: '#696969', - strokeOpacity: 0.75, - strokeWidth: 1.5 -}); diff --git a/src/ol/style/polygonsymbolizer.js b/src/ol/style/polygonsymbolizer.js deleted file mode 100644 index 2e102d66ba..0000000000 --- a/src/ol/style/polygonsymbolizer.js +++ /dev/null @@ -1,286 +0,0 @@ -goog.provide('ol.style.Polygon'); - -goog.require('goog.asserts'); -goog.require('ol.expr'); -goog.require('ol.expr.Expression'); -goog.require('ol.expr.Literal'); -goog.require('ol.style.PolygonLiteral'); -goog.require('ol.style.Symbolizer'); - - - -/** - * @constructor - * @extends {ol.style.Symbolizer} - * @param {ol.style.PolygonOptions} options Polygon options. - */ -ol.style.Polygon = function(options) { - goog.base(this); - - - // fill handling - if any fill property is supplied, use all defaults - var fillColor = null, - fillOpacity = null; - - if (goog.isDefAndNotNull(options.fillColor) || - goog.isDefAndNotNull(options.fillOpacity)) { - - if (goog.isDefAndNotNull(options.fillColor)) { - fillColor = (options.fillColor instanceof ol.expr.Expression) ? - options.fillColor : - new ol.expr.Literal(options.fillColor); - } else { - fillColor = new ol.expr.Literal( - /** @type {string} */ (ol.style.PolygonDefaults.fillColor)); - } - - if (goog.isDefAndNotNull(options.fillOpacity)) { - fillOpacity = (options.fillOpacity instanceof ol.expr.Expression) ? - options.fillOpacity : - new ol.expr.Literal(options.fillOpacity); - } else { - fillOpacity = new ol.expr.Literal( - /** @type {number} */ (ol.style.PolygonDefaults.fillOpacity)); - } - - } - - /** - * @type {ol.expr.Expression} - * @private - */ - this.fillColor_ = fillColor; - - /** - * @type {ol.expr.Expression} - * @private - */ - this.fillOpacity_ = fillOpacity; - - - // stroke handling - if any stroke property is supplied, use defaults - var strokeColor = null, - strokeOpacity = null, - strokeWidth = null; - - if (goog.isDefAndNotNull(options.strokeColor) || - goog.isDefAndNotNull(options.strokeOpacity) || - goog.isDefAndNotNull(options.strokeWidth)) { - - if (goog.isDefAndNotNull(options.strokeColor)) { - strokeColor = (options.strokeColor instanceof ol.expr.Expression) ? - options.strokeColor : - new ol.expr.Literal(options.strokeColor); - } else { - strokeColor = new ol.expr.Literal( - /** @type {string} */ (ol.style.PolygonDefaults.strokeColor)); - } - - if (goog.isDefAndNotNull(options.strokeOpacity)) { - strokeOpacity = (options.strokeOpacity instanceof ol.expr.Expression) ? - options.strokeOpacity : - new ol.expr.Literal(options.strokeOpacity); - } else { - strokeOpacity = new ol.expr.Literal( - /** @type {number} */ (ol.style.PolygonDefaults.strokeOpacity)); - } - - if (goog.isDefAndNotNull(options.strokeWidth)) { - strokeWidth = (options.strokeWidth instanceof ol.expr.Expression) ? - options.strokeWidth : - new ol.expr.Literal(options.strokeWidth); - } else { - strokeWidth = new ol.expr.Literal( - /** @type {number} */ (ol.style.PolygonDefaults.strokeWidth)); - } - - } - - /** - * @type {ol.expr.Expression} - * @private - */ - this.strokeColor_ = strokeColor; - - /** - * @type {ol.expr.Expression} - * @private - */ - this.strokeOpacity_ = strokeOpacity; - - /** - * @type {ol.expr.Expression} - * @private - */ - this.strokeWidth_ = strokeWidth; - - // one of stroke or fill can be null, both null is user error - var fill = !goog.isNull(this.fillColor_) && !goog.isNull(this.fillOpacity_); - var stroke = !goog.isNull(this.strokeColor_) && - !goog.isNull(this.strokeOpacity_) && - !goog.isNull(this.strokeWidth_); - goog.asserts.assert(fill || stroke, - 'Stroke or fill properties must be provided'); - -}; -goog.inherits(ol.style.Polygon, ol.style.Symbolizer); - - -/** - * @inheritDoc - * @return {ol.style.PolygonLiteral} Literal shape symbolizer. - */ -ol.style.Polygon.prototype.createLiteral = function(opt_feature) { - - var fillColor; - if (!goog.isNull(this.fillColor_)) { - fillColor = ol.expr.evaluateFeature(this.fillColor_, opt_feature); - goog.asserts.assertString(fillColor, 'fillColor must be a string'); - } - - var fillOpacity; - if (!goog.isNull(this.fillOpacity_)) { - fillOpacity = ol.expr.evaluateFeature(this.fillOpacity_, opt_feature); - goog.asserts.assertNumber(fillOpacity, 'fillOpacity must be a number'); - } - - var strokeColor; - if (!goog.isNull(this.strokeColor_)) { - strokeColor = ol.expr.evaluateFeature(this.strokeColor_, opt_feature); - goog.asserts.assertString(strokeColor, 'strokeColor must be a string'); - } - - var strokeOpacity; - if (!goog.isNull(this.strokeOpacity_)) { - strokeOpacity = ol.expr.evaluateFeature(this.strokeOpacity_, opt_feature); - goog.asserts.assertNumber(strokeOpacity, 'strokeOpacity must be a number'); - } - - var strokeWidth; - if (!goog.isNull(this.strokeWidth_)) { - strokeWidth = ol.expr.evaluateFeature(this.strokeWidth_, opt_feature); - goog.asserts.assertNumber(strokeWidth, 'strokeWidth must be a number'); - } - - var fill = goog.isDef(fillColor) && goog.isDef(fillOpacity); - var stroke = goog.isDef(strokeColor) && goog.isDef(strokeOpacity) && - goog.isDef(strokeWidth); - - goog.asserts.assert(fill || stroke, - 'either fill or stroke properties must be defined'); - - return new ol.style.PolygonLiteral({ - fillColor: fillColor, - fillOpacity: fillOpacity, - strokeColor: strokeColor, - strokeOpacity: strokeOpacity, - strokeWidth: strokeWidth - }); -}; - - -/** - * Get the fill color. - * @return {ol.expr.Expression} Fill color. - */ -ol.style.Polygon.prototype.getFillColor = function() { - return this.fillColor_; -}; - - -/** - * Get the fill opacity. - * @return {ol.expr.Expression} Fill opacity. - */ -ol.style.Polygon.prototype.getFillOpacity = function() { - return this.fillOpacity_; -}; - - -/** - * Get the stroke color. - * @return {ol.expr.Expression} Stroke color. - */ -ol.style.Polygon.prototype.getStrokeColor = function() { - return this.strokeColor_; -}; - - -/** - * Get the stroke opacity. - * @return {ol.expr.Expression} Stroke opacity. - */ -ol.style.Polygon.prototype.getStrokeOpacity = function() { - return this.strokeOpacity_; -}; - - -/** - * Get the stroke width. - * @return {ol.expr.Expression} Stroke width. - */ -ol.style.Polygon.prototype.getStrokeWidth = function() { - return this.strokeWidth_; -}; - - -/** - * Set the fill color. - * @param {ol.expr.Expression} fillColor Fill color. - */ -ol.style.Polygon.prototype.setFillColor = function(fillColor) { - goog.asserts.assertInstanceof(fillColor, ol.expr.Expression); - this.fillColor_ = fillColor; -}; - - -/** - * Set the fill opacity. - * @param {ol.expr.Expression} fillOpacity Fill opacity. - */ -ol.style.Polygon.prototype.setFillOpacity = function(fillOpacity) { - goog.asserts.assertInstanceof(fillOpacity, ol.expr.Expression); - this.fillOpacity_ = fillOpacity; -}; - - -/** - * Set the stroke color. - * @param {ol.expr.Expression} strokeColor Stroke color. - */ -ol.style.Polygon.prototype.setStrokeColor = function(strokeColor) { - goog.asserts.assertInstanceof(strokeColor, ol.expr.Expression); - this.strokeColor_ = strokeColor; -}; - - -/** - * Set the stroke opacity. - * @param {ol.expr.Expression} strokeOpacity Stroke opacity. - */ -ol.style.Polygon.prototype.setStrokeOpacity = function(strokeOpacity) { - goog.asserts.assertInstanceof(strokeOpacity, ol.expr.Expression); - this.strokeOpacity_ = strokeOpacity; -}; - - -/** - * Set the stroke width. - * @param {ol.expr.Expression} strokeWidth Stroke width. - */ -ol.style.Polygon.prototype.setStrokeWidth = function(strokeWidth) { - goog.asserts.assertInstanceof(strokeWidth, ol.expr.Expression); - this.strokeWidth_ = strokeWidth; -}; - - -/** - * @type {ol.style.PolygonLiteral} - */ -ol.style.PolygonDefaults = new ol.style.PolygonLiteral({ - fillColor: '#ffffff', - fillOpacity: 0.4, - strokeColor: '#696969', - strokeOpacity: 0.8, - strokeWidth: 1.5 -}); diff --git a/src/ol/style/shapesymbolizer.js b/src/ol/style/shapesymbolizer.js index 2080cd72fa..0cbfabb2fa 100644 --- a/src/ol/style/shapesymbolizer.js +++ b/src/ol/style/shapesymbolizer.js @@ -1,13 +1,16 @@ goog.provide('ol.style.Shape'); goog.require('goog.asserts'); +goog.require('ol.geom.GeometryType'); goog.require('ol.expr'); goog.require('ol.expr.Expression'); goog.require('ol.expr.Literal'); +goog.require('ol.style.Fill'); goog.require('ol.style.Point'); goog.require('ol.style.PointLiteral'); goog.require('ol.style.ShapeLiteral'); goog.require('ol.style.ShapeType'); +goog.require('ol.style.Stroke'); @@ -34,109 +37,21 @@ ol.style.Shape = function(options) { (options.size instanceof ol.expr.Expression) ? options.size : new ol.expr.Literal(options.size); - // fill handling - if any fill property is supplied, use all defaults - var fillColor = null, - fillOpacity = null; - - if (goog.isDefAndNotNull(options.fillColor) || - goog.isDefAndNotNull(options.fillOpacity)) { - - if (goog.isDefAndNotNull(options.fillColor)) { - fillColor = (options.fillColor instanceof ol.expr.Expression) ? - options.fillColor : - new ol.expr.Literal(options.fillColor); - } else { - fillColor = new ol.expr.Literal( - /** @type {string} */ (ol.style.ShapeDefaults.fillColor)); - } - - if (goog.isDefAndNotNull(options.fillOpacity)) { - fillOpacity = (options.fillOpacity instanceof ol.expr.Expression) ? - options.fillOpacity : - new ol.expr.Literal(options.fillOpacity); - } else { - fillOpacity = new ol.expr.Literal( - /** @type {number} */ (ol.style.ShapeDefaults.fillOpacity)); - } - - } - /** - * @type {ol.expr.Expression} + * @type {ol.style.Fill} * @private */ - this.fillColor_ = fillColor; + this.fill_ = goog.isDefAndNotNull(options.fill) ? options.fill : null; /** - * @type {ol.expr.Expression} + * @type {ol.style.Stroke} * @private */ - this.fillOpacity_ = fillOpacity; - - - // stroke handling - if any stroke property is supplied, use defaults - var strokeColor = null, - strokeOpacity = null, - strokeWidth = null; - - if (goog.isDefAndNotNull(options.strokeColor) || - goog.isDefAndNotNull(options.strokeOpacity) || - goog.isDefAndNotNull(options.strokeWidth)) { - - if (goog.isDefAndNotNull(options.strokeColor)) { - strokeColor = (options.strokeColor instanceof ol.expr.Expression) ? - options.strokeColor : - new ol.expr.Literal(options.strokeColor); - } else { - strokeColor = new ol.expr.Literal( - /** @type {string} */ (ol.style.ShapeDefaults.strokeColor)); - } - - if (goog.isDefAndNotNull(options.strokeOpacity)) { - strokeOpacity = (options.strokeOpacity instanceof ol.expr.Expression) ? - options.strokeOpacity : - new ol.expr.Literal(options.strokeOpacity); - } else { - strokeOpacity = new ol.expr.Literal( - /** @type {number} */ (ol.style.ShapeDefaults.strokeOpacity)); - } - - if (goog.isDefAndNotNull(options.strokeWidth)) { - strokeWidth = (options.strokeWidth instanceof ol.expr.Expression) ? - options.strokeWidth : - new ol.expr.Literal(options.strokeWidth); - } else { - strokeWidth = new ol.expr.Literal( - /** @type {number} */ (ol.style.ShapeDefaults.strokeWidth)); - } - - } - - /** - * @type {ol.expr.Expression} - * @private - */ - this.strokeColor_ = strokeColor; - - /** - * @type {ol.expr.Expression} - * @private - */ - this.strokeOpacity_ = strokeOpacity; - - /** - * @type {ol.expr.Expression} - * @private - */ - this.strokeWidth_ = strokeWidth; + this.stroke_ = goog.isDefAndNotNull(options.stroke) ? options.stroke : null; // one of stroke or fill can be null, both null is user error - var fill = !goog.isNull(this.fillColor_) && !goog.isNull(this.fillOpacity_); - var stroke = !goog.isNull(this.strokeColor_) && - !goog.isNull(this.strokeOpacity_) && - !goog.isNull(this.strokeWidth_); - goog.asserts.assert(fill || stroke, - 'Stroke or fill properties must be provided'); + goog.asserts.assert(this.fill_ || this.stroke_, + 'Stroke or fill must be provided'); }; @@ -145,75 +60,59 @@ ol.style.Shape = function(options) { * @inheritDoc * @return {ol.style.ShapeLiteral} Literal shape symbolizer. */ -ol.style.Shape.prototype.createLiteral = function(opt_feature) { +ol.style.Shape.prototype.createLiteral = function(type, opt_feature) { + var literal = null; - var size = ol.expr.evaluateFeature(this.size_, opt_feature); - goog.asserts.assertNumber(size, 'size must be a number'); + if (type === ol.geom.GeometryType.POINT || + type === ol.geom.GeometryType.MULTIPOINT) { + var size = ol.expr.evaluateFeature(this.size_, opt_feature); + goog.asserts.assertNumber(size, 'size must be a number'); - var fillColor; - if (!goog.isNull(this.fillColor_)) { - fillColor = ol.expr.evaluateFeature(this.fillColor_, opt_feature); - goog.asserts.assertString(fillColor, 'fillColor must be a string'); + var fillColor, fillOpacity; + if (!goog.isNull(this.fill_)) { + fillColor = ol.expr.evaluateFeature(this.fill_.getColor(), opt_feature); + goog.asserts.assertString( + fillColor, 'fillColor must be a string'); + fillOpacity = ol.expr.evaluateFeature(this.fill_.getOpacity(), opt_feature); + goog.asserts.assertNumber( + fillOpacity, 'fillOpacity must be a number'); + } + + var strokeColor, strokeOpacity, strokeWidth; + if (!goog.isNull(this.stroke_)) { + strokeColor = ol.expr.evaluateFeature(this.stroke_.getColor(), opt_feature); + goog.asserts.assertString( + strokeColor, 'strokeColor must be a string'); + strokeOpacity = ol.expr.evaluateFeature(this.stroke_.getOpacity(), + opt_feature); + goog.asserts.assertNumber( + strokeOpacity, 'strokeOpacity must be a number'); + strokeWidth = ol.expr.evaluateFeature(this.stroke_.getWidth(), opt_feature); + goog.asserts.assertNumber( + strokeWidth, 'strokeWidth must be a number'); + } + + literal = new ol.style.ShapeLiteral({ + type: this.type_, + size: size, + fillColor: fillColor, + fillOpacity: fillOpacity, + strokeColor: strokeColor, + strokeOpacity: strokeOpacity, + strokeWidth: strokeWidth + }); } - var fillOpacity; - if (!goog.isNull(this.fillOpacity_)) { - fillOpacity = ol.expr.evaluateFeature(this.fillOpacity_, opt_feature); - goog.asserts.assertNumber(fillOpacity, 'fillOpacity must be a number'); - } - - var strokeColor; - if (!goog.isNull(this.strokeColor_)) { - strokeColor = ol.expr.evaluateFeature(this.strokeColor_, opt_feature); - goog.asserts.assertString(strokeColor, 'strokeColor must be a string'); - } - - var strokeOpacity; - if (!goog.isNull(this.strokeOpacity_)) { - strokeOpacity = ol.expr.evaluateFeature(this.strokeOpacity_, opt_feature); - goog.asserts.assertNumber(strokeOpacity, 'strokeOpacity must be a number'); - } - - var strokeWidth; - if (!goog.isNull(this.strokeWidth_)) { - strokeWidth = ol.expr.evaluateFeature(this.strokeWidth_, opt_feature); - goog.asserts.assertNumber(strokeWidth, 'strokeWidth must be a number'); - } - - var fill = goog.isDef(fillColor) && goog.isDef(fillOpacity); - var stroke = goog.isDef(strokeColor) && goog.isDef(strokeOpacity) && - goog.isDef(strokeWidth); - - goog.asserts.assert(fill || stroke, - 'either fill or stroke properties must be defined'); - - return new ol.style.ShapeLiteral({ - type: this.type_, - size: size, - fillColor: fillColor, - fillOpacity: fillOpacity, - strokeColor: strokeColor, - strokeOpacity: strokeOpacity, - strokeWidth: strokeWidth - }); + return literal; }; /** - * Get the fill color. - * @return {ol.expr.Expression} Fill color. + * Get the fill. + * @return {ol.style.Fill} Shape fill. */ -ol.style.Shape.prototype.getFillColor = function() { - return this.fillColor_; -}; - - -/** - * Get the fill opacity. - * @return {ol.expr.Expression} Fill opacity. - */ -ol.style.Shape.prototype.getFillOpacity = function() { - return this.fillOpacity_; +ol.style.Shape.prototype.getFill = function() { + return this.fill_; }; @@ -227,29 +126,11 @@ ol.style.Shape.prototype.getSize = function() { /** - * Get the stroke color. - * @return {ol.expr.Expression} Stroke color. + * Get the stroke. + * @return {ol.style.Stroke} Shape stroke. */ -ol.style.Shape.prototype.getStrokeColor = function() { - return this.strokeColor_; -}; - - -/** - * Get the stroke opacity. - * @return {ol.expr.Expression} Stroke opacity. - */ -ol.style.Shape.prototype.getStrokeOpacity = function() { - return this.strokeOpacity_; -}; - - -/** - * Get the stroke width. - * @return {ol.expr.Expression} Stroke width. - */ -ol.style.Shape.prototype.getStrokeWidth = function() { - return this.strokeWidth_; +ol.style.Shape.prototype.getStroke = function() { + return this.stroke_; }; @@ -263,22 +144,14 @@ ol.style.Shape.prototype.getType = function() { /** - * Set the fill color. - * @param {ol.expr.Expression} fillColor Fill color. + * Set the fill. + * @param {ol.style.Fill} fill Shape fill. */ -ol.style.Shape.prototype.setFillColor = function(fillColor) { - goog.asserts.assertInstanceof(fillColor, ol.expr.Expression); - this.fillColor_ = fillColor; -}; - - -/** - * Set the fill opacity. - * @param {ol.expr.Expression} fillOpacity Fill opacity. - */ -ol.style.Shape.prototype.setFillOpacity = function(fillOpacity) { - goog.asserts.assertInstanceof(fillOpacity, ol.expr.Expression); - this.fillOpacity_ = fillOpacity; +ol.style.Shape.prototype.setFill = function(fill) { + if (!goog.isNull(fill)) { + goog.asserts.assertInstanceof(fill, ol.style.Fill); + } + this.fill_ = fill; }; @@ -293,32 +166,14 @@ ol.style.Shape.prototype.setSize = function(size) { /** - * Set the stroke color. - * @param {ol.expr.Expression} strokeColor Stroke color. + * Set the stroke. + * @param {ol.style.Stroke} stroke Shape stroke. */ -ol.style.Shape.prototype.setStrokeColor = function(strokeColor) { - goog.asserts.assertInstanceof(strokeColor, ol.expr.Expression); - this.strokeColor_ = strokeColor; -}; - - -/** - * Set the stroke opacity. - * @param {ol.expr.Expression} strokeOpacity Stroke opacity. - */ -ol.style.Shape.prototype.setStrokeOpacity = function(strokeOpacity) { - goog.asserts.assertInstanceof(strokeOpacity, ol.expr.Expression); - this.strokeOpacity_ = strokeOpacity; -}; - - -/** - * Set the stroke width. - * @param {ol.expr.Expression} strokeWidth Stroke width. - */ -ol.style.Shape.prototype.setStrokeWidth = function(strokeWidth) { - goog.asserts.assertInstanceof(strokeWidth, ol.expr.Expression); - this.strokeWidth_ = strokeWidth; +ol.style.Shape.prototype.setStroke = function(stroke) { + if (!goog.isNull(stroke)) { + goog.asserts.assertInstanceof(stroke, ol.style.Stroke); + } + this.stroke_ = stroke; }; @@ -332,14 +187,10 @@ ol.style.Shape.prototype.setType = function(type) { /** - * @type {ol.style.ShapeLiteral} + * @typedef {{type: (ol.style.ShapeType), + * size: (number)}} */ -ol.style.ShapeDefaults = new ol.style.ShapeLiteral({ +ol.style.ShapeDefaults = { type: ol.style.ShapeType.CIRCLE, - size: 5, - fillColor: '#ffffff', - fillOpacity: 0.4, - strokeColor: '#696969', - strokeOpacity: 0.8, - strokeWidth: 1.5 -}); + size: 5 +}; diff --git a/src/ol/style/strokesymbolizer.js b/src/ol/style/strokesymbolizer.js new file mode 100644 index 0000000000..189bf1d1ee --- /dev/null +++ b/src/ol/style/strokesymbolizer.js @@ -0,0 +1,158 @@ +goog.provide('ol.style.Stroke'); +goog.provide('ol.style.StrokeDefaults'); + +goog.require('goog.asserts'); +goog.require('ol.geom.GeometryType'); +goog.require('ol.expr'); +goog.require('ol.expr.Expression'); +goog.require('ol.expr.Literal'); +goog.require('ol.style.LineLiteral'); +goog.require('ol.style.Symbolizer'); +goog.require('ol.style.Literal'); + + + +/** + * @constructor + * @extends {ol.style.Symbolizer} + * @param {ol.style.StrokeOptions=} opt_options Stroke options. + */ +ol.style.Stroke = function(opt_options) { + goog.base(this); + var options = opt_options || {}; + + /** + * @type {ol.expr.Expression} + * @private + */ + this.color_ = !goog.isDefAndNotNull(options.color) ? + new ol.expr.Literal(ol.style.StrokeDefaults.color) : + (options.color instanceof ol.expr.Expression) ? + options.color : new ol.expr.Literal(options.color); + + /** + * @type {ol.expr.Expression} + * @private + */ + this.opacity_ = !goog.isDefAndNotNull(options.opacity) ? + new ol.expr.Literal(ol.style.StrokeDefaults.opacity) : + (options.opacity instanceof ol.expr.Expression) ? + options.opacity : new ol.expr.Literal(options.opacity); + + /** + * @type {ol.expr.Expression} + * @private + */ + this.width_ = !goog.isDefAndNotNull(options.width) ? + new ol.expr.Literal(ol.style.StrokeDefaults.width) : + (options.width instanceof ol.expr.Expression) ? + options.width : new ol.expr.Literal(options.width); + +}; +goog.inherits(ol.style.Stroke, ol.style.Symbolizer); + + +/** + * @inheritDoc + * @return {ol.style.LineLiteral|ol.style.PolygonLiteral} Symbolizer literal. + */ +ol.style.Stroke.prototype.createLiteral = function(type, opt_feature) { + var color = ol.expr.evaluateFeature( + this.color_, opt_feature); + goog.asserts.assertString(color, 'color must be a string'); + + var opacity = ol.expr.evaluateFeature( + this.opacity_, opt_feature); + goog.asserts.assertNumber(opacity, 'opacity must be a number'); + + var width = ol.expr.evaluateFeature( + this.width_, opt_feature); + goog.asserts.assertNumber(width, 'width must be a number'); + + var literal = null; + if (type === ol.geom.GeometryType.LINESTRING || + type === ol.geom.GeometryType.MULTILINESTRING) { + literal = new ol.style.LineLiteral({ + strokeColor: color, + strokeOpacity: opacity, + strokeWidth: width + }); + } else if (type === ol.geom.GeometryType.POLYGON || + type === ol.geom.GeometryType.MULTIPOLYGON) { + literal = new ol.style.PolygonLiteral({ + strokeColor: color, + strokeOpacity: opacity, + strokeWidth: width + }); + } + return literal; +}; + + +/** + * Get the stroke color. + * @return {ol.expr.Expression} Stroke color. + */ +ol.style.Stroke.prototype.getColor = function() { + return this.color_; +}; + + +/** + * Get the stroke opacity. + * @return {ol.expr.Expression} Stroke opacity. + */ +ol.style.Stroke.prototype.getOpacity = function() { + return this.opacity_; +}; + + +/** + * Get the stroke width. + * @return {ol.expr.Expression} Stroke width. + */ +ol.style.Stroke.prototype.getWidth = function() { + return this.width_; +}; + + +/** + * Set the stroke color. + * @param {ol.expr.Expression} color Stroke color. + */ +ol.style.Stroke.prototype.setColor = function(color) { + goog.asserts.assertInstanceof(color, ol.expr.Expression); + this.color_ = color; +}; + + +/** + * Set the stroke opacity. + * @param {ol.expr.Expression} opacity Stroke opacity. + */ +ol.style.Stroke.prototype.setOpacity = function(opacity) { + goog.asserts.assertInstanceof(opacity, ol.expr.Expression); + this.opacity_ = opacity; +}; + + +/** + * Set the stroke width. + * @param {ol.expr.Expression} width Stroke width. + */ +ol.style.Stroke.prototype.setWidth = function(width) { + goog.asserts.assertInstanceof(width, ol.expr.Expression); + this.width_ = width; +}; + + +/** + * @typedef {{strokeColor: (string), + * strokeOpacity: (number), + * strokeWidth: (number)}} + */ +ol.style.StrokeDefaults = { + color: '#696969', + opacity: 0.75, + width: 1.5 +}; diff --git a/src/ol/style/style.js b/src/ol/style/style.js index c6f3e02afb..ed92d99d0b 100644 --- a/src/ol/style/style.js +++ b/src/ol/style/style.js @@ -1,10 +1,14 @@ goog.provide('ol.style.Style'); +goog.require('goog.object'); goog.require('ol.Feature'); goog.require('ol.geom.GeometryType'); -goog.require('ol.style.Rule'); +goog.require('ol.style.Fill'); goog.require('ol.style.Literal'); goog.require('ol.style.PolygonLiteral'); +goog.require('ol.style.Rule'); +goog.require('ol.style.Shape'); +goog.require('ol.style.Stroke'); @@ -31,15 +35,20 @@ ol.style.Style = function(options) { ol.style.Style.prototype.apply = function(feature) { var rules = this.rules_, literals = [], + geometry = feature.getGeometry(), rule, symbolizers; - for (var i = 0, ii = rules.length; i < ii; ++i) { - rule = rules[i]; - if (rule.applies(feature)) { - symbolizers = rule.getSymbolizers(); - for (var j = 0, jj = symbolizers.length; j < jj; ++j) { - literals.push(symbolizers[j].createLiteral(feature)); + var type = geometry ? geometry.getType() : null; + if (!goog.isNull(type)) { + for (var i = 0, ii = rules.length; i < ii; ++i) { + rule = rules[i]; + if (rule.applies(feature)) { + symbolizers = rule.getSymbolizers(); + for (var j = 0, jj = symbolizers.length; j < jj; ++j) { + literals.push(symbolizers[j].createLiteral(type, feature)); + } } } + literals = ol.style.Style.reduceLiterals_(literals); } return literals; }; @@ -51,32 +60,54 @@ ol.style.Style.prototype.apply = function(feature) { * the feature. */ ol.style.Style.applyDefaultStyle = function(feature) { - var geometry = feature.getGeometry(), - symbolizerLiterals = []; - if (!goog.isNull(geometry)) { - var type = geometry.getType(); - if (type === ol.geom.GeometryType.POINT || - type === ol.geom.GeometryType.MULTIPOINT) { - symbolizerLiterals.push(ol.style.ShapeDefaults); - } else if (type === ol.geom.GeometryType.LINESTRING || - type === ol.geom.GeometryType.MULTILINESTRING) { - symbolizerLiterals.push(ol.style.LineDefaults); - } else if (type === ol.geom.GeometryType.LINEARRING || - type === ol.geom.GeometryType.POLYGON || - type === ol.geom.GeometryType.MULTIPOLYGON) { - symbolizerLiterals.push(ol.style.PolygonDefaults); - } - } - return symbolizerLiterals; + return ol.style.Style.defaults.apply(feature); }; /** - * Collapse partial polygon symbolizers. + * The default style. + * @type {ol.style.Style} + */ +ol.style.Style.defaults = new ol.style.Style({ + rules: [ + new ol.style.Rule({ + symbolizers: [ + new ol.style.Shape({ + fill: new ol.style.Fill(), + stroke: new ol.style.Stroke() + }), + new ol.style.Fill(), + new ol.style.Stroke() + ] + }) + ] +}); + + +/** + * Given an array of symbolizers, generate an array of literals. + * @param {Array.} symbolizers List of symbolizers. + * @param {ol.geom.GeometryType} type Geometry type. + * @param {ol.Feature=} opt_feature Optional feature. + * @return {Array.} Array of literals. + */ +ol.style.Style.createLiterals = function(symbolizers, type, opt_feature) { + var length = symbolizers.length; + var literals = new Array(length); + for (var i = 0; i < length; ++i) { + literals[i] = symbolizers[i].createLiteral(type, opt_feature); + } + return ol.style.Style.reduceLiterals_(literals); +} + + +/** + * Collapse partial polygon symbolizers and remove null symbolizers. * @param {Array.} literals Input literals. * @return {Array.} Reduced literals. + * @private */ -ol.style.Style.reduceLiterals = function(literals) { +ol.style.Style.reduceLiterals_ = function(literals) { var reduced = []; var literal, stroke, fill, key, value; for (var i = 0, ii = literals.length; i < ii; ++i) { @@ -116,7 +147,7 @@ ol.style.Style.reduceLiterals = function(literals) { // both stroke and fill, proceed reduced.push(literal); } - } else { + } else if (literal) { reduced.push(literal); } } diff --git a/src/ol/style/symbolizer.js b/src/ol/style/symbolizer.js index d599dbb2c2..f96cf4f083 100644 --- a/src/ol/style/symbolizer.js +++ b/src/ol/style/symbolizer.js @@ -12,6 +12,7 @@ ol.style.Symbolizer = function() {}; /** + * @param {ol.geom.GeometryType} type Geometry type. * @param {ol.Feature=} opt_feature Feature for evaluating expressions. * @return {ol.style.Literal} Literal symbolizer. */ diff --git a/src/ol/style/textsymbolizer.js b/src/ol/style/textsymbolizer.js index 68cea7c2b2..1919488920 100644 --- a/src/ol/style/textsymbolizer.js +++ b/src/ol/style/textsymbolizer.js @@ -67,7 +67,7 @@ goog.inherits(ol.style.Text, ol.style.Symbolizer); * @inheritDoc * @return {ol.style.TextLiteral} Literal text symbolizer. */ -ol.style.Text.prototype.createLiteral = function(opt_feature) { +ol.style.Text.prototype.createLiteral = function(type, opt_feature) { var color = ol.expr.evaluateFeature(this.color_, opt_feature); goog.asserts.assertString(color, 'color must be a string'); @@ -190,12 +190,14 @@ ol.style.Text.prototype.setText = function(text) { /** - * @type {ol.style.TextLiteral} + * @typedef {{color: string, + * fontFamily: string, + * fontSize: number, + * opacity: number}} */ -ol.style.TextDefaults = new ol.style.TextLiteral({ +ol.style.TextDefaults = { color: '#000', fontFamily: 'sans-serif', fontSize: 10, - text: '', opacity: 1 -}); +}; diff --git a/test/spec/ol/layer/vectorlayer.test.js b/test/spec/ol/layer/vectorlayer.test.js index 8c6c9f06e1..7e4075dce0 100644 --- a/test/spec/ol/layer/vectorlayer.test.js +++ b/test/spec/ol/layer/vectorlayer.test.js @@ -106,9 +106,9 @@ describe('ol.layer.Vector', function() { rules: [ new ol.style.Rule({ symbolizers: [ - new ol.style.Line({ - strokeWidth: 2, - strokeColor: ol.expr.parse('colorProperty'), + new ol.style.Stroke({ + width: 2, + color: ol.expr.parse('colorProperty'), opacity: 1 }) ] @@ -143,14 +143,14 @@ describe('ol.layer.Vector', function() { }); it('groups equal symbolizers also when defined on features', function() { - var symbolizer = new ol.style.Line({ - strokeWidth: 3, - strokeColor: ol.expr.parse('colorProperty'), + var symbolizer = new ol.style.Stroke({ + width: 3, + color: ol.expr.parse('colorProperty'), opacity: 1 }); - var anotherSymbolizer = new ol.style.Line({ - strokeWidth: 3, - strokeColor: '#BADA55', + var anotherSymbolizer = new ol.style.Stroke({ + width: 3, + color: '#BADA55', opacity: 1 }); var featureWithSymbolizers = new ol.Feature({ @@ -165,7 +165,7 @@ describe('ol.layer.Vector', function() { features.push(featureWithSymbolizers, anotherFeatureWithSymbolizers); var groups = layer.groupFeaturesBySymbolizerLiteral(features); - expect(groups.length).to.be(3); + expect(groups).to.have.length(3); expect(groups[2][0].length).to.be(2); expect(groups[2][1].strokeWidth).to.be(3); @@ -188,6 +188,6 @@ goog.require('ol.geom.Point'); goog.require('ol.proj'); goog.require('ol.layer.Vector'); goog.require('ol.source.Vector'); -goog.require('ol.style.Line'); goog.require('ol.style.Rule'); +goog.require('ol.style.Stroke'); goog.require('ol.style.Style'); diff --git a/test/spec/ol/parser/kml.test.js b/test/spec/ol/parser/kml.test.js index 694e222a86..a43ce97119 100644 --- a/test/spec/ol/parser/kml.test.js +++ b/test/spec/ol/parser/kml.test.js @@ -1,6 +1,6 @@ -goog.provide('ol.test.parser.kml'); +goog.provide('ol.test.parser.KML'); -describe('ol.parser.kml', function() { +describe('ol.parser.KML', function() { var parser = new ol.parser.KML(); @@ -165,8 +165,9 @@ describe('ol.parser.kml', function() { expect(obj.features[0].get('description')).to.eql('Full of text.'); expect(obj.features[0].get('name')).to.eql('Pezinok'); }); - it('Test line style (read / write)', function() { - var test_style = ' ' + @@ -175,16 +176,24 @@ describe('ol.parser.kml', function() { ' -112,36 -113,37 ' + ''; var p = new ol.parser.KML({extractStyles: true}); - var obj = p.read(test_style); + var obj = p.read(kml); var output = p.write(obj); - expect(goog.dom.xml.loadXml(test_style)).to.xmleql( + expect(goog.dom.xml.loadXml(kml)).to.xmleql( goog.dom.xml.loadXml(output)); - var symbolizer = obj.features[0].getSymbolizerLiterals()[0]; - expect(symbolizer instanceof ol.style.LineLiteral).to.be.ok(); - expect(symbolizer.strokeColor).to.eql('#ff0000'); - expect(symbolizer.strokeOpacity).to.eql(0.5294117647058824); - expect(symbolizer.strokeWidth).to.eql(10); + + var symbolizers = obj.features[0].getSymbolizers(); + expect(symbolizers).to.have.length(1); + + var stroke = symbolizers[0]; + expect(stroke).to.be.a(ol.style.Stroke); + + var literal = stroke.createLiteral(ol.geom.GeometryType.LINESTRING); + expect(literal).to.be.a(ol.style.LineLiteral); + expect(literal.strokeColor).to.eql('#ff0000'); + expect(literal.strokeOpacity).to.eql(0.5294117647058824); + expect(literal.strokeWidth).to.eql(10); }); + it('reads PolyStyle fill', function() { var kml = '' + '