Changeset 7634
- Timestamp:
- 07/31/08 13:02:10 (4 months ago)
- Files:
-
- trunk/openlayers/examples/graphic-name.html (added)
- trunk/openlayers/examples/tasmania/TasmaniaCities.xml (modified) (1 diff)
- trunk/openlayers/examples/tasmania/sld-tasmania.xml (modified) (2 diffs)
- trunk/openlayers/examples/vector-features.html (modified) (1 diff)
- trunk/openlayers/lib/OpenLayers/Feature/Vector.js (modified) (1 diff)
- trunk/openlayers/lib/OpenLayers/Format/SLD/v1.js (modified) (1 diff)
- trunk/openlayers/lib/OpenLayers/Renderer/Elements.js (modified) (1 diff)
- trunk/openlayers/lib/OpenLayers/Renderer/SVG.js (modified) (8 diffs)
- trunk/openlayers/lib/OpenLayers/Renderer/VML.js (modified) (7 diffs)
- trunk/openlayers/tests/Renderer/SVG.html (modified) (1 diff)
- trunk/openlayers/tests/Renderer/VML.html (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/openlayers/examples/tasmania/TasmaniaCities.xml
r5520 r7634 24 24 </topp:tasmania_cities> 25 25 </gml:featureMember> 26 <gml:featureMember> 27 <topp:tasmania_cities fid="tasmania_cities.2"> 28 <topp:the_geom> 29 <gml:MultiPoint srsName="http://www.opengis.net/gml/srs/epsg.xml#4326"> 30 <gml:pointMember> 31 <gml:Point> 32 <gml:coordinates xmlns:gml="http://www.opengis.net/gml" decimal="." cs="," ts=" ">147,-41.1</gml:coordinates> 33 </gml:Point> 34 </gml:pointMember> 35 </gml:MultiPoint> 36 </topp:the_geom> 37 <topp:CNTRY_NAME>Australia</topp:CNTRY_NAME> 38 </topp:tasmania_cities> 39 </gml:featureMember> 26 40 </wfs:FeatureCollection> trunk/openlayers/examples/tasmania/sld-tasmania.xml
r6645 r7634 529 529 <sld:FeatureTypeStyle> 530 530 <sld:Rule> 531 <ogc:Filter> 532 <ogc:FeatureId fid="tasmania_cities.1"/> 533 </ogc:Filter> 531 534 <sld:PointSymbolizer> 532 535 <sld:Graphic> … … 535 538 <sld:Format>image/png</sld:Format> 536 539 </sld:ExternalGraphic> 537 <sld:Opacity>0.5</sld:Opacity> 540 <sld:Opacity>0.7</sld:Opacity> 541 <sld:Size>14</sld:Size> 542 </sld:Graphic> 543 </sld:PointSymbolizer> 544 </sld:Rule> 545 <sld:Rule> 546 <sld:ElseFilter/> 547 <sld:PointSymbolizer> 548 <sld:Graphic> 549 <sld:Mark> 550 <sld:WellKnownName>cross</sld:WellKnownName> 551 </sld:Mark> 538 552 <sld:Size>10</sld:Size> 539 553 </sld:Graphic> trunk/openlayers/examples/vector-features.html
r7534 r7634 27 27 style_blue.strokeColor = "blue"; 28 28 style_blue.fillColor = "blue"; 29 style_blue.graphicName = "star"; 30 style_blue.pointRadius = 10; 31 style_blue.strokeWidth = 3; 32 style_blue.rotation = 45; 33 style_blue.strokeLinecap = "butt"; 29 34 30 35 /* trunk/openlayers/lib/OpenLayers/Feature/Vector.js
r7593 r7634 324 324 * - graphicWidth, 325 325 * - graphicHeight, 326 * - graphicOpacity 327 * - graphicXOffset 328 * - graphicYOffset 326 * - graphicOpacity, 327 * - graphicXOffset, 328 * - graphicYOffset, 329 * - graphicName, 329 330 * - display 330 331 */ trunk/openlayers/lib/OpenLayers/Format/SLD/v1.js
r7627 r7634 53 53 strokeOpacity: 1, 54 54 strokeWidth: 1, 55 pointRadius: 6 55 pointRadius: 3, 56 graphicName: "square" 56 57 }, 57 58 trunk/openlayers/lib/OpenLayers/Renderer/Elements.js
r7627 r7634 372 372 return node; 373 373 }, 374 374 375 /** 376 * Method: isComplexSymbol 377 * Determines if a symbol cannot be rendered using drawCircle 378 * 379 * Parameters: 380 * graphicName - {String} 381 * 382 * Returns 383 * {Boolean} true if the symbol is complex, false if not 384 */ 385 isComplexSymbol: function(graphicName) { 386 return (graphicName != "circle") && !!graphicName; 387 }, 388 375 389 CLASS_NAME: "OpenLayers.Renderer.Elements" 376 390 }); 391 392 393 /** 394 * Constant: OpenLayers.Renderer.symbol 395 * Coordinate arrays for well known (named) symbols. 396 */ 397 OpenLayers.Renderer.symbol = { 398 "star": [350,75, 379,161, 469,161, 397,215, 423,301, 350,250, 277,301, 399 303,215, 231,161, 321,161, 350,75], 400 "cross": [4,0, 6,0, 6,4, 10,4, 10,6, 6,6, 6,10, 4,10, 4,6, 0,6, 0,4, 4,4, 401 4,0], 402 "x": [0,0, 25,0, 50,35, 75,0, 100,0, 65,50, 100,100, 75,100, 50,65, 25,100, 0,100, 35,50, 0,0], 403 "square": [0,0, 0,1, 1,1, 1,0, 0,0], 404 "triangle": [0,10, 10,10, 5,0, 0,10] 405 } trunk/openlayers/lib/OpenLayers/Renderer/SVG.js
r7627 r7634 20 20 */ 21 21 xmlns: "http://www.w3.org/2000/svg", 22 23 /** 24 * Property: xlinkns 25 * {String} 26 */ 27 xlinkns: "http://www.w3.org/1999/xlink", 22 28 23 29 /** … … 34 40 */ 35 41 localResolution: null, 42 43 /** 44 * Property: symbolSize 45 * {Object} Cache for symbol sizes according to their svg coordinate space 46 */ 47 symbolSize: {}, 36 48 37 49 /** … … 155 167 switch (geometry.CLASS_NAME) { 156 168 case "OpenLayers.Geometry.Point": 157 nodeType = style.externalGraphic ? "image" : "circle"; 169 if (style.externalGraphic) { 170 nodeType = "image"; 171 } else if (this.isComplexSymbol(style.graphicName)) { 172 nodeType = "use"; 173 } else { 174 nodeType = "circle"; 175 } 158 176 break; 159 177 case "OpenLayers.Geometry.Rectangle": … … 195 213 options = options || node._options; 196 214 var r = parseFloat(node.getAttributeNS(null, "r")); 215 var widthFactor = 1; 216 var pos; 197 217 if (node._geometryClass == "OpenLayers.Geometry.Point" && r) { 198 218 if (style.externalGraphic) { 199 var x = parseFloat(node.getAttributeNS(null, "cx")); 200 var y = parseFloat(node.getAttributeNS(null, "cy")); 219 pos = this.getPosition(node); 201 220 202 221 if (style.graphicWidth && style.graphicHeight) { … … 214 233 var opacity = style.graphicOpacity || style.fillOpacity; 215 234 216 node.setAttributeNS(null, "x", ( x + xOffset).toFixed());217 node.setAttributeNS(null, "y", ( y + yOffset).toFixed());235 node.setAttributeNS(null, "x", (pos.x + xOffset).toFixed()); 236 node.setAttributeNS(null, "y", (pos.y + yOffset).toFixed()); 218 237 node.setAttributeNS(null, "width", width); 219 238 node.setAttributeNS(null, "height", height); 220 node.setAttributeNS( "http://www.w3.org/1999/xlink", "href", style.externalGraphic);239 node.setAttributeNS(this.xlinkns, "href", style.externalGraphic); 221 240 node.setAttributeNS(null, "style", "opacity: "+opacity); 241 } else if (this.isComplexSymbol(style.graphicName)) { 242 // the symbol viewBox is three times as large as the symbol 243 var offset = style.pointRadius * 3; 244 var size = offset * 2; 245 var id = this.importSymbol(style.graphicName); 246 pos = this.getPosition(node); 247 widthFactor = this.symbolSize[id] / size; 248 node.setAttributeNS(this.xlinkns, "href", "#" + id); 249 node.setAttributeNS(null, "width", size); 250 node.setAttributeNS(null, "height", size); 251 node.setAttributeNS(null, "x", pos.x - offset); 252 node.setAttributeNS(null, "y", pos.y - offset); 222 253 } else { 223 254 node.setAttributeNS(null, "r", style.pointRadius); 224 255 } 225 256 226 if (style.rotation ) {257 if (style.rotation && pos) { 227 258 var rotation = OpenLayers.String.format( 228 "rotate(${0} ${1} ${2})", [style.rotation, x,y]);259 "rotate(${0} ${1} ${2})", [style.rotation, pos.x, pos.y]); 229 260 node.setAttributeNS(null, "transform", rotation); 230 261 } … … 241 272 node.setAttributeNS(null, "stroke", style.strokeColor); 242 273 node.setAttributeNS(null, "stroke-opacity", style.strokeOpacity); 243 node.setAttributeNS(null, "stroke-width", style.strokeWidth );274 node.setAttributeNS(null, "stroke-width", style.strokeWidth * widthFactor); 244 275 node.setAttributeNS(null, "stroke-linecap", style.strokeLinecap); 245 276 } else { … … 307 338 createRoot: function() { 308 339 return this.nodeFactory(this.container.id + "_root", "g"); 340 }, 341 342 /** 343 * Method: createDefs 344 * 345 * Returns: 346 * {DOMElement} The element to which we'll add the symbol definitions 347 */ 348 createDefs: function() { 349 var defs = this.nodeFactory("ol-renderer-defs", "defs"); 350 this.rendererRoot.appendChild(defs); 351 return defs; 309 352 }, 310 353 … … 511 554 } 512 555 }, 556 557 /** 558 * Method: getPosition 559 * Finds the position of an svg node. 560 * 561 * Parameters: 562 * node - {DOMElement} 563 * 564 * Returns: 565 * {Object} hash with x and y properties, representing the coordinates 566 * within the svg coordinate system 567 */ 568 getPosition: function(node) { 569 return({ 570 x: parseFloat(node.getAttributeNS(null, "cx")), 571 y: parseFloat(node.getAttributeNS(null, "cy")) 572 }); 573 }, 574 575 /** 576 * Method: importSymbol 577 * add a new symbol definition from the rendererer's symbol hash 578 * 579 * Parameters: 580 * graphicName - {String} name of the symbol to import 581 * 582 * Returns: 583 * {String} - id of the imported symbol 584 */ 585 importSymbol: function (graphicName) { 586 if (!this.defs) { 587 // create svg defs tag 588 this.defs = this.createDefs(); 589 } 590 var id = this.container.id + "-" + graphicName; 591 592 // check if symbol already exists in the defs 593 if (document.getElementById(id) != null) { 594 return id; 595 } 596 597 var symbol = OpenLayers.Renderer.symbol[graphicName]; 598 if (!symbol) { 599 throw new Error(graphicName + ' is not a valid symbol name'); 600 return; 601 } 602 603 var symbolNode = this.nodeFactory(id, "symbol"); 604 var node = this.nodeFactory(null, "polygon"); 605 symbolNode.appendChild(node); 606 var symbolExtent = new OpenLayers.Bounds( 607 Number.MAX_VALUE, Number.MAX_VALUE, 0, 0); 608 609 var points = ""; 610 var x,y; 611 for (var i=0; i<symbol.length; i=i+2) { 612 x = symbol[i]; 613 y = symbol[i+1]; 614 symbolExtent.left = Math.min(symbolExtent.left, x); 615 symbolExtent.bottom = Math.min(symbolExtent.bottom, y); 616 symbolExtent.right = Math.max(symbolExtent.right, x); 617 symbolExtent.top = Math.max(symbolExtent.top, y); 618 points += " " + x + "," + y; 619 } 620 621 node.setAttributeNS(null, "points", points); 622 // Hard-coded linejoin for now, to make it look the same as in VML. 623 // There is no strokeLinejoin property yet for symbolizers. 624 node.setAttributeNS(null, "stroke-linejoin", "round"); 625 626 var width = symbolExtent.getWidth(); 627 var height = symbolExtent.getHeight(); 628 // create a viewBox three times as large as the symbol itself, 629 // to allow for strokeWidth being displayed correctly at the corners. 630 var viewBox = [symbolExtent.left - width, 631 symbolExtent.bottom - height, width * 3, height * 3]; 632 symbolNode.setAttributeNS(null, "viewBox", viewBox.join(" ")); 633 this.symbolSize[id] = Math.max(width, height) * 3; 634 635 this.defs.appendChild(symbolNode); 636 return symbolNode.id; 637 }, 513 638 514 639 CLASS_NAME: "OpenLayers.Renderer.SVG" trunk/openlayers/lib/OpenLayers/Renderer/VML.js
r7627 r7634 26 26 */ 27 27 xmlns: "urn:schemas-microsoft-com:vml", 28 29 /** 30 * Property: symbolCache 31 * {DOMElement} node holding symbols. This hash is keyed by symbol name, 32 * and each value is a hash with a "path" and an "extent" property. 33 */ 34 symbolCache: {}, 28 35 29 36 /** … … 124 131 switch (geometry.CLASS_NAME) { 125 132 case "OpenLayers.Geometry.Point": 126 nodeType = style.externalGraphic ? "olv:rect" : "olv:oval"; 133 if (style.externalGraphic) { 134 nodeType = "olv:rect"; 135 } else if (this.isComplexSymbol(style.graphicName)) { 136 nodeType = "olv:shape"; 137 } else { 138 nodeType = "olv:oval"; 139 } 127 140 break; 128 141 case "OpenLayers.Geometry.Rectangle": … … 157 170 style = style || node._style; 158 171 options = options || node._options; 172 var widthFactor = 1; 159 173 160 174 if (node._geometryClass == "OpenLayers.Geometry.Point") { … … 180 194 style.fillColor = "none"; 181 195 options.isStroked = false; 182 196 } else if (this.isComplexSymbol(style.graphicName)) { 197 var cache = this.importSymbol(style.graphicName); 198 var symbolExtent = cache.extent; 199 var width = symbolExtent.getWidth(); 200 var height = symbolExtent.getHeight(); 201 node.setAttribute("path", cache.path); 202 node.setAttribute("coordorigin", symbolExtent.left + "," + 203 symbolExtent.bottom); 204 node.setAttribute("coordsize", width + "," + height); 205 node.style.left = symbolExtent.left + "px"; 206 node.style.top = symbolExtent.bottom + "px"; 207 node.style.width = width + "px"; 208 node.style.height = height + "px"; 209 210 this.drawCircle(node, geometry, style.pointRadius); 211 node.style.flip = "y"; 183 212 } else { 184 213 this.drawCircle(node, geometry, style.pointRadius); … … 218 247 fill.aspect = "atmost"; 219 248 } 220 221 // additional rendering for rotated graphics222 if (style.rotation) {223 this.graphicRotate(node, xOffset, yOffset);224 // make the fill fully transparent, because we now have225 // the graphic as imagedata element. We cannot just remove226 // the fill, because this is part of the hack described227 // in graphicRotate228 fill.setAttribute("opacity", 0);229 }230 249 } 231 250 if (fill.parentNode != node) { … … 234 253 } 235 254 255 // additional rendering for rotated graphics or symbols 256 if (style.rotation) { 257 if (style.externalGraphic) { 258 this.graphicRotate(node, xOffset, yOffset); 259 // make the fill fully transparent, because we now have 260 // the graphic as imagedata element. We cannot just remove 261 // the fill, because this is part of the hack described 262 // in graphicRotate 263 fill.setAttribute("opacity", 0); 264 } else { 265 node.style.rotation = style.rotation; 266 } 267 } 236 268 237 269 // stroke … … 695 727 node.path = path.join(""); 696 728 }, 697 729 730 /** 731 * Method: importSymbol 732 * add a new symbol definition from the rendererer's symbol hash 733 * 734 * Parameters: 735 * graphicName - {String} name of the symbol to import 736 * 737 * Returns: 738 * {Object} - hash of {DOMElement} "symbol" and {Number} "size" 739 */ 740 importSymbol: function (graphicName) { 741 var id = this.container.id + "-" + graphicName; 742 743 // check if symbol already exists in the cache 744 var cache = this.symbolCache[id]; 745 if (cache) { 746 return cache; 747 } 748 749 var symbol = OpenLayers.Renderer.symbol[graphicName]; 750 if (!symbol) { 751 throw new Error(graphicName + ' is not a valid symbol name'); 752 return; 753 } 754 755 var symbolExtent = new OpenLayers.Bounds( 756 Number.MAX_VALUE, Number.MAX_VALUE, 0, 0); 757 758 var pathitems = ["m"]; 759 for (var i=0; i<symbol.length; i=i+2) { 760 x = symbol[i]; 761 y = symbol[i+1]; 762 symbolExtent.left = Math.min(symbolExtent.left, x); 763 symbolExtent.bottom = Math.min(symbolExtent.bottom, y); 764 symbolExtent.right = Math.max(symbolExtent.right, x); 765 symbolExtent.top = Math.max(symbolExtent.top, y); 766 767 pathitems.push(x); 768 pathitems.push(y); 769 if (i == 0) { 770 pathitems.push("l"); 771 } 772 } 773 pathitems.push("x e"); 774 var path = pathitems.join(" "); 775 776 cache = { 777 path: path, 778 extent: symbolExtent 779 }; 780 this.symbolCache[id] = cache; 781 782 return cache; 783 }, 784 698 785 CLASS_NAME: "OpenLayers.Renderer.VML" 699 786 }); trunk/openlayers/tests/Renderer/SVG.html
r7586 r7634 372 372 } 373 373 374 375 374 function test_svg_getnodetype(t) { 375 if (!OpenLayers.Renderer.SVG.prototype.supported()) { 376 t.plan(0); 377 return; 378 } 379 380 t.plan(1); 381 382 var r = new OpenLayers.Renderer.SVG(document.body); 383 384 var g = {CLASS_NAME: "OpenLayers.Geometry.Point"} 385 var s = {graphicName: "square"}; 386 387 t.eq(r.getNodeType(g, s), "use", "Correct node type for well known symbols"); 388 } 389 390 function test_svg_importsymbol(t) { 391 if (!OpenLayers.Renderer.SVG.prototype.supported()) { 392 t.plan(0); 393 return; 394 } 395 396 t.plan(2); 397 398 var r = new OpenLayers.Renderer.SVG(document.body); 399 400 r.importSymbol("square"); 401 402 var polygon = document.getElementById("ol-renderer-defs").firstChild.firstChild; 403 404 t.eq(polygon.getAttribute("points"), "0,0 0,1 1,1 1,0 0,0", "Square symbol rendered correctly"); 405 t.ok(r.symbolSize["-square"], "Symbol size cached correctly."); 406 } 407 376 408 </script> 377 409 </head> trunk/openlayers/tests/Renderer/VML.html
r7586 r7634 339 339 } 340 340 341 341 function test_vml_getnodetype(t) { 342 if (!OpenLayers.Renderer.VML.prototype.supported()) { 343 t.plan(0); 344 return; 345 } 346 347 t.plan(1); 348 349 var r = new OpenLayers.Renderer.VML(document.body); 350 351 var g = {CLASS_NAME: "OpenLayers.Geometry.Point"} 352 var s = {graphicName: "square"}; 353 354 t.eq(r.getNodeType(g, s), "olv:shape", "Correct node type for well known symbols"); 355 } 356 357 function test_vml_importsymbol(t) { 358 if (!OpenLayers.Renderer.VML.prototype.supported()) { 359 t.plan(0); 360 return; 361 } 362 363 t.plan(2); 364 365 var r = new OpenLayers.Renderer.VML(document.body); 366 367 var cache = r.importSymbol("square"); 368 369 t.eq(cache.path, "m 0 0 l 0 1 1 1 1 0 0 0 x e", "Square symbol rendered correctly"); 370 t.ok(r.symbolCache["-square"], "Symbol has been cached correctly."); 371 372 } 373 342 374 </script> 343 375 </head>
