added new graphicName symbolizer property, which allows to render well-known graphic symbols named "square", "cross", "x" and "triangle", in addition to the existing "circle". Thanks Tim for the tweaks and the example. r=tschaub,elemoine (closes #1398)
git-svn-id: http://svn.openlayers.org/trunk/openlayers@7634 dc9f47b5-9b13-0410-9fdd-eb0c1a62fdaf
This commit is contained in:
83
examples/graphic-name.html
Normal file
83
examples/graphic-name.html
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||||
|
<head>
|
||||||
|
<title>OpenLayers Graphic Names</title>
|
||||||
|
<link rel="stylesheet" href="../theme/default/style.css" type="text/css" />
|
||||||
|
<link rel="stylesheet" href="style.css" type="text/css" />
|
||||||
|
<script src="../lib/OpenLayers.js"></script>
|
||||||
|
<script type="text/javascript">
|
||||||
|
var map;
|
||||||
|
|
||||||
|
function init() {
|
||||||
|
map = new OpenLayers.Map('map');
|
||||||
|
|
||||||
|
// list of well-known graphic names
|
||||||
|
var graphics = ["star", "cross", "x", "square", "triangle", "circle"];
|
||||||
|
|
||||||
|
// Create one feature for each well known graphic.
|
||||||
|
// Give features a type attribute with the graphic name.
|
||||||
|
var num = graphics.length;
|
||||||
|
var slot = map.maxExtent.getWidth() / num;
|
||||||
|
var features = Array(num);
|
||||||
|
for(var i=0; i<graphics.length; ++i) {
|
||||||
|
lon = map.maxExtent.left + (i * slot) + (slot / 2);
|
||||||
|
features[i] = new OpenLayers.Feature.Vector(
|
||||||
|
new OpenLayers.Geometry.Point(
|
||||||
|
map.maxExtent.left + (i * slot) + (slot / 2), 0
|
||||||
|
), {
|
||||||
|
type: graphics[i]
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a style map for painting the features.
|
||||||
|
// The graphicName property of the symbolizer is evaluated using
|
||||||
|
// the type attribute on each feature (set above).
|
||||||
|
var styles = new OpenLayers.StyleMap({
|
||||||
|
"default": {
|
||||||
|
graphicName: "${type}",
|
||||||
|
pointRadius: 10,
|
||||||
|
strokeColor: "fuchsia",
|
||||||
|
strokeWidth: 2,
|
||||||
|
fillColor: "lime",
|
||||||
|
fillOpacity: 0.6
|
||||||
|
},
|
||||||
|
"select": {
|
||||||
|
pointRadius: 20,
|
||||||
|
fillOpacity: 1
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Create a vector layer and give it your style map.
|
||||||
|
var layer = new OpenLayers.Layer.Vector(
|
||||||
|
"Graphics", {styleMap: styles, isBaseLayer: true}
|
||||||
|
);
|
||||||
|
layer.addFeatures(features);
|
||||||
|
map.addLayer(layer);
|
||||||
|
|
||||||
|
// Create a select feature control and add it to the map.
|
||||||
|
var select = new OpenLayers.Control.SelectFeature(layer, {hover: true});
|
||||||
|
map.addControl(select);
|
||||||
|
select.activate();
|
||||||
|
|
||||||
|
map.setCenter(new OpenLayers.LonLat(0, 0), 0);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body onload="init()">
|
||||||
|
<h1 id="title">Named Graphics Example</h1>
|
||||||
|
|
||||||
|
<div id="tags"></div>
|
||||||
|
|
||||||
|
<p id="shortdesc">
|
||||||
|
Shows how to use well-known graphic names.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div id="map" class="smallmap"></div>
|
||||||
|
|
||||||
|
<div id="docs">
|
||||||
|
OpenLayers supports well-known names for a few graphics. You can use
|
||||||
|
the names "star", "cross", "x", "square", "triangle", and "circle" as
|
||||||
|
the value for the graphicName property of a symbolizer.
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -23,4 +23,18 @@
|
|||||||
<topp:POP_CLASS>100,000 to 250,000</topp:POP_CLASS>
|
<topp:POP_CLASS>100,000 to 250,000</topp:POP_CLASS>
|
||||||
</topp:tasmania_cities>
|
</topp:tasmania_cities>
|
||||||
</gml:featureMember>
|
</gml:featureMember>
|
||||||
|
<gml:featureMember>
|
||||||
|
<topp:tasmania_cities fid="tasmania_cities.2">
|
||||||
|
<topp:the_geom>
|
||||||
|
<gml:MultiPoint srsName="http://www.opengis.net/gml/srs/epsg.xml#4326">
|
||||||
|
<gml:pointMember>
|
||||||
|
<gml:Point>
|
||||||
|
<gml:coordinates xmlns:gml="http://www.opengis.net/gml" decimal="." cs="," ts=" ">147,-41.1</gml:coordinates>
|
||||||
|
</gml:Point>
|
||||||
|
</gml:pointMember>
|
||||||
|
</gml:MultiPoint>
|
||||||
|
</topp:the_geom>
|
||||||
|
<topp:CNTRY_NAME>Australia</topp:CNTRY_NAME>
|
||||||
|
</topp:tasmania_cities>
|
||||||
|
</gml:featureMember>
|
||||||
</wfs:FeatureCollection>
|
</wfs:FeatureCollection>
|
||||||
|
|||||||
@@ -528,13 +528,27 @@
|
|||||||
<sld:IsDefault>1</sld:IsDefault>
|
<sld:IsDefault>1</sld:IsDefault>
|
||||||
<sld:FeatureTypeStyle>
|
<sld:FeatureTypeStyle>
|
||||||
<sld:Rule>
|
<sld:Rule>
|
||||||
|
<ogc:Filter>
|
||||||
|
<ogc:FeatureId fid="tasmania_cities.1"/>
|
||||||
|
</ogc:Filter>
|
||||||
<sld:PointSymbolizer>
|
<sld:PointSymbolizer>
|
||||||
<sld:Graphic>
|
<sld:Graphic>
|
||||||
<sld:ExternalGraphic>
|
<sld:ExternalGraphic>
|
||||||
<sld:OnlineResource xlink:href="../img/marker.png" />
|
<sld:OnlineResource xlink:href="../img/marker.png" />
|
||||||
<sld:Format>image/png</sld:Format>
|
<sld:Format>image/png</sld:Format>
|
||||||
</sld:ExternalGraphic>
|
</sld:ExternalGraphic>
|
||||||
<sld:Opacity>0.5</sld:Opacity>
|
<sld:Opacity>0.7</sld:Opacity>
|
||||||
|
<sld:Size>14</sld:Size>
|
||||||
|
</sld:Graphic>
|
||||||
|
</sld:PointSymbolizer>
|
||||||
|
</sld:Rule>
|
||||||
|
<sld:Rule>
|
||||||
|
<sld:ElseFilter/>
|
||||||
|
<sld:PointSymbolizer>
|
||||||
|
<sld:Graphic>
|
||||||
|
<sld:Mark>
|
||||||
|
<sld:WellKnownName>cross</sld:WellKnownName>
|
||||||
|
</sld:Mark>
|
||||||
<sld:Size>10</sld:Size>
|
<sld:Size>10</sld:Size>
|
||||||
</sld:Graphic>
|
</sld:Graphic>
|
||||||
</sld:PointSymbolizer>
|
</sld:PointSymbolizer>
|
||||||
|
|||||||
@@ -26,6 +26,11 @@
|
|||||||
var style_blue = OpenLayers.Util.extend({}, layer_style);
|
var style_blue = OpenLayers.Util.extend({}, layer_style);
|
||||||
style_blue.strokeColor = "blue";
|
style_blue.strokeColor = "blue";
|
||||||
style_blue.fillColor = "blue";
|
style_blue.fillColor = "blue";
|
||||||
|
style_blue.graphicName = "star";
|
||||||
|
style_blue.pointRadius = 10;
|
||||||
|
style_blue.strokeWidth = 3;
|
||||||
|
style_blue.rotation = 45;
|
||||||
|
style_blue.strokeLinecap = "butt";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Green style
|
* Green style
|
||||||
|
|||||||
@@ -323,9 +323,10 @@ OpenLayers.Feature.Vector = OpenLayers.Class(OpenLayers.Feature, {
|
|||||||
* - externalGraphic,
|
* - externalGraphic,
|
||||||
* - graphicWidth,
|
* - graphicWidth,
|
||||||
* - graphicHeight,
|
* - graphicHeight,
|
||||||
* - graphicOpacity
|
* - graphicOpacity,
|
||||||
* - graphicXOffset
|
* - graphicXOffset,
|
||||||
* - graphicYOffset
|
* - graphicYOffset,
|
||||||
|
* - graphicName,
|
||||||
* - display
|
* - display
|
||||||
*/
|
*/
|
||||||
OpenLayers.Feature.Vector.style = {
|
OpenLayers.Feature.Vector.style = {
|
||||||
|
|||||||
@@ -52,7 +52,8 @@ OpenLayers.Format.SLD.v1 = OpenLayers.Class(OpenLayers.Format.XML, {
|
|||||||
strokeColor: "#000000",
|
strokeColor: "#000000",
|
||||||
strokeOpacity: 1,
|
strokeOpacity: 1,
|
||||||
strokeWidth: 1,
|
strokeWidth: 1,
|
||||||
pointRadius: 6
|
pointRadius: 3,
|
||||||
|
graphicName: "square"
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -371,6 +371,35 @@ OpenLayers.Renderer.Elements = OpenLayers.Class(OpenLayers.Renderer, {
|
|||||||
}
|
}
|
||||||
return node;
|
return node;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method: isComplexSymbol
|
||||||
|
* Determines if a symbol cannot be rendered using drawCircle
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* graphicName - {String}
|
||||||
|
*
|
||||||
|
* Returns
|
||||||
|
* {Boolean} true if the symbol is complex, false if not
|
||||||
|
*/
|
||||||
|
isComplexSymbol: function(graphicName) {
|
||||||
|
return (graphicName != "circle") && !!graphicName;
|
||||||
|
},
|
||||||
|
|
||||||
CLASS_NAME: "OpenLayers.Renderer.Elements"
|
CLASS_NAME: "OpenLayers.Renderer.Elements"
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constant: OpenLayers.Renderer.symbol
|
||||||
|
* Coordinate arrays for well known (named) symbols.
|
||||||
|
*/
|
||||||
|
OpenLayers.Renderer.symbol = {
|
||||||
|
"star": [350,75, 379,161, 469,161, 397,215, 423,301, 350,250, 277,301,
|
||||||
|
303,215, 231,161, 321,161, 350,75],
|
||||||
|
"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,
|
||||||
|
4,0],
|
||||||
|
"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],
|
||||||
|
"square": [0,0, 0,1, 1,1, 1,0, 0,0],
|
||||||
|
"triangle": [0,10, 10,10, 5,0, 0,10]
|
||||||
|
}
|
||||||
|
|||||||
@@ -19,6 +19,12 @@ OpenLayers.Renderer.SVG = OpenLayers.Class(OpenLayers.Renderer.Elements, {
|
|||||||
* {String}
|
* {String}
|
||||||
*/
|
*/
|
||||||
xmlns: "http://www.w3.org/2000/svg",
|
xmlns: "http://www.w3.org/2000/svg",
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Property: xlinkns
|
||||||
|
* {String}
|
||||||
|
*/
|
||||||
|
xlinkns: "http://www.w3.org/1999/xlink",
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constant: MAX_PIXEL
|
* Constant: MAX_PIXEL
|
||||||
@@ -33,6 +39,12 @@ OpenLayers.Renderer.SVG = OpenLayers.Class(OpenLayers.Renderer.Elements, {
|
|||||||
* {Float}
|
* {Float}
|
||||||
*/
|
*/
|
||||||
localResolution: null,
|
localResolution: null,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Property: symbolSize
|
||||||
|
* {Object} Cache for symbol sizes according to their svg coordinate space
|
||||||
|
*/
|
||||||
|
symbolSize: {},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor: OpenLayers.Renderer.SVG
|
* Constructor: OpenLayers.Renderer.SVG
|
||||||
@@ -154,7 +166,13 @@ OpenLayers.Renderer.SVG = OpenLayers.Class(OpenLayers.Renderer.Elements, {
|
|||||||
var nodeType = null;
|
var nodeType = null;
|
||||||
switch (geometry.CLASS_NAME) {
|
switch (geometry.CLASS_NAME) {
|
||||||
case "OpenLayers.Geometry.Point":
|
case "OpenLayers.Geometry.Point":
|
||||||
nodeType = style.externalGraphic ? "image" : "circle";
|
if (style.externalGraphic) {
|
||||||
|
nodeType = "image";
|
||||||
|
} else if (this.isComplexSymbol(style.graphicName)) {
|
||||||
|
nodeType = "use";
|
||||||
|
} else {
|
||||||
|
nodeType = "circle";
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case "OpenLayers.Geometry.Rectangle":
|
case "OpenLayers.Geometry.Rectangle":
|
||||||
nodeType = "rect";
|
nodeType = "rect";
|
||||||
@@ -194,10 +212,11 @@ OpenLayers.Renderer.SVG = OpenLayers.Class(OpenLayers.Renderer.Elements, {
|
|||||||
style = style || node._style;
|
style = style || node._style;
|
||||||
options = options || node._options;
|
options = options || node._options;
|
||||||
var r = parseFloat(node.getAttributeNS(null, "r"));
|
var r = parseFloat(node.getAttributeNS(null, "r"));
|
||||||
|
var widthFactor = 1;
|
||||||
|
var pos;
|
||||||
if (node._geometryClass == "OpenLayers.Geometry.Point" && r) {
|
if (node._geometryClass == "OpenLayers.Geometry.Point" && r) {
|
||||||
if (style.externalGraphic) {
|
if (style.externalGraphic) {
|
||||||
var x = parseFloat(node.getAttributeNS(null, "cx"));
|
pos = this.getPosition(node);
|
||||||
var y = parseFloat(node.getAttributeNS(null, "cy"));
|
|
||||||
|
|
||||||
if (style.graphicWidth && style.graphicHeight) {
|
if (style.graphicWidth && style.graphicHeight) {
|
||||||
node.setAttributeNS(null, "preserveAspectRatio", "none");
|
node.setAttributeNS(null, "preserveAspectRatio", "none");
|
||||||
@@ -213,19 +232,31 @@ OpenLayers.Renderer.SVG = OpenLayers.Class(OpenLayers.Renderer.Elements, {
|
|||||||
|
|
||||||
var opacity = style.graphicOpacity || style.fillOpacity;
|
var opacity = style.graphicOpacity || style.fillOpacity;
|
||||||
|
|
||||||
node.setAttributeNS(null, "x", (x + xOffset).toFixed());
|
node.setAttributeNS(null, "x", (pos.x + xOffset).toFixed());
|
||||||
node.setAttributeNS(null, "y", (y + yOffset).toFixed());
|
node.setAttributeNS(null, "y", (pos.y + yOffset).toFixed());
|
||||||
node.setAttributeNS(null, "width", width);
|
node.setAttributeNS(null, "width", width);
|
||||||
node.setAttributeNS(null, "height", height);
|
node.setAttributeNS(null, "height", height);
|
||||||
node.setAttributeNS("http://www.w3.org/1999/xlink", "href", style.externalGraphic);
|
node.setAttributeNS(this.xlinkns, "href", style.externalGraphic);
|
||||||
node.setAttributeNS(null, "style", "opacity: "+opacity);
|
node.setAttributeNS(null, "style", "opacity: "+opacity);
|
||||||
|
} else if (this.isComplexSymbol(style.graphicName)) {
|
||||||
|
// the symbol viewBox is three times as large as the symbol
|
||||||
|
var offset = style.pointRadius * 3;
|
||||||
|
var size = offset * 2;
|
||||||
|
var id = this.importSymbol(style.graphicName);
|
||||||
|
pos = this.getPosition(node);
|
||||||
|
widthFactor = this.symbolSize[id] / size;
|
||||||
|
node.setAttributeNS(this.xlinkns, "href", "#" + id);
|
||||||
|
node.setAttributeNS(null, "width", size);
|
||||||
|
node.setAttributeNS(null, "height", size);
|
||||||
|
node.setAttributeNS(null, "x", pos.x - offset);
|
||||||
|
node.setAttributeNS(null, "y", pos.y - offset);
|
||||||
} else {
|
} else {
|
||||||
node.setAttributeNS(null, "r", style.pointRadius);
|
node.setAttributeNS(null, "r", style.pointRadius);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (style.rotation) {
|
if (style.rotation && pos) {
|
||||||
var rotation = OpenLayers.String.format(
|
var rotation = OpenLayers.String.format(
|
||||||
"rotate(${0} ${1} ${2})", [style.rotation, x, y]);
|
"rotate(${0} ${1} ${2})", [style.rotation, pos.x, pos.y]);
|
||||||
node.setAttributeNS(null, "transform", rotation);
|
node.setAttributeNS(null, "transform", rotation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -240,7 +271,7 @@ OpenLayers.Renderer.SVG = OpenLayers.Class(OpenLayers.Renderer.Elements, {
|
|||||||
if (options.isStroked) {
|
if (options.isStroked) {
|
||||||
node.setAttributeNS(null, "stroke", style.strokeColor);
|
node.setAttributeNS(null, "stroke", style.strokeColor);
|
||||||
node.setAttributeNS(null, "stroke-opacity", style.strokeOpacity);
|
node.setAttributeNS(null, "stroke-opacity", style.strokeOpacity);
|
||||||
node.setAttributeNS(null, "stroke-width", style.strokeWidth);
|
node.setAttributeNS(null, "stroke-width", style.strokeWidth * widthFactor);
|
||||||
node.setAttributeNS(null, "stroke-linecap", style.strokeLinecap);
|
node.setAttributeNS(null, "stroke-linecap", style.strokeLinecap);
|
||||||
} else {
|
} else {
|
||||||
node.setAttributeNS(null, "stroke", "none");
|
node.setAttributeNS(null, "stroke", "none");
|
||||||
@@ -308,6 +339,18 @@ OpenLayers.Renderer.SVG = OpenLayers.Class(OpenLayers.Renderer.Elements, {
|
|||||||
return this.nodeFactory(this.container.id + "_root", "g");
|
return this.nodeFactory(this.container.id + "_root", "g");
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method: createDefs
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* {DOMElement} The element to which we'll add the symbol definitions
|
||||||
|
*/
|
||||||
|
createDefs: function() {
|
||||||
|
var defs = this.nodeFactory("ol-renderer-defs", "defs");
|
||||||
|
this.rendererRoot.appendChild(defs);
|
||||||
|
return defs;
|
||||||
|
},
|
||||||
|
|
||||||
/**************************************
|
/**************************************
|
||||||
* *
|
* *
|
||||||
* GEOMETRY DRAWING FUNCTIONS *
|
* GEOMETRY DRAWING FUNCTIONS *
|
||||||
@@ -510,6 +553,88 @@ OpenLayers.Renderer.SVG = OpenLayers.Class(OpenLayers.Renderer.Elements, {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method: getPosition
|
||||||
|
* Finds the position of an svg node.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* node - {DOMElement}
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* {Object} hash with x and y properties, representing the coordinates
|
||||||
|
* within the svg coordinate system
|
||||||
|
*/
|
||||||
|
getPosition: function(node) {
|
||||||
|
return({
|
||||||
|
x: parseFloat(node.getAttributeNS(null, "cx")),
|
||||||
|
y: parseFloat(node.getAttributeNS(null, "cy"))
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method: importSymbol
|
||||||
|
* add a new symbol definition from the rendererer's symbol hash
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* graphicName - {String} name of the symbol to import
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* {String} - id of the imported symbol
|
||||||
|
*/
|
||||||
|
importSymbol: function (graphicName) {
|
||||||
|
if (!this.defs) {
|
||||||
|
// create svg defs tag
|
||||||
|
this.defs = this.createDefs();
|
||||||
|
}
|
||||||
|
var id = this.container.id + "-" + graphicName;
|
||||||
|
|
||||||
|
// check if symbol already exists in the defs
|
||||||
|
if (document.getElementById(id) != null) {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
var symbol = OpenLayers.Renderer.symbol[graphicName];
|
||||||
|
if (!symbol) {
|
||||||
|
throw new Error(graphicName + ' is not a valid symbol name');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var symbolNode = this.nodeFactory(id, "symbol");
|
||||||
|
var node = this.nodeFactory(null, "polygon");
|
||||||
|
symbolNode.appendChild(node);
|
||||||
|
var symbolExtent = new OpenLayers.Bounds(
|
||||||
|
Number.MAX_VALUE, Number.MAX_VALUE, 0, 0);
|
||||||
|
|
||||||
|
var points = "";
|
||||||
|
var x,y;
|
||||||
|
for (var i=0; i<symbol.length; i=i+2) {
|
||||||
|
x = symbol[i];
|
||||||
|
y = symbol[i+1];
|
||||||
|
symbolExtent.left = Math.min(symbolExtent.left, x);
|
||||||
|
symbolExtent.bottom = Math.min(symbolExtent.bottom, y);
|
||||||
|
symbolExtent.right = Math.max(symbolExtent.right, x);
|
||||||
|
symbolExtent.top = Math.max(symbolExtent.top, y);
|
||||||
|
points += " " + x + "," + y;
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
// create a viewBox three times as large as the symbol itself,
|
||||||
|
// to allow for strokeWidth being displayed correctly at the corners.
|
||||||
|
var viewBox = [symbolExtent.left - width,
|
||||||
|
symbolExtent.bottom - height, width * 3, height * 3];
|
||||||
|
symbolNode.setAttributeNS(null, "viewBox", viewBox.join(" "));
|
||||||
|
this.symbolSize[id] = Math.max(width, height) * 3;
|
||||||
|
|
||||||
|
this.defs.appendChild(symbolNode);
|
||||||
|
return symbolNode.id;
|
||||||
|
},
|
||||||
|
|
||||||
CLASS_NAME: "OpenLayers.Renderer.SVG"
|
CLASS_NAME: "OpenLayers.Renderer.SVG"
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -25,6 +25,13 @@ OpenLayers.Renderer.VML = OpenLayers.Class(OpenLayers.Renderer.Elements, {
|
|||||||
* {String} XML Namespace URN
|
* {String} XML Namespace URN
|
||||||
*/
|
*/
|
||||||
xmlns: "urn:schemas-microsoft-com:vml",
|
xmlns: "urn:schemas-microsoft-com:vml",
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Property: symbolCache
|
||||||
|
* {DOMElement} node holding symbols. This hash is keyed by symbol name,
|
||||||
|
* and each value is a hash with a "path" and an "extent" property.
|
||||||
|
*/
|
||||||
|
symbolCache: {},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor: OpenLayers.Renderer.VML
|
* Constructor: OpenLayers.Renderer.VML
|
||||||
@@ -123,7 +130,13 @@ OpenLayers.Renderer.VML = OpenLayers.Class(OpenLayers.Renderer.Elements, {
|
|||||||
var nodeType = null;
|
var nodeType = null;
|
||||||
switch (geometry.CLASS_NAME) {
|
switch (geometry.CLASS_NAME) {
|
||||||
case "OpenLayers.Geometry.Point":
|
case "OpenLayers.Geometry.Point":
|
||||||
nodeType = style.externalGraphic ? "olv:rect" : "olv:oval";
|
if (style.externalGraphic) {
|
||||||
|
nodeType = "olv:rect";
|
||||||
|
} else if (this.isComplexSymbol(style.graphicName)) {
|
||||||
|
nodeType = "olv:shape";
|
||||||
|
} else {
|
||||||
|
nodeType = "olv:oval";
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case "OpenLayers.Geometry.Rectangle":
|
case "OpenLayers.Geometry.Rectangle":
|
||||||
nodeType = "olv:rect";
|
nodeType = "olv:rect";
|
||||||
@@ -156,6 +169,7 @@ OpenLayers.Renderer.VML = OpenLayers.Class(OpenLayers.Renderer.Elements, {
|
|||||||
setStyle: function(node, style, options, geometry) {
|
setStyle: function(node, style, options, geometry) {
|
||||||
style = style || node._style;
|
style = style || node._style;
|
||||||
options = options || node._options;
|
options = options || node._options;
|
||||||
|
var widthFactor = 1;
|
||||||
|
|
||||||
if (node._geometryClass == "OpenLayers.Geometry.Point") {
|
if (node._geometryClass == "OpenLayers.Geometry.Point") {
|
||||||
if (style.externalGraphic) {
|
if (style.externalGraphic) {
|
||||||
@@ -179,7 +193,22 @@ OpenLayers.Renderer.VML = OpenLayers.Class(OpenLayers.Renderer.Elements, {
|
|||||||
// modify style/options for fill and stroke styling below
|
// modify style/options for fill and stroke styling below
|
||||||
style.fillColor = "none";
|
style.fillColor = "none";
|
||||||
options.isStroked = false;
|
options.isStroked = false;
|
||||||
|
} else if (this.isComplexSymbol(style.graphicName)) {
|
||||||
|
var cache = this.importSymbol(style.graphicName);
|
||||||
|
var symbolExtent = cache.extent;
|
||||||
|
var width = symbolExtent.getWidth();
|
||||||
|
var height = symbolExtent.getHeight();
|
||||||
|
node.setAttribute("path", cache.path);
|
||||||
|
node.setAttribute("coordorigin", symbolExtent.left + "," +
|
||||||
|
symbolExtent.bottom);
|
||||||
|
node.setAttribute("coordsize", width + "," + height);
|
||||||
|
node.style.left = symbolExtent.left + "px";
|
||||||
|
node.style.top = symbolExtent.bottom + "px";
|
||||||
|
node.style.width = width + "px";
|
||||||
|
node.style.height = height + "px";
|
||||||
|
|
||||||
|
this.drawCircle(node, geometry, style.pointRadius);
|
||||||
|
node.style.flip = "y";
|
||||||
} else {
|
} else {
|
||||||
this.drawCircle(node, geometry, style.pointRadius);
|
this.drawCircle(node, geometry, style.pointRadius);
|
||||||
}
|
}
|
||||||
@@ -217,22 +246,25 @@ OpenLayers.Renderer.VML = OpenLayers.Class(OpenLayers.Renderer.Elements, {
|
|||||||
if (!(style.graphicWidth && style.graphicHeight)) {
|
if (!(style.graphicWidth && style.graphicHeight)) {
|
||||||
fill.aspect = "atmost";
|
fill.aspect = "atmost";
|
||||||
}
|
}
|
||||||
|
|
||||||
// additional rendering for rotated graphics
|
|
||||||
if (style.rotation) {
|
|
||||||
this.graphicRotate(node, xOffset, yOffset);
|
|
||||||
// make the fill fully transparent, because we now have
|
|
||||||
// the graphic as imagedata element. We cannot just remove
|
|
||||||
// the fill, because this is part of the hack described
|
|
||||||
// in graphicRotate
|
|
||||||
fill.setAttribute("opacity", 0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (fill.parentNode != node) {
|
if (fill.parentNode != node) {
|
||||||
node.appendChild(fill);
|
node.appendChild(fill);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// additional rendering for rotated graphics or symbols
|
||||||
|
if (style.rotation) {
|
||||||
|
if (style.externalGraphic) {
|
||||||
|
this.graphicRotate(node, xOffset, yOffset);
|
||||||
|
// make the fill fully transparent, because we now have
|
||||||
|
// the graphic as imagedata element. We cannot just remove
|
||||||
|
// the fill, because this is part of the hack described
|
||||||
|
// in graphicRotate
|
||||||
|
fill.setAttribute("opacity", 0);
|
||||||
|
} else {
|
||||||
|
node.style.rotation = style.rotation;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// stroke
|
// stroke
|
||||||
if (options.isStroked) {
|
if (options.isStroked) {
|
||||||
@@ -694,6 +726,61 @@ OpenLayers.Renderer.VML = OpenLayers.Class(OpenLayers.Renderer.Elements, {
|
|||||||
|
|
||||||
node.path = path.join("");
|
node.path = path.join("");
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method: importSymbol
|
||||||
|
* add a new symbol definition from the rendererer's symbol hash
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* graphicName - {String} name of the symbol to import
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* {Object} - hash of {DOMElement} "symbol" and {Number} "size"
|
||||||
|
*/
|
||||||
|
importSymbol: function (graphicName) {
|
||||||
|
var id = this.container.id + "-" + graphicName;
|
||||||
|
|
||||||
|
// check if symbol already exists in the cache
|
||||||
|
var cache = this.symbolCache[id];
|
||||||
|
if (cache) {
|
||||||
|
return cache;
|
||||||
|
}
|
||||||
|
|
||||||
|
var symbol = OpenLayers.Renderer.symbol[graphicName];
|
||||||
|
if (!symbol) {
|
||||||
|
throw new Error(graphicName + ' is not a valid symbol name');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var symbolExtent = new OpenLayers.Bounds(
|
||||||
|
Number.MAX_VALUE, Number.MAX_VALUE, 0, 0);
|
||||||
|
|
||||||
|
var pathitems = ["m"];
|
||||||
|
for (var i=0; i<symbol.length; i=i+2) {
|
||||||
|
x = symbol[i];
|
||||||
|
y = symbol[i+1];
|
||||||
|
symbolExtent.left = Math.min(symbolExtent.left, x);
|
||||||
|
symbolExtent.bottom = Math.min(symbolExtent.bottom, y);
|
||||||
|
symbolExtent.right = Math.max(symbolExtent.right, x);
|
||||||
|
symbolExtent.top = Math.max(symbolExtent.top, y);
|
||||||
|
|
||||||
|
pathitems.push(x);
|
||||||
|
pathitems.push(y);
|
||||||
|
if (i == 0) {
|
||||||
|
pathitems.push("l");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pathitems.push("x e");
|
||||||
|
var path = pathitems.join(" ");
|
||||||
|
|
||||||
|
cache = {
|
||||||
|
path: path,
|
||||||
|
extent: symbolExtent
|
||||||
|
};
|
||||||
|
this.symbolCache[id] = cache;
|
||||||
|
|
||||||
|
return cache;
|
||||||
|
},
|
||||||
|
|
||||||
CLASS_NAME: "OpenLayers.Renderer.VML"
|
CLASS_NAME: "OpenLayers.Renderer.VML"
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -371,8 +371,40 @@
|
|||||||
t.eq(string, "2,-4", "returned string is correct");
|
t.eq(string, "2,-4", "returned string is correct");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function test_svg_getnodetype(t) {
|
||||||
|
if (!OpenLayers.Renderer.SVG.prototype.supported()) {
|
||||||
|
t.plan(0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
t.plan(1);
|
||||||
|
|
||||||
|
var r = new OpenLayers.Renderer.SVG(document.body);
|
||||||
|
|
||||||
|
var g = {CLASS_NAME: "OpenLayers.Geometry.Point"}
|
||||||
|
var s = {graphicName: "square"};
|
||||||
|
|
||||||
|
t.eq(r.getNodeType(g, s), "use", "Correct node type for well known symbols");
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_svg_importsymbol(t) {
|
||||||
|
if (!OpenLayers.Renderer.SVG.prototype.supported()) {
|
||||||
|
t.plan(0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
t.plan(2);
|
||||||
|
|
||||||
|
var r = new OpenLayers.Renderer.SVG(document.body);
|
||||||
|
|
||||||
|
r.importSymbol("square");
|
||||||
|
|
||||||
|
var polygon = document.getElementById("ol-renderer-defs").firstChild.firstChild;
|
||||||
|
|
||||||
|
t.eq(polygon.getAttribute("points"), "0,0 0,1 1,1 1,0 0,0", "Square symbol rendered correctly");
|
||||||
|
t.ok(r.symbolSize["-square"], "Symbol size cached correctly.");
|
||||||
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|||||||
@@ -338,7 +338,39 @@
|
|||||||
t.eq(node.style.height, "8px", "node.style.height is correct");
|
t.eq(node.style.height, "8px", "node.style.height is correct");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function test_vml_getnodetype(t) {
|
||||||
|
if (!OpenLayers.Renderer.VML.prototype.supported()) {
|
||||||
|
t.plan(0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
t.plan(1);
|
||||||
|
|
||||||
|
var r = new OpenLayers.Renderer.VML(document.body);
|
||||||
|
|
||||||
|
var g = {CLASS_NAME: "OpenLayers.Geometry.Point"}
|
||||||
|
var s = {graphicName: "square"};
|
||||||
|
|
||||||
|
t.eq(r.getNodeType(g, s), "olv:shape", "Correct node type for well known symbols");
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_vml_importsymbol(t) {
|
||||||
|
if (!OpenLayers.Renderer.VML.prototype.supported()) {
|
||||||
|
t.plan(0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
t.plan(2);
|
||||||
|
|
||||||
|
var r = new OpenLayers.Renderer.VML(document.body);
|
||||||
|
|
||||||
|
var cache = r.importSymbol("square");
|
||||||
|
|
||||||
|
t.eq(cache.path, "m 0 0 l 0 1 1 1 1 0 0 0 x e", "Square symbol rendered correctly");
|
||||||
|
t.ok(r.symbolCache["-square"], "Symbol has been cached correctly.");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|||||||
Reference in New Issue
Block a user