[OpenLayers-Commits] r11838 - in trunk/openlayers: examples lib/OpenLayers/Renderer

commits-20090109 at openlayers.org commits-20090109 at openlayers.org
Thu Mar 31 07:58:33 EDT 2011


Author: ahocevar
Date: 2011-03-31 04:58:28 -0700 (Thu, 31 Mar 2011)
New Revision: 11838

Modified:
   trunk/openlayers/examples/vector-features-with-text.html
   trunk/openlayers/lib/OpenLayers/Renderer/Canvas.js
   trunk/openlayers/lib/OpenLayers/Renderer/SVG.js
   trunk/openlayers/lib/OpenLayers/Renderer/SVG2.js
Log:
adding support for line breaks to SVG, SVG2 and Canvas renderers. Also adds vertical alignment support to Canvas. p=vog,fredj,me r=me (closes #2193)

Modified: trunk/openlayers/examples/vector-features-with-text.html
===================================================================
--- trunk/openlayers/examples/vector-features-with-text.html	2011-03-31 11:53:46 UTC (rev 11837)
+++ trunk/openlayers/examples/vector-features-with-text.html	2011-03-31 11:58:28 UTC (rev 11838)
@@ -29,7 +29,8 @@
                     fillOpacity: 0.5,
                     pointRadius: 6,
                     pointerEvents: "visiblePainted",
-                    label : "name: ${name}, age: ${age}",
+                    // label with \n linebreaks
+                    label : "name: ${name}\n\nage: ${age}",
                     
                     fontColor: "${favColor}",
                     fontSize: "12px",
@@ -113,7 +114,7 @@
             
             map.addLayer(vectorLayer);
             vectorLayer.drawFeature(multiFeature);
-            map.setCenter(new OpenLayers.LonLat(point.x, point.y), 3);
+            map.setCenter(new OpenLayers.LonLat(-109.370078125, 43.39484375), 4);
             vectorLayer.addFeatures([pointFeature, polygonFeature, multiFeature, labelOffsetFeature, nullFeature ]);
         }
     </script>

