diff --git a/examples/vector-features.html b/examples/vector-features.html
index 567c39be0a..812eab174c 100644
--- a/examples/vector-features.html
+++ b/examples/vector-features.html
@@ -58,6 +58,8 @@
// of the image will be ignored
style_mark.graphicWidth = 24;
style_mark.graphicHeight = 20;
+ style_mark.graphicXOffset = -(style_mark.graphicWidth/2); // this is the default value
+ style_mark.graphicYOffset = -style_mark.graphicHeight;
style_mark.externalGraphic = "../img/marker.png";
var vectorLayer = new OpenLayers.Layer.Vector("Simple Geometry", {style: layer_style});
diff --git a/lib/OpenLayers/Feature/Vector.js b/lib/OpenLayers/Feature/Vector.js
index 423af1b8fa..dec6a753da 100644
--- a/lib/OpenLayers/Feature/Vector.js
+++ b/lib/OpenLayers/Feature/Vector.js
@@ -263,6 +263,8 @@ OpenLayers.Feature.Vector = OpenLayers.Class(OpenLayers.Feature, {
* - graphicWidth,
* - graphicHeight,
* - graphicOpacity
+ * - graphicXOffset
+ * - graphicYOffset
*/
OpenLayers.Feature.Vector.style = {
'default': {
diff --git a/lib/OpenLayers/Renderer/SVG.js b/lib/OpenLayers/Renderer/SVG.js
index f0a12813fe..525bb749c6 100644
--- a/lib/OpenLayers/Renderer/SVG.js
+++ b/lib/OpenLayers/Renderer/SVG.js
@@ -184,8 +184,8 @@ OpenLayers.Renderer.SVG = OpenLayers.Class(OpenLayers.Renderer.Elements, {
if (style.externalGraphic) {
// remove old node
var id = node.getAttributeNS(null, "id");
- var x = node.getAttributeNS(null, "cx");
- var y = node.getAttributeNS(null, "cy");
+ var x = parseFloat(node.getAttributeNS(null, "cx"));
+ var y = parseFloat(node.getAttributeNS(null, "cy"));
var _featureId = node._featureId;
var _geometryClass = node._geometryClass;
var _style = node._style;
@@ -206,10 +206,14 @@ OpenLayers.Renderer.SVG = OpenLayers.Class(OpenLayers.Renderer.Elements, {
var height = style.graphicHeight || style.graphicWidth;
width = width ? width : style.pointRadius*2;
height = height ? height : style.pointRadius*2;
+ var xOffset = (style.graphicXOffset != undefined) ?
+ style.graphicXOffset : -(0.5 * width);
+ var yOffset = (style.graphicYOffset != undefined) ?
+ style.graphicYOffset : -(0.5 * height);
var opacity = style.graphicOpacity || style.fillOpacity;
- node.setAttributeNS(null, "x", x-(.5*width).toFixed());
- node.setAttributeNS(null, "y", -y-(.5*height).toFixed());
+ node.setAttributeNS(null, "x", (x + xOffset).toFixed());
+ node.setAttributeNS(null, "y", (-y + yOffset).toFixed());
node.setAttributeNS(null, "width", width);
node.setAttributeNS(null, "height", height);
node.setAttributeNS("http://www.w3.org/1999/xlink", "href", style.externalGraphic);
diff --git a/lib/OpenLayers/Renderer/VML.js b/lib/OpenLayers/Renderer/VML.js
index 1c39759f21..2d63dd0b25 100644
--- a/lib/OpenLayers/Renderer/VML.js
+++ b/lib/OpenLayers/Renderer/VML.js
@@ -181,9 +181,15 @@ OpenLayers.Renderer.VML = OpenLayers.Class(OpenLayers.Renderer.Elements, {
var height = style.graphicHeight || style.graphicWidth;
width = width ? width : style.pointRadius*2;
height = height ? height : style.pointRadius*2;
+
var resolution = this.getResolution();
- node.style.left = (geometry.x/resolution-.5*width).toFixed();
- node.style.top = (geometry.y/resolution-.5*height).toFixed();
+ var xOffset = (style.graphicXOffset != undefined) ?
+ style.graphicXOffset : -(0.5 * width);
+ var yOffset = (style.graphicYOffset != undefined) ?
+ style.graphicYOffset : -(0.5 * height);
+
+ node.style.left = ((geometry.x/resolution)+xOffset).toFixed();
+ node.style.top = ((geometry.y/resolution)-(yOffset+height)).toFixed();
node.style.width = width;
node.style.height = height;
diff --git a/tests/Layer/test_Vector.html b/tests/Layer/test_Vector.html
index b916338cd7..ec950dfdb2 100644
--- a/tests/Layer/test_Vector.html
+++ b/tests/Layer/test_Vector.html
@@ -158,7 +158,7 @@
}
function test_Layer_Vector_externalGraphic(t) {
- t.plan(9);
+ t.plan(11);
// base layer is needed for getResolution() to return a value,
// otherwise VML test will fail because style.left and style.top
// cannot be set
@@ -169,12 +169,17 @@
format: 'image/png'});
var layer = new OpenLayers.Layer.Vector("Test Layer");
+ var renderer = layer.renderer;
var map = new OpenLayers.Map('map');
map.addLayers([baseLayer, layer]);
- var geometry = new OpenLayers.Geometry.Point(10, 10);
+ var geometryX = 10;
+ var geometryY = 10;
+ var geometry = new OpenLayers.Geometry.Point(geometryX, geometryY);
var feature = new OpenLayers.Feature.Vector(geometry);
+ map.zoomToMaxExtent();
+
var customStyle1 = new Object({
externalGraphic: 'test.png',
pointRadius: 10
@@ -197,8 +202,15 @@
graphicWidth: 24,
graphicOpacity: 1
});
+ var customStyle6 = new Object({
+ externalGraphic: 'test.png',
+ graphicWidth: 24,
+ graphicHeight: 16,
+ graphicXOffset: -24,
+ graphicYOffset: -16
+ });
- var root = layer.renderer.root;
+ var root = renderer.root;
if (layer.renderer.CLASS_NAME == 'OpenLayers.Renderer.SVG') {
feature.style = customStyle1;
layer.drawFeature(feature);
@@ -237,6 +249,23 @@
t.eq(root.firstChild.getAttributeNS(null, 'style'),
'opacity: '+customStyle5.graphicOpacity.toString()+';',
"graphicOpacity correctly set");
+ feature.style = customStyle6;
+ layer.drawFeature(feature);
+ var x = geometryX / renderer.getResolution() + renderer.left;
+ var y = geometryY / renderer.getResolution() - renderer.top;
+ // SVG setStyle() gets x and y using getAttributeNS(), which returns
+ // a value with only 3 decimal digits. To mimic this we use toFixed(3) here
+ x = x.toFixed(3);
+ y = y.toFixed(3);
+ // toFixed() returns a string
+ x = parseFloat(x);
+ y = parseFloat(y);
+ t.eq(root.firstChild.getAttributeNS(null, 'x'),
+ (x + customStyle6.graphicXOffset).toFixed().toString(),
+ "graphicXOffset correctly set");
+ t.eq(root.firstChild.getAttributeNS(null, 'y'),
+ (-y + customStyle6.graphicYOffset).toFixed().toString(),
+ "graphicYOffset correctly set");
}
if (layer.renderer.CLASS_NAME == 'OpenLayers.Renderer.VML') {
feature.style = customStyle1;
@@ -279,6 +308,17 @@
t.eq(opacity,
customStyle5.graphicOpacity,
"graphicOpacity correctly set");
+ feature.style = customStyle6;
+ layer.drawFeature(feature);
+ var x = geometryX / renderer.getResolution();
+ var y = geometryY / renderer.getResolution();
+ t.eq(root.firstChild.style.left,
+ (x + customStyle6.graphicXOffset).toFixed().toString()+'px',
+ "graphicXOffset correctly set");
+
+ t.eq(root.firstChild.style.top,
+ (y - (customStyle6.graphicYOffset+parseInt(root.firstChild.style.height))).toFixed().toString()+'px',
+ "graphicYOffset correctly set");
}
}