Move SVG2 renderer to deprecated.js
This commit is contained in:
@@ -411,7 +411,6 @@ Group: OpenLayers {
|
||||
File: ElementsIndexer (no auto-title, OpenLayers/Renderer/Elements.js)
|
||||
File: NG (no auto-title, OpenLayers/Renderer/NG.js)
|
||||
File: SVG (no auto-title, OpenLayers/Renderer/SVG.js)
|
||||
File: SVG2 (no auto-title, OpenLayers/Renderer/SVG2.js)
|
||||
File: VML (no auto-title, OpenLayers/Renderer/VML.js)
|
||||
} # Group: Renderer
|
||||
|
||||
|
||||
@@ -411,7 +411,6 @@ Group: OpenLayers {
|
||||
File: ElementsIndexer (no auto-title, OpenLayers/Renderer/Elements.js)
|
||||
File: NG (no auto-title, OpenLayers/Renderer/NG.js)
|
||||
File: SVG (no auto-title, OpenLayers/Renderer/SVG.js)
|
||||
File: SVG2 (no auto-title, OpenLayers/Renderer/SVG2.js)
|
||||
File: VML (no auto-title, OpenLayers/Renderer/VML.js)
|
||||
} # Group: Renderer
|
||||
|
||||
|
||||
@@ -259,7 +259,6 @@
|
||||
"OpenLayers/Renderer/Elements.js",
|
||||
"OpenLayers/Renderer/NG.js",
|
||||
"OpenLayers/Renderer/SVG.js",
|
||||
"OpenLayers/Renderer/SVG2.js",
|
||||
"OpenLayers/Renderer/Canvas.js",
|
||||
"OpenLayers/Renderer/VML.js",
|
||||
"OpenLayers/Layer/Vector.js",
|
||||
|
||||
@@ -1,797 +0,0 @@
|
||||
/* Copyright (c) 2006-2012 by OpenLayers Contributors (see authors.txt for
|
||||
* full list of contributors). Published under the Clear BSD license.
|
||||
* See http://svn.openlayers.org/trunk/openlayers/license.txt for the
|
||||
* full text of the license. */
|
||||
|
||||
/**
|
||||
* @requires OpenLayers/Renderer/NG.js
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class: OpenLayers.Renderer.SVG2
|
||||
*
|
||||
* Inherits from:
|
||||
* - <OpenLayers.Renderer.NG>
|
||||
*/
|
||||
OpenLayers.Renderer.SVG2 = OpenLayers.Class(OpenLayers.Renderer.NG, {
|
||||
|
||||
/**
|
||||
* Property: xmlns
|
||||
* {String}
|
||||
*/
|
||||
xmlns: "http://www.w3.org/2000/svg",
|
||||
|
||||
/**
|
||||
* Property: xlinkns
|
||||
* {String}
|
||||
*/
|
||||
xlinkns: "http://www.w3.org/1999/xlink",
|
||||
|
||||
/**
|
||||
* Property: symbolMetrics
|
||||
* {Object} Cache for symbol metrics according to their svg coordinate
|
||||
* space. This is an object keyed by the symbol's id, and values are
|
||||
* an object with size, x and y properties.
|
||||
*/
|
||||
symbolMetrics: null,
|
||||
|
||||
/**
|
||||
* Constant: labelNodeType
|
||||
* {String} The node type for text label containers.
|
||||
*/
|
||||
labelNodeType: "g",
|
||||
|
||||
/**
|
||||
* Constructor: OpenLayers.Renderer.SVG2
|
||||
*
|
||||
* Parameters:
|
||||
* containerID - {String}
|
||||
*/
|
||||
initialize: function(containerID) {
|
||||
if (!this.supported()) {
|
||||
return;
|
||||
}
|
||||
OpenLayers.Renderer.Elements.prototype.initialize.apply(this,
|
||||
arguments);
|
||||
|
||||
this.symbolMetrics = {};
|
||||
},
|
||||
|
||||
/**
|
||||
* APIMethod: supported
|
||||
*
|
||||
* Returns:
|
||||
* {Boolean} Whether or not the browser supports the SVG renderer
|
||||
*/
|
||||
supported: function() {
|
||||
var svgFeature = "http://www.w3.org/TR/SVG11/feature#";
|
||||
return (document.implementation &&
|
||||
(document.implementation.hasFeature("org.w3c.svg", "1.0") ||
|
||||
document.implementation.hasFeature(svgFeature + "SVG", "1.1") ||
|
||||
document.implementation.hasFeature(svgFeature + "BasicStructure", "1.1") ));
|
||||
},
|
||||
|
||||
/**
|
||||
* Method: updateDimensions
|
||||
*
|
||||
* Parameters:
|
||||
* zoomChanged - {Boolean}
|
||||
*/
|
||||
updateDimensions: function(zoomChanged) {
|
||||
OpenLayers.Renderer.NG.prototype.updateDimensions.apply(this, arguments);
|
||||
|
||||
var res = this.getResolution();
|
||||
|
||||
var width = this.extent.getWidth();
|
||||
var height = this.extent.getHeight();
|
||||
|
||||
var extentString = [
|
||||
this.extent.left,
|
||||
-this.extent.top,
|
||||
width,
|
||||
height
|
||||
].join(" ");
|
||||
this.rendererRoot.setAttributeNS(null, "viewBox", extentString);
|
||||
this.rendererRoot.setAttributeNS(null, "width", width / res);
|
||||
this.rendererRoot.setAttributeNS(null, "height", height / res);
|
||||
|
||||
if (zoomChanged === true) {
|
||||
// update styles for the new resolution
|
||||
var i, len;
|
||||
var nodes = this.vectorRoot.childNodes;
|
||||
for (i=0, len=nodes.length; i<len; ++i) {
|
||||
this.setStyle(nodes[i]);
|
||||
}
|
||||
var textNodes = this.textRoot.childNodes;
|
||||
var label;
|
||||
for (i=0, len=textNodes.length; i<len; ++i) {
|
||||
label = textNodes[i];
|
||||
this.drawText(label, label._style,
|
||||
new OpenLayers.Geometry.Point(label._x, label._y)
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Method: getNodeType
|
||||
*
|
||||
* Parameters:
|
||||
* geometry - {<OpenLayers.Geometry>}
|
||||
* style - {Object}
|
||||
*
|
||||
* Returns:
|
||||
* {String} The corresponding node type for the specified geometry
|
||||
*/
|
||||
getNodeType: function(geometry, style) {
|
||||
var nodeType = null;
|
||||
switch (geometry.CLASS_NAME) {
|
||||
case "OpenLayers.Geometry.Point":
|
||||
if (style.externalGraphic) {
|
||||
nodeType = "image";
|
||||
} else if (this.isComplexSymbol(style.graphicName)) {
|
||||
nodeType = "svg";
|
||||
} else {
|
||||
nodeType = "circle";
|
||||
}
|
||||
break;
|
||||
case "OpenLayers.Geometry.Rectangle":
|
||||
nodeType = "rect";
|
||||
break;
|
||||
case "OpenLayers.Geometry.LineString":
|
||||
nodeType = "polyline";
|
||||
break;
|
||||
case "OpenLayers.Geometry.LinearRing":
|
||||
nodeType = "polygon";
|
||||
break;
|
||||
case "OpenLayers.Geometry.Polygon":
|
||||
case "OpenLayers.Geometry.Curve":
|
||||
nodeType = "path";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return nodeType;
|
||||
},
|
||||
|
||||
/**
|
||||
* Method: setStyle
|
||||
* Use to set all the style attributes to a SVG node.
|
||||
*
|
||||
* Takes care to adjust stroke width and point radius to be
|
||||
* resolution-relative
|
||||
*
|
||||
* Parameters:
|
||||
* node - {SVGDomElement} An SVG element to decorate
|
||||
* style - {Object}
|
||||
* options - {Object} Currently supported options include
|
||||
* 'isFilled' {Boolean} and
|
||||
* 'isStroked' {Boolean}
|
||||
*/
|
||||
setStyle: function(node, style, options) {
|
||||
style = style || node._style;
|
||||
options = options || node._options;
|
||||
var resolution = this.getResolution();
|
||||
var r = node._radius;
|
||||
var widthFactor = resolution;
|
||||
if (node._geometryClass == "OpenLayers.Geometry.Point" && r) {
|
||||
node.style.visibility = "";
|
||||
if (style.graphic === false) {
|
||||
node.style.visibility = "hidden";
|
||||
} else if (style.externalGraphic) {
|
||||
|
||||
if (style.graphicTitle) {
|
||||
node.setAttributeNS(null, "title", style.graphicTitle);
|
||||
//Standards-conformant SVG
|
||||
// Prevent duplicate nodes. See issue https://github.com/openlayers/openlayers/issues/92
|
||||
var titleNode = node.getElementsByTagName("title");
|
||||
if (titleNode.length > 0) {
|
||||
titleNode[0].firstChild.textContent = style.graphicTitle;
|
||||
} else {
|
||||
var label = this.nodeFactory(null, "title");
|
||||
label.textContent = style.graphicTitle;
|
||||
node.appendChild(label);
|
||||
}
|
||||
}
|
||||
if (style.graphicWidth && style.graphicHeight) {
|
||||
node.setAttributeNS(null, "preserveAspectRatio", "none");
|
||||
}
|
||||
var width = style.graphicWidth || style.graphicHeight;
|
||||
var height = style.graphicHeight || style.graphicWidth;
|
||||
width = width ? width : style.pointRadius*2;
|
||||
height = height ? height : style.pointRadius*2;
|
||||
width *= resolution;
|
||||
height *= resolution;
|
||||
|
||||
var xOffset = (style.graphicXOffset != undefined) ?
|
||||
style.graphicXOffset * resolution : -(0.5 * width);
|
||||
var yOffset = (style.graphicYOffset != undefined) ?
|
||||
style.graphicYOffset * resolution : -(0.5 * height);
|
||||
|
||||
var opacity = style.graphicOpacity || style.fillOpacity;
|
||||
|
||||
node.setAttributeNS(null, "x", node._x + xOffset);
|
||||
node.setAttributeNS(null, "y", node._y + yOffset);
|
||||
node.setAttributeNS(null, "width", width);
|
||||
node.setAttributeNS(null, "height", height);
|
||||
node.setAttributeNS(this.xlinkns, "href", style.externalGraphic);
|
||||
node.setAttributeNS(null, "style", "opacity: "+opacity);
|
||||
node.onclick = OpenLayers.Renderer.SVG2.preventDefault;
|
||||
} else if (this.isComplexSymbol(style.graphicName)) {
|
||||
// the symbol viewBox is three times as large as the symbol
|
||||
var offset = style.pointRadius * 3 * resolution;
|
||||
var size = offset * 2;
|
||||
var src = this.importSymbol(style.graphicName);
|
||||
widthFactor = this.symbolMetrics[src.id].size * 3 / size * resolution;
|
||||
|
||||
// remove the node from the dom before we modify it. This
|
||||
// prevents various rendering issues in Safari and FF
|
||||
var parent = node.parentNode;
|
||||
var nextSibling = node.nextSibling;
|
||||
if(parent) {
|
||||
parent.removeChild(node);
|
||||
}
|
||||
|
||||
// The more appropriate way to implement this would be use/defs,
|
||||
// but due to various issues in several browsers, it is safer to
|
||||
// copy the symbols instead of referencing them.
|
||||
// See e.g. ticket http://trac.osgeo.org/openlayers/ticket/2985
|
||||
// and this email thread
|
||||
// http://osgeo-org.1803224.n2.nabble.com/Select-Control-Ctrl-click-on-Feature-with-a-graphicName-opens-new-browser-window-tc5846039.html
|
||||
node.firstChild && node.removeChild(node.firstChild);
|
||||
node.appendChild(src.firstChild.cloneNode(true));
|
||||
node.setAttributeNS(null, "viewBox", src.getAttributeNS(null, "viewBox"));
|
||||
|
||||
node.setAttributeNS(null, "width", size);
|
||||
node.setAttributeNS(null, "height", size);
|
||||
node.setAttributeNS(null, "x", node._x - offset);
|
||||
node.setAttributeNS(null, "y", node._y - offset);
|
||||
|
||||
// now that the node has all its new properties, insert it
|
||||
// back into the dom where it was
|
||||
if(nextSibling) {
|
||||
parent.insertBefore(node, nextSibling);
|
||||
} else if(parent) {
|
||||
parent.appendChild(node);
|
||||
}
|
||||
} else {
|
||||
node.setAttributeNS(null, "r", style.pointRadius * resolution);
|
||||
}
|
||||
|
||||
var rotation = style.rotation;
|
||||
if (rotation !== undefined || node._rotation !== undefined) {
|
||||
node._rotation = rotation;
|
||||
rotation |= 0;
|
||||
if (node.nodeName !== "svg") {
|
||||
node.setAttributeNS(null, "transform",
|
||||
["rotate(", rotation, node._x, node._y, ")"].join(" ")
|
||||
);
|
||||
} else {
|
||||
var metrics = this.symbolMetrics[src.id];
|
||||
node.firstChild.setAttributeNS(null, "transform",
|
||||
["rotate(", rotation, metrics.x, metrics.y, ")"].join(" ")
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (options.isFilled) {
|
||||
node.setAttributeNS(null, "fill", style.fillColor);
|
||||
node.setAttributeNS(null, "fill-opacity", style.fillOpacity);
|
||||
} else {
|
||||
node.setAttributeNS(null, "fill", "none");
|
||||
}
|
||||
|
||||
if (options.isStroked) {
|
||||
node.setAttributeNS(null, "stroke", style.strokeColor);
|
||||
node.setAttributeNS(null, "stroke-opacity", style.strokeOpacity);
|
||||
node.setAttributeNS(null, "stroke-width", style.strokeWidth * widthFactor);
|
||||
node.setAttributeNS(null, "stroke-linecap", style.strokeLinecap || "round");
|
||||
// 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");
|
||||
style.strokeDashstyle && node.setAttributeNS(null,
|
||||
"stroke-dasharray", this.dashStyle(style, widthFactor));
|
||||
} else {
|
||||
node.setAttributeNS(null, "stroke", "none");
|
||||
}
|
||||
|
||||
if (style.pointerEvents) {
|
||||
node.setAttributeNS(null, "pointer-events", style.pointerEvents);
|
||||
}
|
||||
|
||||
if (style.cursor != null) {
|
||||
node.setAttributeNS(null, "cursor", style.cursor);
|
||||
}
|
||||
|
||||
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;
|
||||
var str = style.strokeDashstyle;
|
||||
switch (str) {
|
||||
case 'solid':
|
||||
return 'none';
|
||||
case 'dot':
|
||||
return [widthFactor, 4 * w].join();
|
||||
case 'dash':
|
||||
return [4 * w, 4 * w].join();
|
||||
case 'dashdot':
|
||||
return [4 * w, 4 * w, widthFactor, 4 * w].join();
|
||||
case 'longdash':
|
||||
return [8 * w, 4 * w].join();
|
||||
case 'longdashdot':
|
||||
return [8 * w, 4 * w, widthFactor, 4 * w].join();
|
||||
default:
|
||||
var parts = OpenLayers.String.trim(str).split(/\s+/g);
|
||||
for (var i=0, ii=parts.length; i<ii; i++) {
|
||||
parts[i] = parts[i] * widthFactor;
|
||||
}
|
||||
return parts.join();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Method: createNode
|
||||
*
|
||||
* Parameters:
|
||||
* type - {String} Kind of node to draw
|
||||
* id - {String} Id for node
|
||||
*
|
||||
* Returns:
|
||||
* {DOMElement} A new node of the given type and id
|
||||
*/
|
||||
createNode: function(type, id) {
|
||||
var node = document.createElementNS(this.xmlns, type);
|
||||
if (id) {
|
||||
node.setAttributeNS(null, "id", id);
|
||||
}
|
||||
return node;
|
||||
},
|
||||
|
||||
/**
|
||||
* Method: nodeTypeCompare
|
||||
*
|
||||
* Parameters:
|
||||
* node - {SVGDomElement} An SVG element
|
||||
* type - {String} Kind of node
|
||||
*
|
||||
* Returns:
|
||||
* {Boolean} Whether or not the specified node is of the specified type
|
||||
*/
|
||||
nodeTypeCompare: function(node, type) {
|
||||
return (type == node.nodeName);
|
||||
},
|
||||
|
||||
/**
|
||||
* Method: createRenderRoot
|
||||
*
|
||||
* Returns:
|
||||
* {DOMElement} The specific render engine's root element
|
||||
*/
|
||||
createRenderRoot: function() {
|
||||
return this.nodeFactory(this.container.id + "_svgRoot", "svg");
|
||||
},
|
||||
|
||||
/**
|
||||
* Method: createRoot
|
||||
*
|
||||
* Parameters:
|
||||
* suffix - {String} suffix to append to the id
|
||||
*
|
||||
* Returns:
|
||||
* {DOMElement}
|
||||
*/
|
||||
createRoot: function(suffix) {
|
||||
return this.nodeFactory(this.container.id + suffix, "g");
|
||||
},
|
||||
|
||||
/**
|
||||
* Method: createDefs
|
||||
*
|
||||
* Returns:
|
||||
* {DOMElement} The element to which we'll add the symbol definitions
|
||||
*/
|
||||
createDefs: function() {
|
||||
var defs = this.nodeFactory(this.container.id + "_defs", "defs");
|
||||
this.rendererRoot.appendChild(defs);
|
||||
return defs;
|
||||
},
|
||||
|
||||
/**************************************
|
||||
* *
|
||||
* GEOMETRY DRAWING FUNCTIONS *
|
||||
* *
|
||||
**************************************/
|
||||
|
||||
/**
|
||||
* Method: drawPoint
|
||||
* This method is only called by the renderer itself.
|
||||
*
|
||||
* Parameters:
|
||||
* node - {DOMElement}
|
||||
* geometry - {<OpenLayers.Geometry>}
|
||||
*
|
||||
* Returns:
|
||||
* {DOMElement} or false if the renderer could not draw the point
|
||||
*/
|
||||
drawPoint: function(node, geometry) {
|
||||
return this.drawCircle(node, geometry, 1);
|
||||
},
|
||||
|
||||
/**
|
||||
* Method: drawCircle
|
||||
* This method is only called by the renderer itself.
|
||||
*
|
||||
* Parameters:
|
||||
* node - {DOMElement}
|
||||
* geometry - {<OpenLayers.Geometry>}
|
||||
* radius - {Float}
|
||||
*
|
||||
* Returns:
|
||||
* {DOMElement} or false if the renderer could not draw the circle
|
||||
*/
|
||||
drawCircle: function(node, geometry, radius) {
|
||||
var x = geometry.x;
|
||||
var y = -geometry.y;
|
||||
node.setAttributeNS(null, "cx", x);
|
||||
node.setAttributeNS(null, "cy", y);
|
||||
node._x = x;
|
||||
node._y = y;
|
||||
node._radius = radius;
|
||||
return node;
|
||||
},
|
||||
|
||||
/**
|
||||
* Method: drawLineString
|
||||
* This method is only called by the renderer itself.
|
||||
*
|
||||
* Parameters:
|
||||
* node - {DOMElement}
|
||||
* geometry - {<OpenLayers.Geometry>}
|
||||
*
|
||||
* Returns:
|
||||
* {DOMElement} or null if the renderer could not draw all components of
|
||||
* the linestring, or false if nothing could be drawn
|
||||
*/
|
||||
drawLineString: function(node, geometry) {
|
||||
var path = this.getComponentsString(geometry.components);
|
||||
node.setAttributeNS(null, "points", path);
|
||||
return node;
|
||||
},
|
||||
|
||||
/**
|
||||
* Method: drawLinearRing
|
||||
* This method is only called by the renderer itself.
|
||||
*
|
||||
* Parameters:
|
||||
* node - {DOMElement}
|
||||
* geometry - {<OpenLayers.Geometry>}
|
||||
*
|
||||
* Returns:
|
||||
* {DOMElement} or null if the renderer could not draw all components
|
||||
* of the linear ring, or false if nothing could be drawn
|
||||
*/
|
||||
drawLinearRing: function(node, geometry) {
|
||||
var path = this.getComponentsString(geometry.components);
|
||||
node.setAttributeNS(null, "points", path);
|
||||
return node;
|
||||
},
|
||||
|
||||
/**
|
||||
* Method: drawPolygon
|
||||
* This method is only called by the renderer itself.
|
||||
*
|
||||
* Parameters:
|
||||
* node - {DOMElement}
|
||||
* geometry - {<OpenLayers.Geometry>}
|
||||
*
|
||||
* Returns:
|
||||
* {DOMElement} or null if the renderer could not draw all components
|
||||
* of the polygon, or false if nothing could be drawn
|
||||
*/
|
||||
drawPolygon: function(node, geometry) {
|
||||
var d = [];
|
||||
var draw = true;
|
||||
var complete = true;
|
||||
var linearRingResult, path;
|
||||
for (var j=0, len=geometry.components.length; j<len; j++) {
|
||||
d.push("M");
|
||||
path = this.getComponentsString(
|
||||
geometry.components[j].components, " ");
|
||||
d.push(path);
|
||||
}
|
||||
d.push("z");
|
||||
node.setAttributeNS(null, "d", d.join(" "));
|
||||
node.setAttributeNS(null, "fill-rule", "evenodd");
|
||||
return node;
|
||||
},
|
||||
|
||||
/**
|
||||
* Method: drawRectangle
|
||||
* This method is only called by the renderer itself.
|
||||
*
|
||||
* Parameters:
|
||||
* node - {DOMElement}
|
||||
* geometry - {<OpenLayers.Geometry>}
|
||||
*
|
||||
* Returns:
|
||||
* {DOMElement} or false if the renderer could not draw the rectangle
|
||||
*/
|
||||
drawRectangle: function(node, geometry) {
|
||||
node.setAttributeNS(null, "x", geometry.x);
|
||||
node.setAttributeNS(null, "y", -geometry.y);
|
||||
node.setAttributeNS(null, "width", geometry.width);
|
||||
node.setAttributeNS(null, "height", geometry.height);
|
||||
return node;
|
||||
},
|
||||
|
||||
/**
|
||||
* Method: drawText
|
||||
* Function for drawing text labels.
|
||||
* This method is only called by the renderer itself.
|
||||
*
|
||||
* Parameters:
|
||||
* featureId - {String|DOMElement}
|
||||
* style - {Object}
|
||||
* location - {<OpenLayers.Geometry.Point>}, will be modified inline
|
||||
*
|
||||
* Returns:
|
||||
* {DOMElement} container holding the text label
|
||||
*/
|
||||
drawText: function(featureId, style, location) {
|
||||
var g = OpenLayers.Renderer.NG.prototype.drawText.apply(this, arguments);
|
||||
var text = g.firstChild ||
|
||||
this.nodeFactory(featureId + this.LABEL_ID_SUFFIX + "_text", "text");
|
||||
|
||||
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);
|
||||
}
|
||||
if (style.fontOpacity) {
|
||||
text.setAttributeNS(null, "opacity", style.fontOpacity);
|
||||
}
|
||||
if (style.fontFamily) {
|
||||
text.setAttributeNS(null, "font-family", style.fontFamily);
|
||||
}
|
||||
if (style.fontSize) {
|
||||
text.setAttributeNS(null, "font-size", style.fontSize);
|
||||
}
|
||||
if (style.fontWeight) {
|
||||
text.setAttributeNS(null, "font-weight", style.fontWeight);
|
||||
}
|
||||
if (style.fontStyle) {
|
||||
text.setAttributeNS(null, "font-style", style.fontStyle);
|
||||
}
|
||||
if (style.labelSelect === true) {
|
||||
text.setAttributeNS(null, "pointer-events", "visible");
|
||||
text._featureId = featureId;
|
||||
} else {
|
||||
text.setAttributeNS(null, "pointer-events", "none");
|
||||
}
|
||||
var align = style.labelAlign || OpenLayers.Renderer.defaultSymbolizer.labelAlign;
|
||||
text.setAttributeNS(null, "text-anchor",
|
||||
OpenLayers.Renderer.SVG2.LABEL_ALIGN[align[0]] || "middle");
|
||||
|
||||
if (OpenLayers.IS_GECKO === true) {
|
||||
text.setAttributeNS(null, "dominant-baseline",
|
||||
OpenLayers.Renderer.SVG2.LABEL_ALIGN[align[1]] || "central");
|
||||
}
|
||||
|
||||
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;
|
||||
},
|
||||
|
||||
/**
|
||||
* Method: getComponentString
|
||||
*
|
||||
* Parameters:
|
||||
* components - {Array(<OpenLayers.Geometry.Point>)} Array of points
|
||||
* separator - {String} character between coordinate pairs. Defaults to ","
|
||||
*
|
||||
* Returns:
|
||||
* {Object} hash with properties "path" (the string created from the
|
||||
* components and "complete" (false if the renderer was unable to
|
||||
* draw all components)
|
||||
*/
|
||||
getComponentsString: function(components, separator) {
|
||||
var len = components.length;
|
||||
var strings = new Array(len);
|
||||
for (var i=0; i<len; i++) {
|
||||
strings[i] = this.getShortString(components[i]);
|
||||
}
|
||||
|
||||
return strings.join(separator || ",");
|
||||
},
|
||||
|
||||
/**
|
||||
* Method: getShortString
|
||||
*
|
||||
* Parameters:
|
||||
* point - {<OpenLayers.Geometry.Point>}
|
||||
*
|
||||
* Returns:
|
||||
* {String} or false if point is outside the valid range
|
||||
*/
|
||||
getShortString: function(point) {
|
||||
return point.x + "," + (-point.y);
|
||||
},
|
||||
|
||||
/**
|
||||
* Method: importSymbol
|
||||
* add a new symbol definition from the rendererer's symbol hash
|
||||
*
|
||||
* Parameters:
|
||||
* graphicName - {String} name of the symbol to import
|
||||
*
|
||||
* Returns:
|
||||
* {DOMElement} - 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
|
||||
var existing = document.getElementById(id);
|
||||
if (existing != null) {
|
||||
return existing;
|
||||
}
|
||||
|
||||
var symbol = OpenLayers.Renderer.symbol[graphicName];
|
||||
if (!symbol) {
|
||||
throw new Error(graphicName + ' is not a valid symbol name');
|
||||
}
|
||||
|
||||
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, len=symbol.length; i<len; 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.push(x, ",", y);
|
||||
}
|
||||
|
||||
node.setAttributeNS(null, "points", points.join(" "));
|
||||
|
||||
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.symbolMetrics[id] = {
|
||||
size: Math.max(width, height),
|
||||
x: symbolExtent.getCenterLonLat().lon,
|
||||
y: symbolExtent.getCenterLonLat().lat
|
||||
};
|
||||
|
||||
this.defs.appendChild(symbolNode);
|
||||
return symbolNode;
|
||||
},
|
||||
|
||||
/**
|
||||
* Method: getFeatureIdFromEvent
|
||||
*
|
||||
* Parameters:
|
||||
* evt - {Object} An <OpenLayers.Event> object
|
||||
*
|
||||
* Returns:
|
||||
* {String} A feature id or undefined.
|
||||
*/
|
||||
getFeatureIdFromEvent: function(evt) {
|
||||
var featureId = OpenLayers.Renderer.Elements.prototype.getFeatureIdFromEvent.apply(this, arguments);
|
||||
if(!featureId) {
|
||||
var target = evt.target;
|
||||
featureId = target.parentNode && target != this.rendererRoot ?
|
||||
target.parentNode._featureId : undefined;
|
||||
}
|
||||
return featureId;
|
||||
},
|
||||
|
||||
CLASS_NAME: "OpenLayers.Renderer.SVG2"
|
||||
});
|
||||
|
||||
/**
|
||||
* Constant: OpenLayers.Renderer.SVG2.LABEL_ALIGN
|
||||
* {Object}
|
||||
*/
|
||||
OpenLayers.Renderer.SVG2.LABEL_ALIGN = {
|
||||
"l": "start",
|
||||
"r": "end",
|
||||
"b": "bottom",
|
||||
"t": "hanging"
|
||||
};
|
||||
|
||||
/**
|
||||
* Constant: OpenLayers.Renderer.SVG2.LABEL_VSHIFT
|
||||
* {Object}
|
||||
*/
|
||||
OpenLayers.Renderer.SVG2.LABEL_VSHIFT = {
|
||||
// according to
|
||||
// http://www.w3.org/Graphics/SVG/Test/20061213/htmlObjectHarness/full-text-align-02-b.html
|
||||
// a baseline-shift of -70% shifts the text exactly from the
|
||||
// bottom to the top of the baseline, so -35% moves the text to
|
||||
// the center of the baseline.
|
||||
"t": "-70%",
|
||||
"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
|
||||
* ctrl-click) from being executed for externalGraphic and graphicName symbols
|
||||
*/
|
||||
OpenLayers.Renderer.SVG2.preventDefault = function(e) {
|
||||
e.preventDefault && e.preventDefault();
|
||||
};
|
||||
@@ -21,6 +21,7 @@
|
||||
* @requires OpenLayers/Format/WKT.js
|
||||
* @requires OpenLayers/Format/XML.js
|
||||
* @requires OpenLayers/Geometry.js
|
||||
* @requires OpenLayers/Renderer/NG.js
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -4976,3 +4977,792 @@ OpenLayers.Geometry.Rectangle = OpenLayers.Class(OpenLayers.Geometry, {
|
||||
|
||||
CLASS_NAME: "OpenLayers.Geometry.Rectangle"
|
||||
});
|
||||
|
||||
/**
|
||||
* Class: OpenLayers.Renderer.SVG2
|
||||
*
|
||||
* Inherits from:
|
||||
* - <OpenLayers.Renderer.NG>
|
||||
*/
|
||||
OpenLayers.Renderer.SVG2 = OpenLayers.Class(OpenLayers.Renderer.NG, {
|
||||
|
||||
/**
|
||||
* Property: xmlns
|
||||
* {String}
|
||||
*/
|
||||
xmlns: "http://www.w3.org/2000/svg",
|
||||
|
||||
/**
|
||||
* Property: xlinkns
|
||||
* {String}
|
||||
*/
|
||||
xlinkns: "http://www.w3.org/1999/xlink",
|
||||
|
||||
/**
|
||||
* Property: symbolMetrics
|
||||
* {Object} Cache for symbol metrics according to their svg coordinate
|
||||
* space. This is an object keyed by the symbol's id, and values are
|
||||
* an object with size, x and y properties.
|
||||
*/
|
||||
symbolMetrics: null,
|
||||
|
||||
/**
|
||||
* Constant: labelNodeType
|
||||
* {String} The node type for text label containers.
|
||||
*/
|
||||
labelNodeType: "g",
|
||||
|
||||
/**
|
||||
* Constructor: OpenLayers.Renderer.SVG2
|
||||
*
|
||||
* Parameters:
|
||||
* containerID - {String}
|
||||
*/
|
||||
initialize: function(containerID) {
|
||||
if (!this.supported()) {
|
||||
return;
|
||||
}
|
||||
OpenLayers.Renderer.Elements.prototype.initialize.apply(this,
|
||||
arguments);
|
||||
|
||||
this.symbolMetrics = {};
|
||||
},
|
||||
|
||||
/**
|
||||
* APIMethod: supported
|
||||
*
|
||||
* Returns:
|
||||
* {Boolean} Whether or not the browser supports the SVG renderer
|
||||
*/
|
||||
supported: function() {
|
||||
var svgFeature = "http://www.w3.org/TR/SVG11/feature#";
|
||||
return (document.implementation &&
|
||||
(document.implementation.hasFeature("org.w3c.svg", "1.0") ||
|
||||
document.implementation.hasFeature(svgFeature + "SVG", "1.1") ||
|
||||
document.implementation.hasFeature(svgFeature + "BasicStructure", "1.1") ));
|
||||
},
|
||||
|
||||
/**
|
||||
* Method: updateDimensions
|
||||
*
|
||||
* Parameters:
|
||||
* zoomChanged - {Boolean}
|
||||
*/
|
||||
updateDimensions: function(zoomChanged) {
|
||||
OpenLayers.Renderer.NG.prototype.updateDimensions.apply(this, arguments);
|
||||
|
||||
var res = this.getResolution();
|
||||
|
||||
var width = this.extent.getWidth();
|
||||
var height = this.extent.getHeight();
|
||||
|
||||
var extentString = [
|
||||
this.extent.left,
|
||||
-this.extent.top,
|
||||
width,
|
||||
height
|
||||
].join(" ");
|
||||
this.rendererRoot.setAttributeNS(null, "viewBox", extentString);
|
||||
this.rendererRoot.setAttributeNS(null, "width", width / res);
|
||||
this.rendererRoot.setAttributeNS(null, "height", height / res);
|
||||
|
||||
if (zoomChanged === true) {
|
||||
// update styles for the new resolution
|
||||
var i, len;
|
||||
var nodes = this.vectorRoot.childNodes;
|
||||
for (i=0, len=nodes.length; i<len; ++i) {
|
||||
this.setStyle(nodes[i]);
|
||||
}
|
||||
var textNodes = this.textRoot.childNodes;
|
||||
var label;
|
||||
for (i=0, len=textNodes.length; i<len; ++i) {
|
||||
label = textNodes[i];
|
||||
this.drawText(label, label._style,
|
||||
new OpenLayers.Geometry.Point(label._x, label._y)
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Method: getNodeType
|
||||
*
|
||||
* Parameters:
|
||||
* geometry - {<OpenLayers.Geometry>}
|
||||
* style - {Object}
|
||||
*
|
||||
* Returns:
|
||||
* {String} The corresponding node type for the specified geometry
|
||||
*/
|
||||
getNodeType: function(geometry, style) {
|
||||
var nodeType = null;
|
||||
switch (geometry.CLASS_NAME) {
|
||||
case "OpenLayers.Geometry.Point":
|
||||
if (style.externalGraphic) {
|
||||
nodeType = "image";
|
||||
} else if (this.isComplexSymbol(style.graphicName)) {
|
||||
nodeType = "svg";
|
||||
} else {
|
||||
nodeType = "circle";
|
||||
}
|
||||
break;
|
||||
case "OpenLayers.Geometry.Rectangle":
|
||||
nodeType = "rect";
|
||||
break;
|
||||
case "OpenLayers.Geometry.LineString":
|
||||
nodeType = "polyline";
|
||||
break;
|
||||
case "OpenLayers.Geometry.LinearRing":
|
||||
nodeType = "polygon";
|
||||
break;
|
||||
case "OpenLayers.Geometry.Polygon":
|
||||
case "OpenLayers.Geometry.Curve":
|
||||
nodeType = "path";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return nodeType;
|
||||
},
|
||||
|
||||
/**
|
||||
* Method: setStyle
|
||||
* Use to set all the style attributes to a SVG node.
|
||||
*
|
||||
* Takes care to adjust stroke width and point radius to be
|
||||
* resolution-relative
|
||||
*
|
||||
* Parameters:
|
||||
* node - {SVGDomElement} An SVG element to decorate
|
||||
* style - {Object}
|
||||
* options - {Object} Currently supported options include
|
||||
* 'isFilled' {Boolean} and
|
||||
* 'isStroked' {Boolean}
|
||||
*/
|
||||
setStyle: function(node, style, options) {
|
||||
style = style || node._style;
|
||||
options = options || node._options;
|
||||
var resolution = this.getResolution();
|
||||
var r = node._radius;
|
||||
var widthFactor = resolution;
|
||||
if (node._geometryClass == "OpenLayers.Geometry.Point" && r) {
|
||||
node.style.visibility = "";
|
||||
if (style.graphic === false) {
|
||||
node.style.visibility = "hidden";
|
||||
} else if (style.externalGraphic) {
|
||||
|
||||
if (style.graphicTitle) {
|
||||
node.setAttributeNS(null, "title", style.graphicTitle);
|
||||
//Standards-conformant SVG
|
||||
// Prevent duplicate nodes. See issue https://github.com/openlayers/openlayers/issues/92
|
||||
var titleNode = node.getElementsByTagName("title");
|
||||
if (titleNode.length > 0) {
|
||||
titleNode[0].firstChild.textContent = style.graphicTitle;
|
||||
} else {
|
||||
var label = this.nodeFactory(null, "title");
|
||||
label.textContent = style.graphicTitle;
|
||||
node.appendChild(label);
|
||||
}
|
||||
}
|
||||
if (style.graphicWidth && style.graphicHeight) {
|
||||
node.setAttributeNS(null, "preserveAspectRatio", "none");
|
||||
}
|
||||
var width = style.graphicWidth || style.graphicHeight;
|
||||
var height = style.graphicHeight || style.graphicWidth;
|
||||
width = width ? width : style.pointRadius*2;
|
||||
height = height ? height : style.pointRadius*2;
|
||||
width *= resolution;
|
||||
height *= resolution;
|
||||
|
||||
var xOffset = (style.graphicXOffset != undefined) ?
|
||||
style.graphicXOffset * resolution : -(0.5 * width);
|
||||
var yOffset = (style.graphicYOffset != undefined) ?
|
||||
style.graphicYOffset * resolution : -(0.5 * height);
|
||||
|
||||
var opacity = style.graphicOpacity || style.fillOpacity;
|
||||
|
||||
node.setAttributeNS(null, "x", node._x + xOffset);
|
||||
node.setAttributeNS(null, "y", node._y + yOffset);
|
||||
node.setAttributeNS(null, "width", width);
|
||||
node.setAttributeNS(null, "height", height);
|
||||
node.setAttributeNS(this.xlinkns, "href", style.externalGraphic);
|
||||
node.setAttributeNS(null, "style", "opacity: "+opacity);
|
||||
node.onclick = OpenLayers.Renderer.SVG2.preventDefault;
|
||||
} else if (this.isComplexSymbol(style.graphicName)) {
|
||||
// the symbol viewBox is three times as large as the symbol
|
||||
var offset = style.pointRadius * 3 * resolution;
|
||||
var size = offset * 2;
|
||||
var src = this.importSymbol(style.graphicName);
|
||||
widthFactor = this.symbolMetrics[src.id].size * 3 / size * resolution;
|
||||
|
||||
// remove the node from the dom before we modify it. This
|
||||
// prevents various rendering issues in Safari and FF
|
||||
var parent = node.parentNode;
|
||||
var nextSibling = node.nextSibling;
|
||||
if(parent) {
|
||||
parent.removeChild(node);
|
||||
}
|
||||
|
||||
// The more appropriate way to implement this would be use/defs,
|
||||
// but due to various issues in several browsers, it is safer to
|
||||
// copy the symbols instead of referencing them.
|
||||
// See e.g. ticket http://trac.osgeo.org/openlayers/ticket/2985
|
||||
// and this email thread
|
||||
// http://osgeo-org.1803224.n2.nabble.com/Select-Control-Ctrl-click-on-Feature-with-a-graphicName-opens-new-browser-window-tc5846039.html
|
||||
node.firstChild && node.removeChild(node.firstChild);
|
||||
node.appendChild(src.firstChild.cloneNode(true));
|
||||
node.setAttributeNS(null, "viewBox", src.getAttributeNS(null, "viewBox"));
|
||||
|
||||
node.setAttributeNS(null, "width", size);
|
||||
node.setAttributeNS(null, "height", size);
|
||||
node.setAttributeNS(null, "x", node._x - offset);
|
||||
node.setAttributeNS(null, "y", node._y - offset);
|
||||
|
||||
// now that the node has all its new properties, insert it
|
||||
// back into the dom where it was
|
||||
if(nextSibling) {
|
||||
parent.insertBefore(node, nextSibling);
|
||||
} else if(parent) {
|
||||
parent.appendChild(node);
|
||||
}
|
||||
} else {
|
||||
node.setAttributeNS(null, "r", style.pointRadius * resolution);
|
||||
}
|
||||
|
||||
var rotation = style.rotation;
|
||||
if (rotation !== undefined || node._rotation !== undefined) {
|
||||
node._rotation = rotation;
|
||||
rotation |= 0;
|
||||
if (node.nodeName !== "svg") {
|
||||
node.setAttributeNS(null, "transform",
|
||||
["rotate(", rotation, node._x, node._y, ")"].join(" ")
|
||||
);
|
||||
} else {
|
||||
var metrics = this.symbolMetrics[src.id];
|
||||
node.firstChild.setAttributeNS(null, "transform",
|
||||
["rotate(", rotation, metrics.x, metrics.y, ")"].join(" ")
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (options.isFilled) {
|
||||
node.setAttributeNS(null, "fill", style.fillColor);
|
||||
node.setAttributeNS(null, "fill-opacity", style.fillOpacity);
|
||||
} else {
|
||||
node.setAttributeNS(null, "fill", "none");
|
||||
}
|
||||
|
||||
if (options.isStroked) {
|
||||
node.setAttributeNS(null, "stroke", style.strokeColor);
|
||||
node.setAttributeNS(null, "stroke-opacity", style.strokeOpacity);
|
||||
node.setAttributeNS(null, "stroke-width", style.strokeWidth * widthFactor);
|
||||
node.setAttributeNS(null, "stroke-linecap", style.strokeLinecap || "round");
|
||||
// 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");
|
||||
style.strokeDashstyle && node.setAttributeNS(null,
|
||||
"stroke-dasharray", this.dashStyle(style, widthFactor));
|
||||
} else {
|
||||
node.setAttributeNS(null, "stroke", "none");
|
||||
}
|
||||
|
||||
if (style.pointerEvents) {
|
||||
node.setAttributeNS(null, "pointer-events", style.pointerEvents);
|
||||
}
|
||||
|
||||
if (style.cursor != null) {
|
||||
node.setAttributeNS(null, "cursor", style.cursor);
|
||||
}
|
||||
|
||||
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;
|
||||
var str = style.strokeDashstyle;
|
||||
switch (str) {
|
||||
case 'solid':
|
||||
return 'none';
|
||||
case 'dot':
|
||||
return [widthFactor, 4 * w].join();
|
||||
case 'dash':
|
||||
return [4 * w, 4 * w].join();
|
||||
case 'dashdot':
|
||||
return [4 * w, 4 * w, widthFactor, 4 * w].join();
|
||||
case 'longdash':
|
||||
return [8 * w, 4 * w].join();
|
||||
case 'longdashdot':
|
||||
return [8 * w, 4 * w, widthFactor, 4 * w].join();
|
||||
default:
|
||||
var parts = OpenLayers.String.trim(str).split(/\s+/g);
|
||||
for (var i=0, ii=parts.length; i<ii; i++) {
|
||||
parts[i] = parts[i] * widthFactor;
|
||||
}
|
||||
return parts.join();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Method: createNode
|
||||
*
|
||||
* Parameters:
|
||||
* type - {String} Kind of node to draw
|
||||
* id - {String} Id for node
|
||||
*
|
||||
* Returns:
|
||||
* {DOMElement} A new node of the given type and id
|
||||
*/
|
||||
createNode: function(type, id) {
|
||||
var node = document.createElementNS(this.xmlns, type);
|
||||
if (id) {
|
||||
node.setAttributeNS(null, "id", id);
|
||||
}
|
||||
return node;
|
||||
},
|
||||
|
||||
/**
|
||||
* Method: nodeTypeCompare
|
||||
*
|
||||
* Parameters:
|
||||
* node - {SVGDomElement} An SVG element
|
||||
* type - {String} Kind of node
|
||||
*
|
||||
* Returns:
|
||||
* {Boolean} Whether or not the specified node is of the specified type
|
||||
*/
|
||||
nodeTypeCompare: function(node, type) {
|
||||
return (type == node.nodeName);
|
||||
},
|
||||
|
||||
/**
|
||||
* Method: createRenderRoot
|
||||
*
|
||||
* Returns:
|
||||
* {DOMElement} The specific render engine's root element
|
||||
*/
|
||||
createRenderRoot: function() {
|
||||
return this.nodeFactory(this.container.id + "_svgRoot", "svg");
|
||||
},
|
||||
|
||||
/**
|
||||
* Method: createRoot
|
||||
*
|
||||
* Parameters:
|
||||
* suffix - {String} suffix to append to the id
|
||||
*
|
||||
* Returns:
|
||||
* {DOMElement}
|
||||
*/
|
||||
createRoot: function(suffix) {
|
||||
return this.nodeFactory(this.container.id + suffix, "g");
|
||||
},
|
||||
|
||||
/**
|
||||
* Method: createDefs
|
||||
*
|
||||
* Returns:
|
||||
* {DOMElement} The element to which we'll add the symbol definitions
|
||||
*/
|
||||
createDefs: function() {
|
||||
var defs = this.nodeFactory(this.container.id + "_defs", "defs");
|
||||
this.rendererRoot.appendChild(defs);
|
||||
return defs;
|
||||
},
|
||||
|
||||
/**************************************
|
||||
* *
|
||||
* GEOMETRY DRAWING FUNCTIONS *
|
||||
* *
|
||||
**************************************/
|
||||
|
||||
/**
|
||||
* Method: drawPoint
|
||||
* This method is only called by the renderer itself.
|
||||
*
|
||||
* Parameters:
|
||||
* node - {DOMElement}
|
||||
* geometry - {<OpenLayers.Geometry>}
|
||||
*
|
||||
* Returns:
|
||||
* {DOMElement} or false if the renderer could not draw the point
|
||||
*/
|
||||
drawPoint: function(node, geometry) {
|
||||
return this.drawCircle(node, geometry, 1);
|
||||
},
|
||||
|
||||
/**
|
||||
* Method: drawCircle
|
||||
* This method is only called by the renderer itself.
|
||||
*
|
||||
* Parameters:
|
||||
* node - {DOMElement}
|
||||
* geometry - {<OpenLayers.Geometry>}
|
||||
* radius - {Float}
|
||||
*
|
||||
* Returns:
|
||||
* {DOMElement} or false if the renderer could not draw the circle
|
||||
*/
|
||||
drawCircle: function(node, geometry, radius) {
|
||||
var x = geometry.x;
|
||||
var y = -geometry.y;
|
||||
node.setAttributeNS(null, "cx", x);
|
||||
node.setAttributeNS(null, "cy", y);
|
||||
node._x = x;
|
||||
node._y = y;
|
||||
node._radius = radius;
|
||||
return node;
|
||||
},
|
||||
|
||||
/**
|
||||
* Method: drawLineString
|
||||
* This method is only called by the renderer itself.
|
||||
*
|
||||
* Parameters:
|
||||
* node - {DOMElement}
|
||||
* geometry - {<OpenLayers.Geometry>}
|
||||
*
|
||||
* Returns:
|
||||
* {DOMElement} or null if the renderer could not draw all components of
|
||||
* the linestring, or false if nothing could be drawn
|
||||
*/
|
||||
drawLineString: function(node, geometry) {
|
||||
var path = this.getComponentsString(geometry.components);
|
||||
node.setAttributeNS(null, "points", path);
|
||||
return node;
|
||||
},
|
||||
|
||||
/**
|
||||
* Method: drawLinearRing
|
||||
* This method is only called by the renderer itself.
|
||||
*
|
||||
* Parameters:
|
||||
* node - {DOMElement}
|
||||
* geometry - {<OpenLayers.Geometry>}
|
||||
*
|
||||
* Returns:
|
||||
* {DOMElement} or null if the renderer could not draw all components
|
||||
* of the linear ring, or false if nothing could be drawn
|
||||
*/
|
||||
drawLinearRing: function(node, geometry) {
|
||||
var path = this.getComponentsString(geometry.components);
|
||||
node.setAttributeNS(null, "points", path);
|
||||
return node;
|
||||
},
|
||||
|
||||
/**
|
||||
* Method: drawPolygon
|
||||
* This method is only called by the renderer itself.
|
||||
*
|
||||
* Parameters:
|
||||
* node - {DOMElement}
|
||||
* geometry - {<OpenLayers.Geometry>}
|
||||
*
|
||||
* Returns:
|
||||
* {DOMElement} or null if the renderer could not draw all components
|
||||
* of the polygon, or false if nothing could be drawn
|
||||
*/
|
||||
drawPolygon: function(node, geometry) {
|
||||
var d = [];
|
||||
var draw = true;
|
||||
var complete = true;
|
||||
var linearRingResult, path;
|
||||
for (var j=0, len=geometry.components.length; j<len; j++) {
|
||||
d.push("M");
|
||||
path = this.getComponentsString(
|
||||
geometry.components[j].components, " ");
|
||||
d.push(path);
|
||||
}
|
||||
d.push("z");
|
||||
node.setAttributeNS(null, "d", d.join(" "));
|
||||
node.setAttributeNS(null, "fill-rule", "evenodd");
|
||||
return node;
|
||||
},
|
||||
|
||||
/**
|
||||
* Method: drawRectangle
|
||||
* This method is only called by the renderer itself.
|
||||
*
|
||||
* Parameters:
|
||||
* node - {DOMElement}
|
||||
* geometry - {<OpenLayers.Geometry>}
|
||||
*
|
||||
* Returns:
|
||||
* {DOMElement} or false if the renderer could not draw the rectangle
|
||||
*/
|
||||
drawRectangle: function(node, geometry) {
|
||||
node.setAttributeNS(null, "x", geometry.x);
|
||||
node.setAttributeNS(null, "y", -geometry.y);
|
||||
node.setAttributeNS(null, "width", geometry.width);
|
||||
node.setAttributeNS(null, "height", geometry.height);
|
||||
return node;
|
||||
},
|
||||
|
||||
/**
|
||||
* Method: drawText
|
||||
* Function for drawing text labels.
|
||||
* This method is only called by the renderer itself.
|
||||
*
|
||||
* Parameters:
|
||||
* featureId - {String|DOMElement}
|
||||
* style - {Object}
|
||||
* location - {<OpenLayers.Geometry.Point>}, will be modified inline
|
||||
*
|
||||
* Returns:
|
||||
* {DOMElement} container holding the text label
|
||||
*/
|
||||
drawText: function(featureId, style, location) {
|
||||
var g = OpenLayers.Renderer.NG.prototype.drawText.apply(this, arguments);
|
||||
var text = g.firstChild ||
|
||||
this.nodeFactory(featureId + this.LABEL_ID_SUFFIX + "_text", "text");
|
||||
|
||||
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);
|
||||
}
|
||||
if (style.fontOpacity) {
|
||||
text.setAttributeNS(null, "opacity", style.fontOpacity);
|
||||
}
|
||||
if (style.fontFamily) {
|
||||
text.setAttributeNS(null, "font-family", style.fontFamily);
|
||||
}
|
||||
if (style.fontSize) {
|
||||
text.setAttributeNS(null, "font-size", style.fontSize);
|
||||
}
|
||||
if (style.fontWeight) {
|
||||
text.setAttributeNS(null, "font-weight", style.fontWeight);
|
||||
}
|
||||
if (style.fontStyle) {
|
||||
text.setAttributeNS(null, "font-style", style.fontStyle);
|
||||
}
|
||||
if (style.labelSelect === true) {
|
||||
text.setAttributeNS(null, "pointer-events", "visible");
|
||||
text._featureId = featureId;
|
||||
} else {
|
||||
text.setAttributeNS(null, "pointer-events", "none");
|
||||
}
|
||||
var align = style.labelAlign || OpenLayers.Renderer.defaultSymbolizer.labelAlign;
|
||||
text.setAttributeNS(null, "text-anchor",
|
||||
OpenLayers.Renderer.SVG2.LABEL_ALIGN[align[0]] || "middle");
|
||||
|
||||
if (OpenLayers.IS_GECKO === true) {
|
||||
text.setAttributeNS(null, "dominant-baseline",
|
||||
OpenLayers.Renderer.SVG2.LABEL_ALIGN[align[1]] || "central");
|
||||
}
|
||||
|
||||
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;
|
||||
},
|
||||
|
||||
/**
|
||||
* Method: getComponentString
|
||||
*
|
||||
* Parameters:
|
||||
* components - {Array(<OpenLayers.Geometry.Point>)} Array of points
|
||||
* separator - {String} character between coordinate pairs. Defaults to ","
|
||||
*
|
||||
* Returns:
|
||||
* {Object} hash with properties "path" (the string created from the
|
||||
* components and "complete" (false if the renderer was unable to
|
||||
* draw all components)
|
||||
*/
|
||||
getComponentsString: function(components, separator) {
|
||||
var len = components.length;
|
||||
var strings = new Array(len);
|
||||
for (var i=0; i<len; i++) {
|
||||
strings[i] = this.getShortString(components[i]);
|
||||
}
|
||||
|
||||
return strings.join(separator || ",");
|
||||
},
|
||||
|
||||
/**
|
||||
* Method: getShortString
|
||||
*
|
||||
* Parameters:
|
||||
* point - {<OpenLayers.Geometry.Point>}
|
||||
*
|
||||
* Returns:
|
||||
* {String} or false if point is outside the valid range
|
||||
*/
|
||||
getShortString: function(point) {
|
||||
return point.x + "," + (-point.y);
|
||||
},
|
||||
|
||||
/**
|
||||
* Method: importSymbol
|
||||
* add a new symbol definition from the rendererer's symbol hash
|
||||
*
|
||||
* Parameters:
|
||||
* graphicName - {String} name of the symbol to import
|
||||
*
|
||||
* Returns:
|
||||
* {DOMElement} - 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
|
||||
var existing = document.getElementById(id);
|
||||
if (existing != null) {
|
||||
return existing;
|
||||
}
|
||||
|
||||
var symbol = OpenLayers.Renderer.symbol[graphicName];
|
||||
if (!symbol) {
|
||||
throw new Error(graphicName + ' is not a valid symbol name');
|
||||
}
|
||||
|
||||
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, len=symbol.length; i<len; 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.push(x, ",", y);
|
||||
}
|
||||
|
||||
node.setAttributeNS(null, "points", points.join(" "));
|
||||
|
||||
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.symbolMetrics[id] = {
|
||||
size: Math.max(width, height),
|
||||
x: symbolExtent.getCenterLonLat().lon,
|
||||
y: symbolExtent.getCenterLonLat().lat
|
||||
};
|
||||
|
||||
this.defs.appendChild(symbolNode);
|
||||
return symbolNode;
|
||||
},
|
||||
|
||||
/**
|
||||
* Method: getFeatureIdFromEvent
|
||||
*
|
||||
* Parameters:
|
||||
* evt - {Object} An <OpenLayers.Event> object
|
||||
*
|
||||
* Returns:
|
||||
* {String} A feature id or undefined.
|
||||
*/
|
||||
getFeatureIdFromEvent: function(evt) {
|
||||
var featureId = OpenLayers.Renderer.Elements.prototype.getFeatureIdFromEvent.apply(this, arguments);
|
||||
if(!featureId) {
|
||||
var target = evt.target;
|
||||
featureId = target.parentNode && target != this.rendererRoot ?
|
||||
target.parentNode._featureId : undefined;
|
||||
}
|
||||
return featureId;
|
||||
},
|
||||
|
||||
CLASS_NAME: "OpenLayers.Renderer.SVG2"
|
||||
});
|
||||
|
||||
/**
|
||||
* Constant: OpenLayers.Renderer.SVG2.LABEL_ALIGN
|
||||
* {Object}
|
||||
*/
|
||||
OpenLayers.Renderer.SVG2.LABEL_ALIGN = {
|
||||
"l": "start",
|
||||
"r": "end",
|
||||
"b": "bottom",
|
||||
"t": "hanging"
|
||||
};
|
||||
|
||||
/**
|
||||
* Constant: OpenLayers.Renderer.SVG2.LABEL_VSHIFT
|
||||
* {Object}
|
||||
*/
|
||||
OpenLayers.Renderer.SVG2.LABEL_VSHIFT = {
|
||||
// according to
|
||||
// http://www.w3.org/Graphics/SVG/Test/20061213/htmlObjectHarness/full-text-align-02-b.html
|
||||
// a baseline-shift of -70% shifts the text exactly from the
|
||||
// bottom to the top of the baseline, so -35% moves the text to
|
||||
// the center of the baseline.
|
||||
"t": "-70%",
|
||||
"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
|
||||
* ctrl-click) from being executed for externalGraphic and graphicName symbols
|
||||
*/
|
||||
OpenLayers.Renderer.SVG2.preventDefault = function(e) {
|
||||
e.preventDefault && e.preventDefault();
|
||||
};
|
||||
|
||||
@@ -723,54 +723,6 @@
|
||||
(-y + customStyle6.graphicYOffset).toFixed().toString(),
|
||||
"graphicYOffset correctly set");
|
||||
}
|
||||
if (layer.renderer.CLASS_NAME == 'OpenLayers.Renderer.SVG2') {
|
||||
feature.style = customStyle1;
|
||||
layer.drawFeature(feature);
|
||||
var resolution = map.getResolution();
|
||||
t.eq(root.firstChild.getAttributeNS(null, 'width'),
|
||||
(2*customStyle1.pointRadius*resolution).toString(),
|
||||
"given a pointRadius, width equals 2*pointRadius");
|
||||
t.eq(root.firstChild.getAttributeNS(null, 'height'),
|
||||
(2*customStyle1.pointRadius*resolution).toString(),
|
||||
"given a pointRadius, height equals 2*pointRadius");
|
||||
feature.style = customStyle2;
|
||||
layer.drawFeature(feature);
|
||||
t.eq(root.firstChild.getAttributeNS(null, 'width'),
|
||||
root.firstChild.getAttributeNS(null, 'height'),
|
||||
"given a graphicWidth, width equals height");
|
||||
t.eq(root.firstChild.getAttributeNS(null, 'width'),
|
||||
(customStyle2.graphicWidth*resolution).toString(),
|
||||
"width is set correctly");
|
||||
feature.style = customStyle3;
|
||||
layer.drawFeature(feature);
|
||||
t.eq(root.firstChild.getAttributeNS(null, 'height'),
|
||||
root.firstChild.getAttributeNS(null, 'width'),
|
||||
"given a graphicHeight, height equals width");
|
||||
t.eq(root.firstChild.getAttributeNS(null, 'height'),
|
||||
(customStyle3.graphicHeight*resolution).toString(),
|
||||
"height is set correctly");
|
||||
feature.style = customStyle4;
|
||||
layer.drawFeature(feature);
|
||||
t.eq(root.firstChild.getAttributeNS(null, 'height'),
|
||||
(customStyle4.graphicHeight*resolution).toString(),
|
||||
"given graphicHeight and graphicWidth, both are set: height");
|
||||
t.eq(root.firstChild.getAttributeNS(null, 'width'),
|
||||
(customStyle4.graphicWidth*resolution).toString(),
|
||||
"given graphicHeight and graphicWidth, both are set: width");
|
||||
feature.style = customStyle5;
|
||||
layer.drawFeature(feature);
|
||||
t.eq(root.firstChild.getAttributeNS(null, 'style'),
|
||||
'opacity: '+customStyle5.graphicOpacity.toString()+((OpenLayers.Util.getBrowserName() == "opera" || OpenLayers.Util.getBrowserName() == "safari") ? "" : ';'),
|
||||
"graphicOpacity correctly set");
|
||||
feature.style = customStyle6;
|
||||
layer.drawFeature(feature);
|
||||
t.eq(root.firstChild.getAttributeNS(null, 'x'),
|
||||
(geometryX + customStyle6.graphicXOffset*resolution).toString(),
|
||||
"graphicXOffset correctly set");
|
||||
t.eq(root.firstChild.getAttributeNS(null, 'y'),
|
||||
(-geometryY + customStyle6.graphicYOffset*resolution).toString(),
|
||||
"graphicYOffset correctly set");
|
||||
}
|
||||
if (layer.renderer.CLASS_NAME == 'OpenLayers.Renderer.VML') {
|
||||
feature.style = customStyle1;
|
||||
layer.drawFeature(feature);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<html>
|
||||
<head>
|
||||
<script src="../OLLoader.js"></script>
|
||||
<script src="../../OLLoader.js"></script>
|
||||
<script src="../../../lib/deprecated.js"></script>
|
||||
<script type="text/javascript">
|
||||
|
||||
var geometry = null, node = null;
|
||||
@@ -202,7 +202,6 @@
|
||||
<li>Renderer/Canvas.html</li>
|
||||
<li>Renderer/Elements.html</li>
|
||||
<li>Renderer/SVG.html</li>
|
||||
<li>Renderer/SVG2.html</li>
|
||||
<li>Renderer/VML.html</li>
|
||||
<li>Request.html</li>
|
||||
<li>Request/XMLHttpRequest.html</li>
|
||||
@@ -245,6 +244,7 @@
|
||||
<li>deprecated/Layer/WMS/Post.html</li>
|
||||
<li>deprecated/Protocol/SQL.html</li>
|
||||
<li>deprecated/Protocol/SQL/Gears.html</li>
|
||||
<li>deprecated/Renderer/SVG2.html</li>
|
||||
<li>deprecated/Layer/Yahoo.html</li>
|
||||
<li>deprecated/Tile/WFS.html</li>
|
||||
</ul>
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" >
|
||||
<link rel="stylesheet" href="../../theme/default/style.css" type="text/css" />
|
||||
<style type="text/css">
|
||||
#map {
|
||||
width: 512px;
|
||||
height: 512px;
|
||||
border: 1px solid gray;
|
||||
}
|
||||
</style>
|
||||
<title>SVG2 coordinate range check</title>
|
||||
<script type="text/javascript" src="../../lib/OpenLayers.js"></script>
|
||||
<script>
|
||||
|
||||
var WGS84 = new OpenLayers.Projection("EPSG:4326");
|
||||
var Mercator = new OpenLayers.Projection("EPSG:900913");
|
||||
var wkt = new OpenLayers.Format.WKT({ internalProjection: Mercator, externalProjection: WGS84 });
|
||||
|
||||
function init() {
|
||||
var externalGraphic, baseURL, baseLayer, layerOptions, hidemessenger;
|
||||
|
||||
var map = new OpenLayers.Map('map', {
|
||||
controls: [
|
||||
new OpenLayers.Control.Navigation(),
|
||||
new OpenLayers.Control.PanZoom(),
|
||||
new OpenLayers.Control.Attribution()
|
||||
],
|
||||
theme: null
|
||||
});
|
||||
|
||||
baseLayer = new OpenLayers.Layer.OSM("OSM");
|
||||
|
||||
var viewLayer = new OpenLayers.Layer.Vector("View Layer", {renderers: ["SVG2"]});
|
||||
map.addLayers([baseLayer, viewLayer]);
|
||||
|
||||
viewLayer.addFeatures([wkt.read("LINESTRING(2.4356174739332 48.816618174539, 2.4313688548536 48.826083884311)")]);
|
||||
var lonLat = new OpenLayers.LonLat( 2.43686, 48.81742) .transform( WGS84, Mercator);
|
||||
map.setCenter (lonLat, 16);
|
||||
}
|
||||
</script>
|
||||
|
||||
<body onload="init()">
|
||||
<div id="map"></div>
|
||||
<p>The map should show a line on top of the OSM layer. If it does not, then
|
||||
either the CSS or the SVG coordinate range is exceeded.</p>
|
||||
<p>This test only works on browsers that support SVG.</p>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user