Modified: trunk/openlayers/lib/OpenLayers/Renderer/Canvas.js
===================================================================
--- trunk/openlayers/lib/OpenLayers/Renderer/Canvas.js	2011-03-31 11:53:46 UTC (rev 11837)
+++ trunk/openlayers/lib/OpenLayers/Renderer/Canvas.js	2011-03-31 11:58:28 UTC (rev 11838)
@@ -9,7 +9,7 @@
 
 /**
  * Class: OpenLayers.Renderer.Canvas 
- * A renderer based on the 2D 'canvas' drawing element.element
+ * A renderer based on the 2D 'canvas' drawing element.
  * 
  * Inherits:
  *  - <OpenLayers.Renderer>
@@ -329,42 +329,61 @@
             labelAlign: "cm"
         }, style);
         var pt = this.getLocalXY(location);
-        
+
         this.setCanvasStyle("reset");
         this.canvas.fillStyle = style.fontColor;
         this.canvas.globalAlpha = style.fontOpacity || 1.0;
         var fontStyle = [style.fontStyle ? style.fontStyle : "normal",
                          "normal", // "font-variant" not supported
                          style.fontWeight ? style.fontWeight : "normal",
-                         style.fontSize ? style.fontSize : "10px",
+                         style.fontSize ? style.fontSize : "1em",
                          style.fontFamily ? style.fontFamily : "sans-serif"].join(" ");
+        var labelRows = style.label.split('\n');
+        var numRows = labelRows.length;
         if (this.canvas.fillText) {
             // HTML5
-            var labelAlign =
+            this.canvas.font = fontStyle;
+            this.canvas.textAlign =
                 OpenLayers.Renderer.Canvas.LABEL_ALIGN[style.labelAlign[0]] ||
                 "center";
-            this.canvas.font = fontStyle;
-            this.canvas.textAlign = labelAlign;
-            this.canvas.fillText(style.label, pt[0], pt[1]);
+            this.canvas.textBaseline =
+                OpenLayers.Renderer.Canvas.LABEL_ALIGN[style.labelAlign[1]] ||
+                "middle";
+            var vfactor =
+                OpenLayers.Renderer.Canvas.LABEL_FACTOR[style.labelAlign[1]];
+            if (vfactor == null) {
+                vfactor = -.5;
+            }
+            var lineHeight =
+                this.canvas.measureText('Mg').height ||
+                this.canvas.measureText('xx').width;
+            pt[1] += lineHeight*vfactor*(numRows-1);
+            for (var i = 0; i < numRows; i++) {
+                this.canvas.fillText(labelRows[i], pt[0], pt[1] + (lineHeight*i));
+            }
         } else if (this.canvas.mozDrawText) {
             // Mozilla pre-Gecko1.9.1 (<FF3.1)
             this.canvas.mozTextStyle = fontStyle;
             // No built-in text alignment, so we measure and adjust the position
-            var len = this.canvas.mozMeasureText(style.label);
-            switch(style.labelAlign[0]) {
-                case "l":
-                    break;
-                case "r":
-                    pt[0] -= len;
-                    break;
-                case "c":
-                default:
-                    pt[0] -= len / 2;
+            var hfactor =
+                OpenLayers.Renderer.Canvas.LABEL_FACTOR[style.labelAlign[0]];
+            if (hfactor == null) {
+                hfactor = -.5;
             }
-            this.canvas.translate(pt[0], pt[1]);
-            
-            this.canvas.mozDrawText(style.label);
-            this.canvas.translate(-1*pt[0], -1*pt[1]);
+            var vfactor =
+                OpenLayers.Renderer.Canvas.LABEL_FACTOR[style.labelAlign[1]];
+            if (vfactor == null) {
+                vfactor = -.5;
+            }
+            var lineHeight = this.canvas.mozMeasureText('xx');
+            pt[1] += lineHeight*(1 + (vfactor*numRows));
+            for (var i = 0; i < numRows; i++) {
+                var x = pt[0] + (hfactor*this.canvas.mozMeasureText(labelRows[i]));
+                var y = pt[1] + (i*lineHeight);
+                this.canvas.translate(x, y);
+                this.canvas.mozDrawText(labelRows[i]);
+                this.canvas.translate(-x, -y);
+            }
         }
         this.setCanvasStyle("reset");
     },
@@ -478,5 +497,18 @@
  */
 OpenLayers.Renderer.Canvas.LABEL_ALIGN = {
     "l": "left",
-    "r": "right"
+    "r": "right",
+    "t": "top",
+    "b": "bottom"
 };
+
+/**
+ * Constant: OpenLayers.Renderer.Canvas.LABEL_FACTOR
+ * {Object}
+ */
+OpenLayers.Renderer.Canvas.LABEL_FACTOR = {
+    "l": 0,
+    "r": -1,
+    "t": 0,
+    "b": -1
+};

