diff --git a/examples/tasmania/sld-tasmania.xml b/examples/tasmania/sld-tasmania.xml index 1ffba6ec03..0b174f0616 100644 --- a/examples/tasmania/sld-tasmania.xml +++ b/examples/tasmania/sld-tasmania.xml @@ -581,6 +581,9 @@ 1 + + 3 5 1 5 + diff --git a/examples/vector-features.html b/examples/vector-features.html index bcde5e5b45..2b85694125 100644 --- a/examples/vector-features.html +++ b/examples/vector-features.html @@ -38,6 +38,7 @@ var style_green = { strokeColor: "#00FF00", strokeWidth: 3, + strokeDashstyle: "dashdot", pointRadius: 6, pointerEvents: "visiblePainted" }; @@ -74,7 +75,7 @@ // create a line feature from a list of points var pointList = []; var newPoint = point; - for(var p=0; p<5; ++p) { + for(var p=0; p<15; ++p) { newPoint = new OpenLayers.Geometry.Point(newPoint.x + Math.random(1), newPoint.y + Math.random(1)); pointList.push(newPoint); diff --git a/lib/OpenLayers/Feature/Vector.js b/lib/OpenLayers/Feature/Vector.js index 338fce6ec8..67efab8f64 100644 --- a/lib/OpenLayers/Feature/Vector.js +++ b/lib/OpenLayers/Feature/Vector.js @@ -308,7 +308,8 @@ OpenLayers.Feature.Vector = OpenLayers.Class(OpenLayers.Feature, { * - strokeColor: "#ee9900", * - strokeOpacity: 1, * - strokeWidth: 1, - * - strokeLinecap: "round", + * - strokeLinecap: "round", [butt | round | square] + * - strokeDashstyle: "solid", [dot | dash | dashdot | longdash | longdashdot | solid] * - hoverStrokeColor: "red", * - hoverStrokeOpacity: 1, * - hoverStrokeWidth: 0.2, @@ -339,6 +340,7 @@ OpenLayers.Feature.Vector.style = { strokeOpacity: 1, strokeWidth: 1, strokeLinecap: "round", + strokeDashstyle: "solid", hoverStrokeColor: "red", hoverStrokeOpacity: 1, hoverStrokeWidth: 0.2, @@ -357,6 +359,7 @@ OpenLayers.Feature.Vector.style = { strokeOpacity: 1, strokeWidth: 2, strokeLinecap: "round", + strokeDashstyle: "solid", hoverStrokeColor: "red", hoverStrokeOpacity: 1, hoverStrokeWidth: 0.2, @@ -375,6 +378,7 @@ OpenLayers.Feature.Vector.style = { strokeOpacity: 1, strokeLinecap: "round", strokeWidth: 4, + strokeDashstyle: "solid", hoverStrokeColor: "red", hoverStrokeOpacity: 1, hoverStrokeWidth: 0.2, diff --git a/lib/OpenLayers/Format/SLD/v1.js b/lib/OpenLayers/Format/SLD/v1.js index eda406f1a3..c9c31f18bd 100644 --- a/lib/OpenLayers/Format/SLD/v1.js +++ b/lib/OpenLayers/Format/SLD/v1.js @@ -52,6 +52,7 @@ OpenLayers.Format.SLD.v1 = OpenLayers.Class(OpenLayers.Format.XML, { strokeColor: "#000000", strokeOpacity: 1, strokeWidth: 1, + strokeDashstyle: "solid", pointRadius: 3, graphicName: "square" }, @@ -293,6 +294,7 @@ OpenLayers.Format.SLD.v1 = OpenLayers.Class(OpenLayers.Format.XML, { "stroke-opacity": "strokeOpacity", "stroke-width": "strokeWidth", "stroke-linecap": "strokeLinecap", + "stroke-dasharray": "strokeDashstyle", "fill": "fillColor", "fill-opacity": "fillOpacity", "font-family": "fontFamily", diff --git a/lib/OpenLayers/Renderer/Elements.js b/lib/OpenLayers/Renderer/Elements.js index 09dc7cea2e..61b27f4e52 100644 --- a/lib/OpenLayers/Renderer/Elements.js +++ b/lib/OpenLayers/Renderer/Elements.js @@ -347,6 +347,7 @@ OpenLayers.Renderer.Elements = OpenLayers.Class(OpenLayers.Renderer, { minimumSymbolizer: { strokeLinecap: "round", strokeOpacity: 1, + strokeDashstyle: "solid", fillOpacity: 1, pointRadius: 0 }, diff --git a/lib/OpenLayers/Renderer/SVG.js b/lib/OpenLayers/Renderer/SVG.js index e378716a6c..0651922db7 100644 --- a/lib/OpenLayers/Renderer/SVG.js +++ b/lib/OpenLayers/Renderer/SVG.js @@ -286,6 +286,11 @@ OpenLayers.Renderer.SVG = OpenLayers.Class(OpenLayers.Renderer.Elements, { node.setAttributeNS(null, "stroke-opacity", style.strokeOpacity); node.setAttributeNS(null, "stroke-width", style.strokeWidth * widthFactor); node.setAttributeNS(null, "stroke-linecap", style.strokeLinecap); + // Hard-coded linejoin for now, to make it look the same as in VML. + // There is no strokeLinejoin property yet for symbolizers. + node.setAttributeNS(null, "stroke-linejoin", "round"); + node.setAttributeNS(null, "stroke-dasharray", this.dashStyle(style, + widthFactor)); } else { node.setAttributeNS(null, "stroke", "none"); } @@ -300,6 +305,37 @@ OpenLayers.Renderer.SVG = OpenLayers.Class(OpenLayers.Renderer.Elements, { return node; }, + /** + * Method: dashStyle + * + * Parameters: + * style - {Object} + * widthFactor - {Number} + * + * Returns: + * {String} A SVG compliant 'stroke-dasharray' value + */ + dashStyle: function(style, widthFactor) { + var w = style.strokeWidth * widthFactor; + + switch (style.strokeDashstyle) { + case 'solid': + return 'none'; + case 'dot': + return [1, 4 * w].join(); + case 'dash': + return [4 * w, 4 * w].join(); + case 'dashdot': + return [4 * w, 4 * w, 1, 4 * w].join(); + case 'longdash': + return [8 * w, 4 * w].join(); + case 'longdashdot': + return [8 * w, 4 * w, 1, 4 * w].join(); + default: + return style.strokeDashstyle.replace(/ /g, ","); + } + }, + /** * Method: createNode * @@ -632,9 +668,6 @@ OpenLayers.Renderer.SVG = OpenLayers.Class(OpenLayers.Renderer.Elements, { } node.setAttributeNS(null, "points", points); - // Hard-coded linejoin for now, to make it look the same as in VML. - // There is no strokeLinejoin property yet for symbolizers. - node.setAttributeNS(null, "stroke-linejoin", "round"); var width = symbolExtent.getWidth(); var height = symbolExtent.getHeight(); diff --git a/lib/OpenLayers/Renderer/VML.js b/lib/OpenLayers/Renderer/VML.js index 0cdd9ac0cd..16e653055e 100644 --- a/lib/OpenLayers/Renderer/VML.js +++ b/lib/OpenLayers/Renderer/VML.js @@ -286,6 +286,7 @@ OpenLayers.Renderer.VML = OpenLayers.Class(OpenLayers.Renderer.Elements, { } stroke.setAttribute("opacity", style.strokeOpacity); stroke.setAttribute("endcap", !style.strokeLinecap || style.strokeLinecap == 'butt' ? 'flat' : style.strokeLinecap); + stroke.setAttribute("dashstyle", this.dashStyle(style)); } if (style.cursor != "inherit" && style.cursor != null) { @@ -455,6 +456,41 @@ OpenLayers.Renderer.VML = OpenLayers.Class(OpenLayers.Renderer.Elements, { node.coordsize = scaledBox.getWidth()+ " " + scaledBox.getHeight(); } }, + + /** + * Method: dashStyle + * + * Parameters: + * style - {Object} + * + * Returns: + * {String} A VML compliant 'stroke-dasharray' value + */ + dashStyle: function(style) { + var dash = style.strokeDashstyle; + switch (dash) { + case 'solid': + case 'dot': + case 'dash': + case 'dashdot': + case 'longdash': + case 'longdashdot': + return dash; + default: + // very basic guessing of dash style patterns + var parts = dash.split(/[ ,]/); + if (parts.length == 2) { + if (1*parts[0] >= 2*parts[1]) { + return "longdash"; + } + return (parts[0] == 1 || parts[1] == 1) ? "dot" : "dash"; + } else if (parts.length == 4) { + return (1*parts[0] >= 2*parts[1]) ? "longdashdot" : + "dashdot" + } + return "solid"; + } + }, /** * Method: createNode diff --git a/tests/Renderer/SVG.html b/tests/Renderer/SVG.html index ff3711abd8..a0e4162be9 100644 --- a/tests/Renderer/SVG.html +++ b/tests/Renderer/SVG.html @@ -407,6 +407,23 @@ t.ok(r.symbolSize["-square"], "Symbol size cached correctly."); } + function test_svg_dashstyle(t) { + if (!OpenLayers.Renderer.SVG.prototype.supported()) { + t.plan(0); + return; + } + + t.plan(5); + + var r = new OpenLayers.Renderer.SVG(document.body); + + t.eq(r.dashStyle({strokeWidth: 1, strokeDashstyle: "dot"}, 1), "1,4", "dot dasharray created correctly"); + t.eq(r.dashStyle({strokeWidth: 1, strokeDashstyle: "dash"}, 1), "4,4", "dash dasharray created correctly"); + t.eq(r.dashStyle({strokeWidth: 1, strokeDashstyle: "longdash"}, 1), "8,4", "longdash dasharray created correctly"); + t.eq(r.dashStyle({strokeWidth: 1, strokeDashstyle: "dashdot"}, 1), "4,4,1,4", "dashdot dasharray created correctly"); + t.eq(r.dashStyle({strokeWidth: 1, strokeDashstyle: "longdashdot"}, 1), "8,4,1,4", "dashdot dasharray created correctly"); + } + diff --git a/tests/Renderer/VML.html b/tests/Renderer/VML.html index 173bb43b57..98c3a22649 100644 --- a/tests/Renderer/VML.html +++ b/tests/Renderer/VML.html @@ -370,6 +370,23 @@ t.ok(r.symbolCache["-square"], "Symbol has been cached correctly."); } + + function test_vml_dashstyle(t) { + if (!OpenLayers.Renderer.VML.prototype.supported()) { + t.plan(0); + return; + } + + t.plan(5); + + var r = new OpenLayers.Renderer.VML(document.body); + + t.eq(r.dashStyle({strokeDashstyle: "1 4"}), "dot", "dot pattern recognized correctly."); + t.eq(r.dashStyle({strokeDashstyle: "4 4"}), "dash", "dash pattern recognized correctly."); + t.eq(r.dashStyle({strokeDashstyle: "8 4"}), "longdash", "longdash pattern recognized correctly."); + t.eq(r.dashStyle({strokeDashstyle: "4 4 1 4"}), "dashdot", "dashdot pattern recognized correctly."); + t.eq(r.dashStyle({strokeDashstyle: "8 4 1 4"}), "longdashdot", "longdashdot pattern recognized correctly."); + }