Add support to the vector layer to visualize point geometries with images. This

support was added, tested, and documented by Andreas Hocevar, and I want to
thank him for the work he put into this patch. It looks pretty great. (This
is from ticket #736.)


git-svn-id: http://svn.openlayers.org/trunk/openlayers@3729 dc9f47b5-9b13-0410-9fdd-eb0c1a62fdaf
This commit is contained in:
crschmidt
2007-07-13 13:31:40 +00:00
parent 4f70df0029
commit 8e1eb78c26
4 changed files with 221 additions and 6 deletions

View File

@@ -7,7 +7,7 @@
border: 1px solid black;
}
</style>
<script src="../lib/OpenLayers.js"></script>
<script src="../lib/OpenLayers.js" type="text/javascript"></script>
<script type="text/javascript">
<!--
var map;
@@ -21,6 +21,16 @@
var style_blue = OpenLayers.Util.extend({}, OpenLayers.Feature.Vector.style['default']);
style_blue.strokeColor = "blue";
style_blue.fillColor = "blue";
style_blue.externalGraphic = "../img/marker.png";
// each of the three lines below means the same, if only one of
// them is active: the image will have a size of 24px, and the
// aspect ratio will be kept
style_blue.pointRadius = 12;
//style_blue.graphicWidth = 24;
//style_blue.graphicHeight = 24;
style_blue.fillOpacity = 1;
var style_green = {
strokeColor: "#00FF00",
strokeOpacity: 1,
@@ -28,12 +38,24 @@
pointRadius: 6,
pointerEvents: "visiblePainted"
};
var style_mark = OpenLayers.Util.extend({}, OpenLayers.Feature.Vector.style['default']);
// if graphicWidth and graphicHeight are both set, the aspect ratio
// of the image will be ignored
style_mark.graphicWidth = 24;
style_mark.graphicHeight = 20;
style_mark.externalGraphic = "../img/marker.png";
var vectorLayer = new OpenLayers.Layer.Vector("Simple Geometry");
// create a point feature
var point = new OpenLayers.Geometry.Point(-111.04, 45.68);
var pointFeature = new OpenLayers.Feature.Vector(point,null,style_blue);
var point2 = new OpenLayers.Geometry.Point(-105.04, 49.68);
var pointFeature2 = new OpenLayers.Feature.Vector(point2,null,style_green);
var point3 = new OpenLayers.Geometry.Point(-105.04, 49.68);
var pointFeature3 = new OpenLayers.Feature.Vector(point3,null,style_mark);
// create a line feature from a list of points
var pointList = [];
@@ -64,7 +86,7 @@
map.addLayer(vectorLayer);
map.setCenter(new OpenLayers.LonLat(point.x, point.y), 5);
vectorLayer.addFeatures([pointFeature, lineFeature, polygonFeature]);
vectorLayer.addFeatures([pointFeature, pointFeature3, pointFeature2, lineFeature, polygonFeature]);
}
// -->
</script>
@@ -75,5 +97,12 @@
in different styles, created 'manually', by constructing the entire style
object, via 'copy', extending the default style object, and by
inheriting the default style from the layer.</p>
<p>It also shows how to use external graphic files for point features
and how to set their size: If either graphicWidth or graphicHeight is set,
the aspect ratio of the image will be respected. If both graphicWidth and
graphicHeight are set, it will be ignored. Alternatively, if graphicWidth
and graphicHeight are omitted, pointRadius will be used to set the size
of the image, which will then be twice the value of pointRadius with the
original aspect ratio.</p>
</body>
</html>

View File

@@ -183,7 +183,42 @@ OpenLayers.Renderer.SVG.prototype =
options = options || node._options;
if (node._geometryClass == "OpenLayers.Geometry.Point") {
node.setAttributeNS(null, "r", style.pointRadius);
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 _featureId = node._featureId;
var _geometryClass = node._geometryClass;
var _style = node._style;
this.root.removeChild(node);
// create new image node
var node = this.createNode("image", id);
node._featureId = _featureId;
node._geometryClass = _geometryClass;
node._style = _style;
this.root.appendChild(node);
// now style the new node
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;
node.setAttributeNS(null, "x", x-(.5*width).toFixed());
node.setAttributeNS(null, "y", -y-(.5*height).toFixed());
node.setAttributeNS(null, "width", width);
node.setAttributeNS(null, "height", height);
node.setAttributeNS("http://www.w3.org/1999/xlink", "href", style.externalGraphic);
node.setAttributeNS(null, "transform", "scale(1,-1)");
node.setAttributeNS(null, "style", "opacity: "+style.fillOpacity);
} else {
node.setAttributeNS(null, "r", style.pointRadius);
}
}
if (options.isFilled) {

View File

@@ -153,7 +153,49 @@ OpenLayers.Renderer.VML.prototype =
options = options || node._options;
if (node._geometryClass == "OpenLayers.Geometry.Point") {
this.drawCircle(node, geometry, style.pointRadius);
if (style.externalGraphic) {
// remove old node
var id = node.id;
var _featureId = node._featureId;
var _geometryClass = node._geometryClass;
var _style = node._style;
this.root.removeChild(node);
// create new image node
var node = this.createNode("v:rect", id);
var fill = this.createNode("v:fill", id+"_image");
node.appendChild(fill);
node._featureId = _featureId;
node._geometryClass = _geometryClass;
node._style = _style;
this.root.appendChild(node);
fill.src = style.externalGraphic;
fill.type = "frame";
node.style.flip = "y";
if (!(style.graphicWidth && style.graphicHeight)) {
fill.aspect = "atmost";
}
// now style the new node
var width = style.graphicWidth || style.graphicHeight;
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();
node.style.width = width;
node.style.height = height;
// modify fill style for rect styling below
style.fillColor = "none";
style.strokeColor = "none";
} else {
this.drawCircle(node, geometry, style.pointRadius);
}
}
//fill
@@ -170,7 +212,9 @@ OpenLayers.Renderer.VML.prototype =
fill = this.createNode('v:fill', node.id + "_fill");
node.appendChild(fill);
}
fill.setAttribute("opacity", style.fillOpacity);
if (style.fillOpacity) {
fill.setAttribute("opacity", style.fillOpacity);
}
}

