diff --git a/apidoc_config/Menu.txt b/apidoc_config/Menu.txt index e372a59b09..425c7ebdcd 100644 --- a/apidoc_config/Menu.txt +++ b/apidoc_config/Menu.txt @@ -409,9 +409,7 @@ Group: OpenLayers { File: Renderer (no auto-title, OpenLayers/Renderer.js) File: Canvas (no auto-title, OpenLayers/Renderer/Canvas.js) 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 diff --git a/doc_config/Menu.txt b/doc_config/Menu.txt index edbae8e2e8..14845eac23 100644 --- a/doc_config/Menu.txt +++ b/doc_config/Menu.txt @@ -409,9 +409,7 @@ Group: OpenLayers { File: Renderer (no auto-title, OpenLayers/Renderer.js) File: Canvas (no auto-title, OpenLayers/Renderer/Canvas.js) 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 diff --git a/lib/OpenLayers.js b/lib/OpenLayers.js index 749a14f027..3b6669c9e6 100644 --- a/lib/OpenLayers.js +++ b/lib/OpenLayers.js @@ -257,9 +257,7 @@ "OpenLayers/Geometry/MultiPolygon.js", "OpenLayers/Renderer.js", "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", diff --git a/lib/OpenLayers/Control/Zoom.js b/lib/OpenLayers/Control/Zoom.js index eb212eeb83..589884db7c 100644 --- a/lib/OpenLayers/Control/Zoom.js +++ b/lib/OpenLayers/Control/Zoom.js @@ -62,7 +62,6 @@ OpenLayers.Control.Zoom = OpenLayers.Class(OpenLayers.Control, { links = this.getOrCreateLinks(div), zoomIn = links.zoomIn, zoomOut = links.zoomOut, - bind = OpenLayers.Function.bind, eventsInstance = this.map.events; if (zoomOut.parentNode !== div) { diff --git a/lib/OpenLayers/Layer/Vector.js b/lib/OpenLayers/Layer/Vector.js index 3909920af6..03bd784486 100644 --- a/lib/OpenLayers/Layer/Vector.js +++ b/lib/OpenLayers/Layer/Vector.js @@ -473,49 +473,43 @@ OpenLayers.Layer.Vector = OpenLayers.Class(OpenLayers.Layer, { moveTo: function(bounds, zoomChanged, dragging) { OpenLayers.Layer.prototype.moveTo.apply(this, arguments); - var ng = (OpenLayers.Renderer.NG && this.renderer instanceof OpenLayers.Renderer.NG); - if (ng) { - dragging || this.renderer.updateDimensions(zoomChanged); - } else { - var coordSysUnchanged = true; + var coordSysUnchanged = true; + if (!dragging) { + this.renderer.root.style.visibility = 'hidden'; - if (!dragging) { - this.renderer.root.style.visibility = 'hidden'; + var viewSize = this.map.getSize(), + viewWidth = viewSize.w, + viewHeight = viewSize.h, + offsetLeft = (viewWidth / 2 * this.ratio) - viewWidth / 2, + offsetTop = (viewHeight / 2 * this.ratio) - viewHeight / 2; + offsetLeft += parseInt(this.map.layerContainerDiv.style.left, 10); + offsetLeft = -Math.round(offsetLeft); + offsetTop += parseInt(this.map.layerContainerDiv.style.top, 10); + offsetTop = -Math.round(offsetTop); - var viewSize = this.map.getSize(), - viewWidth = viewSize.w, - viewHeight = viewSize.h, - offsetLeft = (viewWidth / 2 * this.ratio) - viewWidth / 2, - offsetTop = (viewHeight / 2 * this.ratio) - viewHeight / 2; - offsetLeft += parseInt(this.map.layerContainerDiv.style.left, 10); - offsetLeft = -Math.round(offsetLeft); - offsetTop += parseInt(this.map.layerContainerDiv.style.top, 10); - offsetTop = -Math.round(offsetTop); - - this.div.style.left = offsetLeft + 'px'; - this.div.style.top = offsetTop + 'px'; - - var extent = this.map.getExtent().scale(this.ratio); - coordSysUnchanged = this.renderer.setExtent(extent, zoomChanged); + this.div.style.left = offsetLeft + 'px'; + this.div.style.top = offsetTop + 'px'; - this.renderer.root.style.visibility = 'visible'; + var extent = this.map.getExtent().scale(this.ratio); + coordSysUnchanged = this.renderer.setExtent(extent, zoomChanged); - // Force a reflow on gecko based browsers to prevent jump/flicker. - // This seems to happen on only certain configurations; it was originally - // noticed in FF 2.0 and Linux. - if (OpenLayers.IS_GECKO === true) { - this.div.scrollLeft = this.div.scrollLeft; - } + this.renderer.root.style.visibility = 'visible'; + + // Force a reflow on gecko based browsers to prevent jump/flicker. + // This seems to happen on only certain configurations; it was originally + // noticed in FF 2.0 and Linux. + if (OpenLayers.IS_GECKO === true) { + this.div.scrollLeft = this.div.scrollLeft; + } - if(!zoomChanged && coordSysUnchanged) { - for(var i in this.unrenderedFeatures) { - var feature = this.unrenderedFeatures[i]; - this.drawFeature(feature); - } + if (!zoomChanged && coordSysUnchanged) { + for (var i in this.unrenderedFeatures) { + var feature = this.unrenderedFeatures[i]; + this.drawFeature(feature); } } } - if (!this.drawn || (!ng && (zoomChanged || !coordSysUnchanged))) { + if (!this.drawn || zoomChanged || !coordSysUnchanged) { this.drawn = true; var feature; for(var i=0, len=this.features.length; i - */ -OpenLayers.Renderer.NG = OpenLayers.Class(OpenLayers.Renderer.Elements, { - - /** - * Constant: labelNodeType - * {String} The node type for text label containers. To be defined by - * subclasses. - */ - labelNodeType: null, - - /** - * Constructor: OpenLayers.Renderer.NG - * - * Parameters: - * containerID - {String} - * options - {Object} options for this renderer. Supported options are: - * * yOrdering - {Boolean} Whether to use y-ordering - * * zIndexing - {Boolean} Whether to use z-indexing. Will be ignored - * if yOrdering is set to true. - */ - - /** - * Method: updateDimensions - * To be extended by subclasses - here we set positioning related styles - * on HTML elements, subclasses have to do the same for renderer specific - * elements (e.g. viewBox, width and height of the rendererRoot) - * - * Parameters: - * zoomChanged - {Boolean} Has the zoom changed? If so, subclasses may have - * to update feature styles/dimensions. - */ - updateDimensions: function(zoomChanged) { - var mapExtent = this.map.getExtent(); - var renderExtent = mapExtent.scale(3); - this.setExtent(renderExtent, true); - var res = this.getResolution(); - var div = this.rendererRoot.parentNode; - var layerLeft = parseFloat(div.parentNode.style.left); - var layerTop = parseFloat(div.parentNode.style.top); - div.style.left = ((renderExtent.left - mapExtent.left) / res - layerLeft) + "px"; - div.style.top = ((mapExtent.top - renderExtent.top) / res - layerTop) + "px"; - }, - - /** - * Method: resize - */ - setSize: function() { - this.map.getExtent() && this.updateDimensions(); - }, - - /** - * Method: drawFeature - * Draw the feature. The optional style argument can be used - * to override the feature's own style. This method should only - * be called from layer.drawFeature(). - * - * Parameters: - * feature - {} - * style - {} - * - * Returns: - * {Boolean} true if the feature has been drawn completely, false if not, - * undefined if the feature had no geometry - */ - drawFeature: function(feature, style) { - if(style == null) { - style = feature.style; - } - if (feature.geometry) { - var rendered = this.drawGeometry(feature.geometry, style, feature.id); - if(rendered !== false && style.label) { - var location = feature.geometry.getCentroid(); - this.drawText(feature.id, style, location); - } else { - this.removeText(feature.id); - } - return rendered; - } - }, - - /** - * Method: drawText - * Function for drawing text labels. - * This method is only called by the renderer itself. - * - * Parameters: - * featureId - {String|DOMElement} - * style - {Object} - * location - {}, will be modified inline - * - * Returns: - * {DOMElement} container holding the text label (to be populated by - * subclasses) - */ - drawText: function(featureId, style, location) { - var label; - if (typeof featureId !== "string") { - label = featureId; - } else { - label = this.nodeFactory(featureId + this.LABEL_ID_SUFFIX, this.labelNodeType); - label._featureId = featureId; - } - label._style = style; - label._x = location.x; - label._y = location.y; - if(style.labelXOffset || style.labelYOffset) { - var xOffset = isNaN(style.labelXOffset) ? 0 : style.labelXOffset; - var yOffset = isNaN(style.labelYOffset) ? 0 : style.labelYOffset; - var res = this.getResolution(); - location.move(xOffset*res, yOffset*res); - } - - if(label.parentNode !== this.textRoot) { - this.textRoot.appendChild(label); - } - - return label; - }, - - CLASS_NAME: "OpenLayers.Renderer.NG" -}); diff --git a/lib/OpenLayers/Renderer/SVG2.js b/lib/OpenLayers/Renderer/SVG2.js deleted file mode 100644 index 3f64c50ca8..0000000000 --- a/lib/OpenLayers/Renderer/SVG2.js +++ /dev/null @@ -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.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} - * 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} - * - * 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 - {} - * 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 - {} - * - * 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 - {} - * - * 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 - {} - * - * 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} - * - * 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 - {}, 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()} 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} - * - * 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 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(); -}; diff --git a/lib/deprecated.js b/lib/deprecated.js index c22b849216..0f7038c2da 100644 --- a/lib/deprecated.js +++ b/lib/deprecated.js @@ -21,6 +21,7 @@ * @requires OpenLayers/Format/WKT.js * @requires OpenLayers/Format/XML.js * @requires OpenLayers/Geometry.js + * @requires OpenLayers/Renderer/Elements.js */ /** @@ -4976,3 +4977,948 @@ OpenLayers.Geometry.Rectangle = OpenLayers.Class(OpenLayers.Geometry, { CLASS_NAME: "OpenLayers.Geometry.Rectangle" }); + +/** + * Class: OpenLayers.Renderer.NG + * + * Inherits from: + * - + */ +OpenLayers.Renderer.NG = OpenLayers.Class(OpenLayers.Renderer.Elements, { + + /** + * Constant: labelNodeType + * {String} The node type for text label containers. To be defined by + * subclasses. + */ + labelNodeType: null, + + /** + * Constructor: OpenLayers.Renderer.NG + * + * Parameters: + * containerID - {String} + * options - {Object} options for this renderer. Supported options are: + * * yOrdering - {Boolean} Whether to use y-ordering + * * zIndexing - {Boolean} Whether to use z-indexing. Will be ignored + * if yOrdering is set to true. + */ + + /** + * Method: updateDimensions + * To be extended by subclasses - here we set positioning related styles + * on HTML elements, subclasses have to do the same for renderer specific + * elements (e.g. viewBox, width and height of the rendererRoot) + * + * Parameters: + * zoomChanged - {Boolean} Has the zoom changed? If so, subclasses may have + * to update feature styles/dimensions. + */ + updateDimensions: function(zoomChanged) { + var mapExtent = this.map.getExtent(); + var renderExtent = mapExtent.scale(3); + this.setExtent(renderExtent, true); + var res = this.getResolution(); + var div = this.rendererRoot.parentNode; + var layerLeft = parseFloat(div.parentNode.style.left); + var layerTop = parseFloat(div.parentNode.style.top); + div.style.left = ((renderExtent.left - mapExtent.left) / res - layerLeft) + "px"; + div.style.top = ((mapExtent.top - renderExtent.top) / res - layerTop) + "px"; + }, + + /** + * Method: resize + */ + setSize: function() { + this.map.getExtent() && this.updateDimensions(); + }, + + /** + * Method: drawFeature + * Draw the feature. The optional style argument can be used + * to override the feature's own style. This method should only + * be called from layer.drawFeature(). + * + * Parameters: + * feature - {} + * style - {} + * + * Returns: + * {Boolean} true if the feature has been drawn completely, false if not, + * undefined if the feature had no geometry + */ + drawFeature: function(feature, style) { + if(style == null) { + style = feature.style; + } + if (feature.geometry) { + var rendered = this.drawGeometry(feature.geometry, style, feature.id); + if(rendered !== false && style.label) { + var location = feature.geometry.getCentroid(); + this.drawText(feature.id, style, location); + } else { + this.removeText(feature.id); + } + return rendered; + } + }, + + /** + * Method: drawText + * Function for drawing text labels. + * This method is only called by the renderer itself. + * + * Parameters: + * featureId - {String|DOMElement} + * style - {Object} + * location - {}, will be modified inline + * + * Returns: + * {DOMElement} container holding the text label (to be populated by + * subclasses) + */ + drawText: function(featureId, style, location) { + var label; + if (typeof featureId !== "string") { + label = featureId; + } else { + label = this.nodeFactory(featureId + this.LABEL_ID_SUFFIX, this.labelNodeType); + label._featureId = featureId; + } + label._style = style; + label._x = location.x; + label._y = location.y; + if(style.labelXOffset || style.labelYOffset) { + var xOffset = isNaN(style.labelXOffset) ? 0 : style.labelXOffset; + var yOffset = isNaN(style.labelYOffset) ? 0 : style.labelYOffset; + var res = this.getResolution(); + location.move(xOffset*res, yOffset*res); + } + + if(label.parentNode !== this.textRoot) { + this.textRoot.appendChild(label); + } + + return label; + }, + + CLASS_NAME: "OpenLayers.Renderer.NG" +}); + +// Monkey-patching Layer.Vector for Renderer.NG support +(function() { + var moveTo = OpenLayers.Layer.Vector.prototype.moveTo; + OpenLayers.Layer.Vector.prototype.moveTo = function(bounds, zoomChanged, dragging) { + if (OpenLayers.Renderer.NG && this.renderer instanceof OpenLayers.Renderer.NG) { + OpenLayers.Layer.prototype.moveTo.apply(this, arguments); + dragging || this.renderer.updateDimensions(zoomChanged); + if (!this.drawn) { + this.drawn = true; + var feature; + for(var i=0, len=this.features.length; i + */ +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} + * 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} + * + * 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 - {} + * 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 - {} + * + * 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 - {} + * + * 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 - {} + * + * 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} + * + * 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 - {}, 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()} 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} + * + * 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 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(); +}; \ No newline at end of file diff --git a/notes/2.12.md b/notes/2.12.md index f62893ac50..273ef85d0d 100644 --- a/notes/2.12.md +++ b/notes/2.12.md @@ -248,6 +248,8 @@ A number of properties, methods, and constructors have been marked as deprecated * OpenLayers.Layer.Yahoo * OpenLayers.Layer.GML * OpenLayers.Geometry.Rectangle + * OpenLayers.Renderer.NG + * OpenLayers.Renderer.SVG2 In addition, OpenLayers no longer modifies any native prototypes or objects by default. If you rely on any of the following, you'll need to include deprecated.js explicitly to get the same behavior. diff --git a/tests/Layer/Vector.html b/tests/Layer/Vector.html index fa2aff1471..160f2314d7 100644 --- a/tests/Layer/Vector.html +++ b/tests/Layer/Vector.html @@ -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); diff --git a/tests/Renderer/SVG2.html b/tests/deprecated/Renderer/SVG2.html similarity index 99% rename from tests/Renderer/SVG2.html rename to tests/deprecated/Renderer/SVG2.html index 6ee12ee9b6..c23b95c210 100644 --- a/tests/Renderer/SVG2.html +++ b/tests/deprecated/Renderer/SVG2.html @@ -1,6 +1,7 @@ - + + - - - -
-

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.

-

This test only works on browsers that support SVG.

- -