Modified: trunk/openlayers/lib/OpenLayers/Renderer/SVG.js
===================================================================
--- trunk/openlayers/lib/OpenLayers/Renderer/SVG.js	2011-03-31 11:53:46 UTC (rev 11837)
+++ trunk/openlayers/lib/OpenLayers/Renderer/SVG.js	2011-03-31 11:58:28 UTC (rev 11838)
@@ -679,24 +679,23 @@
     /**
      * Method: drawText
      * This method is only called by the renderer itself.
-     * 
-     * Parameters: 
+     *
+     * Parameters:
      * featureId - {String}
      * style -
      * location - {<OpenLayers.Geometry.Point>}
      */
     drawText: function(featureId, style, location) {
         var resolution = this.getResolution();
-        
+
         var x = (location.x / resolution + this.left);
         var y = (location.y / resolution - this.top);
-        
+
         var label = this.nodeFactory(featureId + this.LABEL_ID_SUFFIX, "text");
-        var tspan = this.nodeFactory(featureId + this.LABEL_ID_SUFFIX + "_tspan", "tspan");
 
         label.setAttributeNS(null, "x", x);
         label.setAttributeNS(null, "y", -y);
-        
+
         if (style.fontColor) {
             label.setAttributeNS(null, "fill", style.fontColor);
         }
@@ -715,12 +714,9 @@
         if (style.fontStyle) {
             label.setAttributeNS(null, "font-style", style.fontStyle);
         }
-        if(style.labelSelect === true) {
+        if (style.labelSelect === true) {
             label.setAttributeNS(null, "pointer-events", "visible");
             label._featureId = featureId;
-            tspan._featureId = featureId;
-            tspan._geometry = location;
-            tspan._geometryClass = location.CLASS_NAME;
         } else {
             label.setAttributeNS(null, "pointer-events", "none");
         }
@@ -731,17 +727,43 @@
         if (OpenLayers.IS_GECKO === true) {
             label.setAttributeNS(null, "dominant-baseline",
                 OpenLayers.Renderer.SVG.LABEL_ALIGN[align[1]] || "central");
-        } else {
-            tspan.setAttributeNS(null, "baseline-shift",
-                OpenLayers.Renderer.SVG.LABEL_VSHIFT[align[1]] || "-35%");
         }
 
-        tspan.textContent = style.label;
-        
-        if(!label.parentNode) {
-            label.appendChild(tspan);
+        var labelRows = style.label.split('\n');
+        var numRows = labelRows.length;
+        while (label.childNodes.length > numRows) {
+            label.removeChild(label.lastChild);
+        }
+        for (var i = 0; i < numRows; i++) {
+            var tspan = this.nodeFactory(featureId + this.LABEL_ID_SUFFIX + "_tspan_" + i, "tspan");
+            if (style.labelSelect === true) {
+                tspan._featureId = featureId;
+                tspan._geometry = location;
+                tspan._geometryClass = location.CLASS_NAME;
+            }
+            if (OpenLayers.IS_GECKO === false) {
+                tspan.setAttributeNS(null, "baseline-shift",
+                    OpenLayers.Renderer.SVG.LABEL_VSHIFT[align[1]] || "-35%");
+            }
+            tspan.setAttribute("x", x);
+            if (i == 0) {
+                var vfactor = OpenLayers.Renderer.SVG.LABEL_VFACTOR[align[1]];
+                if (vfactor == null) {
+                     vfactor = -.5;
+                }
+                tspan.setAttribute("dy", (vfactor*(numRows-1)) + "em");
+            } else {
+                tspan.setAttribute("dy", "1em");
+            }
+            tspan.textContent = (labelRows[i] === '') ? ' ' : labelRows[i];
+            if (!tspan.parentNode) {
+                label.appendChild(tspan);
+            }
+        }
+
+        if (!label.parentNode) {
             this.textRoot.appendChild(label);
-        }   
+        }
     },
     
     /** 
@@ -989,6 +1011,15 @@
 };
 
 /**
+ * Constant: OpenLayers.Renderer.SVG.LABEL_VFACTOR
+ * {Object}
+ */
+OpenLayers.Renderer.SVG.LABEL_VFACTOR = {
+    "t": 0,
+    "b": -1
+};
+
+/**
  * Function: OpenLayers.Renderer.SVG.preventDefault
  * Used to prevent default events (especially opening images in a new tab on
  * ctrl-click) from being executed for externalGraphic symbols

Modified: trunk/openlayers/lib/OpenLayers/Renderer/SVG2.js
===================================================================
--- trunk/openlayers/lib/OpenLayers/Renderer/SVG2.js	2011-03-31 11:53:46 UTC (rev 11837)
+++ trunk/openlayers/lib/OpenLayers/Renderer/SVG2.js	2011-03-31 11:58:28 UTC (rev 11838)
@@ -570,8 +570,8 @@
      * Method: drawText
      * Function for drawing text labels.
      * This method is only called by the renderer itself.
-     * 
-     * Parameters: 
+     *
+     * Parameters:
      * featureId - {String|DOMElement}
      * style - {Object}
      * location - {<OpenLayers.Geometry.Point>}, will be modified inline
@@ -583,14 +583,12 @@
         var g = OpenLayers.Renderer.NG.prototype.drawText.apply(this, arguments);
         var text = g.firstChild ||
             this.nodeFactory(featureId + this.LABEL_ID_SUFFIX + "_text", "text");
-        var tspan = text.firstChild ||
-            this.nodeFactory(featureId + this.LABEL_ID_SUFFIX + "_tspan", "tspan");
 
         var res = this.getResolution();
         text.setAttributeNS(null, "x", location.x / res);
         text.setAttributeNS(null, "y", - location.y / res);
         g.setAttributeNS(null, "transform", "scale(" + res + ")");
-        
+
         if (style.fontColor) {
             text.setAttributeNS(null, "fill", style.fontColor);
         }
@@ -609,10 +607,9 @@
         if (style.fontStyle) {
             text.setAttributeNS(null, "font-style", style.fontStyle);
         }
-        if(style.labelSelect === true) {
+        if (style.labelSelect === true) {
             text.setAttributeNS(null, "pointer-events", "visible");
             text._featureId = featureId;
-            tspan._featureId = featureId;
         } else {
             text.setAttributeNS(null, "pointer-events", "none");
         }
@@ -623,18 +620,43 @@
         if (OpenLayers.IS_GECKO === true) {
             text.setAttributeNS(null, "dominant-baseline",
                 OpenLayers.Renderer.SVG2.LABEL_ALIGN[align[1]] || "central");
-        } else {
-            tspan.setAttributeNS(null, "baseline-shift",
-                OpenLayers.Renderer.SVG2.LABEL_VSHIFT[align[1]] || "-35%");
         }
 
-        tspan.textContent = style.label;
-        
-        if(!text.parentNode) {
-            text.appendChild(tspan);
+        var labelRows = style.label.split('\n');
+        var numRows = labelRows.length;
+        while (text.childNodes.length > numRows) {
+            text.removeChild(text.lastChild);
+        }
+        for (var i = 0; i < numRows; i++) {
+            var tspan = text.childNodes[i] ||
+                this.nodeFactory(featureId + this.LABEL_ID_SUFFIX + "_tspan_" + i, "tspan");
+            if (style.labelSelect === true) {
+                tspan._featureId = featureId;
+            }
+            if (OpenLayers.IS_GECKO === false) {
+                tspan.setAttributeNS(null, "baseline-shift",
+                    OpenLayers.Renderer.SVG2.LABEL_VSHIFT[align[1]] || "-35%");
+            }
+            tspan.setAttribute("x", location.x / res);
+            if (i == 0) {
+                var vfactor = OpenLayers.Renderer.SVG2.LABEL_VFACTOR[align[1]];
+                if (vfactor == null) {
+                    vfactor = -.5;
+                }
+                tspan.setAttribute("dy", (vfactor*(numRows-1)) + "em");
+            } else {
+                tspan.setAttribute("dy", "1em");
+            }
+            tspan.textContent = (labelRows[i] === '') ? ' ' : labelRows[i];
+            if (!tspan.parentNode) {
+                text.appendChild(tspan);
+            }
+        }
+
+        if (!text.parentNode) {
             g.appendChild(text);
         }
-        
+
         return g;
     },
     
@@ -786,6 +808,15 @@
     "b": "0"    
 };
 
+/**
+ * Constant: OpenLayers.Renderer.SVG2.LABEL_VFACTOR
+ * {Object}
+ */
+OpenLayers.Renderer.SVG2.LABEL_VFACTOR = {
+    "t": 0,
+    "b": -1
+};
+
 /** 
  * Function: OpenLayers.Renderer.SVG2.preventDefault 
  * Used to prevent default events (especially opening images in a new tab on 



More information about the Commits mailing list