View File

@@ -106,7 +106,7 @@
"given a custom style, renders with that");
}
function test_Layer_Vector_eraseFeatures(t) {
t.plan(2);
var layer = new OpenLayers.Layer.Vector("Test Layer");
@@ -156,6 +156,113 @@
t.eq(layer.map, null, "layer.map is null after destroy");
}
function test_Layer_Vector_externalGraphic(t) {
t.plan(8);
// base layer is needed for getResolution() to return a value,
// otherwise VML test will fail because style.left and style.top
// cannot be set
var baseLayer = new OpenLayers.Layer.WMS("Base Layer",
"http://octo.metacarta.com/cgi-bin/mapserv",
{ map: '/mapdata/vmap_wms.map',
layers: 'basic',
format: 'image/png'});
var layer = new OpenLayers.Layer.Vector("Test Layer");
var map = new OpenLayers.Map('map');
map.addLayers([baseLayer, layer]);
var geometry = new OpenLayers.Geometry.Point(10, 10);
var feature = new OpenLayers.Feature.Vector(geometry);
var customStyle1 = new Object({
externalGraphic: 'test.png',
pointRadius: 10
});
var customStyle2 = new Object({
externalGraphic: 'test.png',
graphicWidth: 12
});
var customStyle3 = new Object({
externalGraphic: 'test.png',
graphicHeight: 14
});
var customStyle4 = new Object({
externalGraphic: 'test.png',
graphicWidth: 24,
graphicHeight: 16
});
var root = layer.renderer.root;
if (layer.renderer.CLASS_NAME == 'OpenLayers.Renderer.SVG') {
feature.style = customStyle1;
layer.drawFeature(feature);
t.eq(root.firstChild.getAttributeNS(null, 'width'),
(2*customStyle1.pointRadius).toString(),
"given a pointRadius, width equals 2*pointRadius");
t.eq(root.firstChild.getAttributeNS(null, 'height'),
(2*customStyle1.pointRadius).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.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.toString(),
"height is set correctly");
feature.style = customStyle4;
layer.drawFeature(feature);
t.eq(root.firstChild.getAttributeNS(null, 'height'),
customStyle4.graphicHeight.toString(),
"given graphicHeight and graphicWidth, both are set: height")
t.eq(root.firstChild.getAttributeNS(null, 'width'),
customStyle4.graphicWidth.toString(),
"given graphicHeight and graphicWidth, both are set: width")
}
if (layer.renderer.CLASS_NAME == 'OpenLayers.Renderer.VML') {
feature.style = customStyle1;
layer.drawFeature(feature);
t.eq(root.firstChild.style.width,
(2*customStyle1.pointRadius).toString()+'px',
"given a pointRadius, width equals 2*pointRadius");
t.eq(root.firstChild.style.height,
(2*customStyle1.pointRadius).toString()+'px',
"given a pointRadius, height equals 2*pointRadius");
feature.style = customStyle2;
layer.drawFeature(feature);
t.eq(root.firstChild.style.width,
root.firstChild.style.height,
"given a graphicWidth, width equals height");
t.eq(root.firstChild.style.width,
customStyle2.graphicWidth.toString()+'px',
"width is set correctly");
feature.style = customStyle3;
layer.drawFeature(feature);
t.eq(root.firstChild.style.height,
root.firstChild.style.width,
"given a graphicHeight, height equals width");
t.eq(root.firstChild.style.height,
customStyle3.graphicHeight.toString()+'px',
"height is set correctly");
feature.style = customStyle4;
layer.drawFeature(feature);
t.eq(root.firstChild.style.height,
customStyle4.graphicHeight.toString()+'px',
"given graphicHeight and graphicWidth, both are set: height")
t.eq(root.firstChild.style.width,
customStyle4.graphicWidth.toString()+'px',
"given graphicHeight and graphicWidth, both are set: width")
}
}
// -->
</script>
</head>