diff --git a/apidoc_config/Menu.txt b/apidoc_config/Menu.txt index dce22b38d8..93d68c2a33 100644 --- a/apidoc_config/Menu.txt +++ b/apidoc_config/Menu.txt @@ -350,6 +350,7 @@ Group: OpenLayers { File: MapGuide (no auto-title, OpenLayers/Layer/MapGuide.js) File: MapServer (no auto-title, OpenLayers/Layer/MapServer.js) File: Markers (no auto-title, OpenLayers/Layer/Markers.js) + File: OSM (no auto-title, OpenLayers/Layer/OSM.js) File: PointGrid (no auto-title, OpenLayers/Layer/PointGrid.js) File: PointTrack (no auto-title, OpenLayers/Layer/PointTrack.js) File: SphericalMercator (no auto-title, OpenLayers/Layer/SphericalMercator.js) diff --git a/examples/vector-features-with-text.html b/examples/vector-features-with-text.html index cbdba665ab..d32fd89e15 100644 --- a/examples/vector-features-with-text.html +++ b/examples/vector-features-with-text.html @@ -39,7 +39,9 @@ fontWeight: "bold", labelAlign: "${align}", labelXOffset: "${xOffset}", - labelYOffset: "${yOffset}" + labelYOffset: "${yOffset}", + labelOutlineColor: "white", + labelOutlineWidth: 3 }}), renderers: renderer }); diff --git a/lib/OpenLayers.js b/lib/OpenLayers.js index 506e362cf7..5302ba8bcf 100644 --- a/lib/OpenLayers.js +++ b/lib/OpenLayers.js @@ -144,6 +144,7 @@ "OpenLayers/Layer/GeoRSS.js", "OpenLayers/Layer/Boxes.js", "OpenLayers/Layer/XYZ.js", + "OpenLayers/Layer/OSM.js", "OpenLayers/Layer/Bing.js", "OpenLayers/Layer/TMS.js", "OpenLayers/Layer/TileCache.js", diff --git a/lib/OpenLayers/Control/DragPan.js b/lib/OpenLayers/Control/DragPan.js index 34e31be905..233e7ab377 100644 --- a/lib/OpenLayers/Control/DragPan.js +++ b/lib/OpenLayers/Control/DragPan.js @@ -57,6 +57,8 @@ OpenLayers.Control.DragPan = OpenLayers.Class(OpenLayers.Control, { * set to true or to an object. If set to an object this * object will be passed to the {} * constructor. Defaults to false. + * If you set this property, you should ensure that + * OpenLayers/Kinetic.js is included in your build config */ enableKinetic: false, diff --git a/lib/OpenLayers/Feature/Vector.js b/lib/OpenLayers/Feature/Vector.js index b0e91009c4..75dd5ff20d 100644 --- a/lib/OpenLayers/Feature/Vector.js +++ b/lib/OpenLayers/Feature/Vector.js @@ -414,11 +414,13 @@ OpenLayers.Feature.Vector = OpenLayers.Class(OpenLayers.Feature, { * labelAlign - {String} Label alignment. This specifies the insertion point relative to the text. It is a string * composed of two characters. The first character is for the horizontal alignment, the second for the vertical * alignment. Valid values for horizontal alignment: "l"=left, "c"=center, "r"=right. Valid values for vertical - * alignment: "t"=top, "m"=middle, "b"=bottom. Example values: "lt", "cm", "rb". + * alignment: "t"=top, "m"=middle, "b"=bottom. Example values: "lt", "cm", "rb". Default is "cm". * labelXOffset - {Number} Pixel offset along the positive x axis for displacing the label. Not supported by the canvas renderer. * labelYOffset - {Number} Pixel offset along the positive y axis for displacing the label. Not supported by the canvas renderer. * labelSelect - {Boolean} If set to true, labels will be selectable using SelectFeature or similar controls. * Default is false. + * labelOutlineColor - {String} The color of the label outline. Default is 'white'. Only supported by the canvas & SVG renderers. + * labelOutlineWidth - {Number} The width of the label outline. Default is 3, set to 0 or null to disable. Only supported by the canvas & SVG renderers. * fontColor - {String} The font color for the label, to be provided like CSS. * fontOpacity - {Number} Opacity (0-1) for the label * fontFamily - {String} The font family for the label, to be provided like in CSS. @@ -445,7 +447,11 @@ OpenLayers.Feature.Vector.style = { hoverPointRadius: 1, hoverPointUnit: "%", pointerEvents: "visiblePainted", - cursor: "inherit" + cursor: "inherit", + fontColor: "#000000", + labelAlign: "cm", + labelOutlineColor: "white", + labelOutlineWidth: 3 }, 'select': { fillColor: "blue", @@ -464,7 +470,12 @@ OpenLayers.Feature.Vector.style = { hoverPointRadius: 1, hoverPointUnit: "%", pointerEvents: "visiblePainted", - cursor: "pointer" + cursor: "pointer", + fontColor: "#000000", + labelAlign: "cm", + labelOutlineColor: "white", + labelOutlineWidth: 3 + }, 'temporary': { fillColor: "#66cccc", @@ -483,7 +494,12 @@ OpenLayers.Feature.Vector.style = { hoverPointRadius: 1, hoverPointUnit: "%", pointerEvents: "visiblePainted", - cursor: "inherit" + cursor: "inherit", + fontColor: "#000000", + labelAlign: "cm", + labelOutlineColor: "white", + labelOutlineWidth: 3 + }, 'delete': { display: "none" diff --git a/lib/OpenLayers/Geometry/LinearRing.js b/lib/OpenLayers/Geometry/LinearRing.js index c8b960915c..4c5450e82d 100644 --- a/lib/OpenLayers/Geometry/LinearRing.js +++ b/lib/OpenLayers/Geometry/LinearRing.js @@ -294,7 +294,7 @@ OpenLayers.Geometry.LinearRing = OpenLayers.Class( var px = approx(point.x, digs); var py = approx(point.y, digs); function getX(y, x1, y1, x2, y2) { - return (((x1 - x2) * y) + ((x2 * y1) - (x1 * y2))) / (y1 - y2); + return (y - y2) * ((x2 - x1) / (y2 - y1)) + x2; } var numSeg = this.components.length - 1; var start, end, x1, y1, x2, y2, cx, cy; diff --git a/lib/OpenLayers/Layer/OSM.js b/lib/OpenLayers/Layer/OSM.js new file mode 100644 index 0000000000..a1874e3453 --- /dev/null +++ b/lib/OpenLayers/Layer/OSM.js @@ -0,0 +1,91 @@ +/* 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/Layer/XYZ.js + * @requires OpenLayers/Layer/SphericalMercator.js + */ + +/** + * Class: OpenLayers.Layer.OSM + * This layer allows accessing OpenStreetMap tiles. By default the OpenStreetMap + * hosted tile.openstreetmap.org Mapnik tileset is used. If you wish to use + * tiles@home / osmarender layer instead, you need to provide a different + * URL to the constructor. Here's an example for tiles@home: + * + * (code) + * new OpenLayers.Layer.OSM("t@h", + * "http://tah.openstreetmap.org/Tiles/tile/${z}/${x}/${y}.png"); + * (end) + * + * Inherits from: + * - + */ +OpenLayers.Layer.OSM = OpenLayers.Class(OpenLayers.Layer.XYZ, { + + /** + * APIProperty: name + * {String} The layer name. Defaults to "OpenStreetMap" if the first + * argument to the constructor is null or undefined. + */ + name: "OpenStreetMap", + + /** + * APIProperty: url + * {String} The tileset URL scheme. Defaults to + * : http://tile.openstreetmap.org/${z}/${x}/${y}.png + * (the official OSM tileset) if the second argument to the constructor + * is null or undefined. To use another tileset you can have something + * like this: + * (start code) + * new OpenLayers.Layer.OSM("t@h", + * "http://tah.openstreetmap.org/Tiles/tile/${z}/${x}/${y}.png"); + * (end) + */ + url: 'http://tile.openstreetmap.org/${z}/${x}/${y}.png', + + /** + * Property: attribution + * {String} The layer attribution. + */ + attribution: "Data CC-By-SA by OpenStreetMap", + + /** + * Property: sphericalMercator + * {Boolean} + */ + sphericalMercator: true, + + /** + * Property: wrapDateLine + * {Boolean} + */ + wrapDateLine: true, + + /** + * Constructor: OpenLayers.Layer.OSM + * + * Parameters: + * name - {String} The layer name. + * url - {String} The tileset URL scheme. + * options - {Object} Configuration options for the layer. Any inherited + * layer option can be set in this object (e.g. + * ). + */ + + /** + * Method: clone + */ + clone: function(obj) { + if (obj == null) { + obj = new OpenLayers.Layer.OSM( + this.name, this.url, this.getOptions()); + } + obj = OpenLayers.Layer.XYZ.prototype.clone.apply(this, [obj]); + return obj; + }, + + CLASS_NAME: "OpenLayers.Layer.OSM" +}); diff --git a/lib/OpenLayers/Layer/XYZ.js b/lib/OpenLayers/Layer/XYZ.js index 84855f95be..7977a3255f 100644 --- a/lib/OpenLayers/Layer/XYZ.js +++ b/lib/OpenLayers/Layer/XYZ.js @@ -183,37 +183,3 @@ OpenLayers.Layer.XYZ = OpenLayers.Class(OpenLayers.Layer.Grid, { CLASS_NAME: "OpenLayers.Layer.XYZ" }); - - -/** - * Class: OpenLayers.Layer.OSM - * A class to access OpenStreetMap tiles. By default, uses the OpenStreetMap - * hosted tile.openstreetmap.org 'Mapnik' tileset. If you wish to use - * tiles@home / osmarender layer instead, you can pass a layer like: - * - * (code) - * new OpenLayers.Layer.OSM("t@h", - * "http://tah.openstreetmap.org/Tiles/tile/${z}/${x}/${y}.png"); - * (end) - * - * This layer defaults to Spherical Mercator. - * - * Inherits from: - * - - */ -OpenLayers.Layer.OSM = OpenLayers.Class(OpenLayers.Layer.XYZ, { - name: "OpenStreetMap", - attribution: "Data CC-By-SA by OpenStreetMap", - sphericalMercator: true, - url: 'http://tile.openstreetmap.org/${z}/${x}/${y}.png', - clone: function(obj) { - if (obj == null) { - obj = new OpenLayers.Layer.OSM( - this.name, this.url, this.getOptions()); - } - obj = OpenLayers.Layer.XYZ.prototype.clone.apply(this, [obj]); - return obj; - }, - wrapDateLine: true, - CLASS_NAME: "OpenLayers.Layer.OSM" -}); diff --git a/lib/OpenLayers/Protocol/HTTP.js b/lib/OpenLayers/Protocol/HTTP.js index 37768fbac0..edcb3ed6fa 100644 --- a/lib/OpenLayers/Protocol/HTTP.js +++ b/lib/OpenLayers/Protocol/HTTP.js @@ -9,8 +9,8 @@ */ /** - * TODO: remove this dependency in 3.0 - * @requires OpenLayers/Format/QueryStringFilter.js + * if application uses the query string, for example, for BBOX parameters, + * OpenLayers/Format/QueryStringFilter.js should be included in the build config file */ /** diff --git a/lib/OpenLayers/Protocol/Script.js b/lib/OpenLayers/Protocol/Script.js index b53b8bed02..49e332b7f0 100644 --- a/lib/OpenLayers/Protocol/Script.js +++ b/lib/OpenLayers/Protocol/Script.js @@ -9,6 +9,11 @@ * @requires OpenLayers/Format/GeoJSON.js */ +/** + * if application uses the query string, for example, for BBOX parameters, + * OpenLayers/Format/QueryStringFilter.js should be included in the build config file + */ + /** * Class: OpenLayers.Protocol.Script * A basic Script protocol for vector layers. Create a new instance with the diff --git a/lib/OpenLayers/Renderer/Canvas.js b/lib/OpenLayers/Renderer/Canvas.js index 105959db44..4edaf92a7b 100644 --- a/lib/OpenLayers/Renderer/Canvas.js +++ b/lib/OpenLayers/Renderer/Canvas.js @@ -525,10 +525,6 @@ OpenLayers.Renderer.Canvas = OpenLayers.Class(OpenLayers.Renderer, { * style - {Object} */ drawText: function(location, style) { - style = OpenLayers.Util.extend({ - fontColor: "#000000", - labelAlign: "cm" - }, style); var pt = this.getLocalXY(location); this.setCanvasStyle("reset"); @@ -560,6 +556,13 @@ OpenLayers.Renderer.Canvas = OpenLayers.Class(OpenLayers.Renderer, { this.canvas.measureText('xx').width; pt[1] += lineHeight*vfactor*(numRows-1); for (var i = 0; i < numRows; i++) { + if (style.labelOutlineWidth) { + this.canvas.save(); + this.canvas.strokeStyle = style.labelOutlineColor; + this.canvas.lineWidth = style.labelOutlineWidth; + this.canvas.strokeText(labelRows[i], pt[0], pt[1] + (lineHeight*i) + 1); + this.canvas.restore(); + } this.canvas.fillText(labelRows[i], pt[0], pt[1] + (lineHeight*i)); } } else if (this.canvas.mozDrawText) { diff --git a/lib/OpenLayers/Renderer/Elements.js b/lib/OpenLayers/Renderer/Elements.js index 49b4ab6f26..7e1d89e5b1 100644 --- a/lib/OpenLayers/Renderer/Elements.js +++ b/lib/OpenLayers/Renderer/Elements.js @@ -415,6 +415,12 @@ OpenLayers.Renderer.Elements = OpenLayers.Class(OpenLayers.Renderer, { */ LABEL_ID_SUFFIX: "_label", + /** + * Constant: LABEL_OUTLINE_SUFFIX + * {String} + */ + LABEL_OUTLINE_SUFFIX: "_outline", + /** * Constructor: OpenLayers.Renderer.Elements * @@ -879,6 +885,10 @@ OpenLayers.Renderer.Elements = OpenLayers.Class(OpenLayers.Renderer, { if (label) { this.textRoot.removeChild(label); } + var outline = document.getElementById(featureId + this.LABEL_OUTLINE_SUFFIX); + if (outline) { + this.textRoot.removeChild(outline); + } }, /** diff --git a/lib/OpenLayers/Renderer/SVG.js b/lib/OpenLayers/Renderer/SVG.js index e526e818a4..f35c4b7236 100644 --- a/lib/OpenLayers/Renderer/SVG.js +++ b/lib/OpenLayers/Renderer/SVG.js @@ -643,12 +643,25 @@ OpenLayers.Renderer.SVG = OpenLayers.Class(OpenLayers.Renderer.Elements, { * location - {} */ drawText: function(featureId, style, location) { + var drawOutline = (!!style.labelOutlineWidth); + // First draw text in halo color and size and overlay the + // normal text afterwards + if (drawOutline) { + var outlineStyle = OpenLayers.Util.extend({}, style); + outlineStyle.fontColor = outlineStyle.labelOutlineColor; + outlineStyle.fontStrokeColor = outlineStyle.labelOutlineColor; + outlineStyle.fontStrokeWidth = style.labelOutlineWidth; + delete outlineStyle.labelOutlineWidth; + this.drawText(featureId, outlineStyle, location); + } + var resolution = this.getResolution(); var x = ((location.x - this.featureDx) / resolution + this.left); var y = (location.y / resolution - this.top); - var label = this.nodeFactory(featureId + this.LABEL_ID_SUFFIX, "text"); + var suffix = (drawOutline)?this.LABEL_OUTLINE_SUFFIX:this.LABEL_ID_SUFFIX; + label = this.nodeFactory(featureId + suffix, "text"); label.setAttributeNS(null, "x", x); label.setAttributeNS(null, "y", -y); @@ -656,6 +669,12 @@ OpenLayers.Renderer.SVG = OpenLayers.Class(OpenLayers.Renderer.Elements, { if (style.fontColor) { label.setAttributeNS(null, "fill", style.fontColor); } + if (style.fontStrokeColor) { + label.setAttributeNS(null, "stroke", style.fontStrokeColor); + } + if (style.fontStrokeWidth) { + label.setAttributeNS(null, "stroke-width", style.fontStrokeWidth); + } if (style.fontOpacity) { label.setAttributeNS(null, "opacity", style.fontOpacity); } @@ -677,7 +696,7 @@ OpenLayers.Renderer.SVG = OpenLayers.Class(OpenLayers.Renderer.Elements, { } else { label.setAttributeNS(null, "pointer-events", "none"); } - var align = style.labelAlign || "cm"; + var align = style.labelAlign; label.setAttributeNS(null, "text-anchor", OpenLayers.Renderer.SVG.LABEL_ALIGN[align[0]] || "middle"); @@ -692,7 +711,7 @@ OpenLayers.Renderer.SVG = OpenLayers.Class(OpenLayers.Renderer.Elements, { label.removeChild(label.lastChild); } for (var i = 0; i < numRows; i++) { - var tspan = this.nodeFactory(featureId + this.LABEL_ID_SUFFIX + "_tspan_" + i, "tspan"); + var tspan = this.nodeFactory(featureId + suffix + "_tspan_" + i, "tspan"); if (style.labelSelect === true) { tspan._featureId = featureId; tspan._geometry = location; diff --git a/lib/OpenLayers/Renderer/SVG2.js b/lib/OpenLayers/Renderer/SVG2.js index 50e21919e6..a385689481 100644 --- a/lib/OpenLayers/Renderer/SVG2.js +++ b/lib/OpenLayers/Renderer/SVG2.js @@ -584,7 +584,7 @@ OpenLayers.Renderer.SVG2 = OpenLayers.Class(OpenLayers.Renderer.NG, { } else { text.setAttributeNS(null, "pointer-events", "none"); } - var align = style.labelAlign || "cm"; + var align = style.labelAlign; text.setAttributeNS(null, "text-anchor", OpenLayers.Renderer.SVG2.LABEL_ALIGN[align[0]] || "middle"); diff --git a/notes/2.12.md b/notes/2.12.md index d57ce08859..7013846924 100644 --- a/notes/2.12.md +++ b/notes/2.12.md @@ -50,6 +50,14 @@ The base `OpenLayers.Geometry` class no longer depends on `OpenLayers.Format.WKT Without the WKT format included (by default), the `OpenLayers.Geometry::toString` method now returns "[object Object]." Previously, it returned the Well-Known Text representation of the geometry. To maintain the previous behavior, include the OpenLayers/Format/WKT.js file in your build. +## OSM Layer + +`Layer.OSM` is now defined in its own script file, namely `OpenLayers/Layer/OSM.js`. So people using `Layer.OSM` should now include `OpenLayers/Layer/OSM.js`, as opposed to `OpenLayers/Layer/XYZ.js`, in their OpenLayers builds. (See https://github.com/openlayers/openlayers/issues/138) + +## QueryStringFilter + +`OpenLayers.Protocol.HTTP` no longer requires `OpenLayers.Format.QueryStringFilter`. It you need this, make sure it is included in your build config file. + ## Deprecated Components A number of properties, methods, and constructors have been marked as deprecated for multiple releases in the 2.x series. For the 2.12 release this deprecated functionality has been moved to a separate deprecated.js file. If you use any of the constructors or methods below, you will have to explicitly include the deprecated.js file in your build (or add it in a separate ` diff --git a/tests/Layer/OSM.html b/tests/Layer/OSM.html new file mode 100644 index 0000000000..fac471caf0 --- /dev/null +++ b/tests/Layer/OSM.html @@ -0,0 +1,16 @@ + + + + + + +
+ + diff --git a/tests/Layer/XYZ.html b/tests/Layer/XYZ.html index d6685c05b5..8b8a7cbf31 100644 --- a/tests/Layer/XYZ.html +++ b/tests/Layer/XYZ.html @@ -251,17 +251,11 @@ } function test_clone(t) { - t.plan(2); - - var clone; + t.plan(1); layer = new OpenLayers.Layer.XYZ(name, url, options); - clone = layer.clone(); + var clone = layer.clone(); t.ok(clone instanceof OpenLayers.Layer.XYZ, "clone is a Layer.XYZ instance"); - - layer = new OpenLayers.Layer.OSM(); - clone = layer.clone(); - t.ok(clone instanceof OpenLayers.Layer.OSM, "clone is a Layer.OSM instance"); } diff --git a/tests/list-tests.html b/tests/list-tests.html index b5beafe9e2..ff53d566bd 100644 --- a/tests/list-tests.html +++ b/tests/list-tests.html @@ -167,6 +167,7 @@
  • Layer/WMTS.html
  • Layer/WrapDateLine.html
  • Layer/XYZ.html
  • +
  • Layer/OSM.html
  • Map.html
  • Marker.html
  • Marker/Box.html