Drawing MultiPolygon with different style for each component in OpenLayers
I have a OpenLayers.Feature.Vector created as follows:
var multiPol = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.MultiPolygon([polygonGeometry1,polygonGeometry2]));
Both polygons represent same logical object (an "entity") on a map, say a cloud. This is why I keep them in one feature. I would like to draw it so that each component of this multi-polygon (polygonGeometry1, polygonGeometry2) is drawn with different color when it's added to a layer:
var layer = new OpenLayers.Layer.Vector("polygonLayer");
开发者_StackOverflow layer.addFeatures([multiPol]);
I have taken a look at styles, style maps and rules in OpenLayers but they appear to be insufficient. They do enable me to draw each geometry type with different color but only if they belong to different features (vectors). Is there a way to solve this problem? Do really I have to use separate Vector for each polygon?
The proposed solution by Jon Snyder provided us with a general idea, but did not fully work for in the end (especially extending OpenLayers.Layer.Vector
wasn't necessary for this task, based on OpenLayers 2.1x).
We created a class YourApp.Handler.EndPointsPath
(extending OpenLayers.Handler.Path
), where the function geometryClone()
returns a new geometry of type YourApp.Geometry.EndPointsPath
.
We then patched the function drawGeometry()
in OpenLayers.Renderer.Elements
to draw this new geometry:
OpenLayers.Util.extend(OpenLayers.Renderer.Elements.prototype, {
drawGeometry: function (geometry, style, featureId) {
var cl = geometry.CLASS_NAME;
var rendered = true,
i, len;
if ((cl === "OpenLayers.Geometry.Collection") ||
(cl === "OpenLayers.Geometry.MultiPoint") ||
(cl === "OpenLayers.Geometry.MultiLineString") ||
(cl === "OpenLayers.Geometry.MultiPolygon") ||
(cl === "YourApp.Geometry.EndPointsPath")) {
// Iterate over all Geometry components and draw each individually
for (i = 0, len = geometry.components.length; i < len; i++) {
// Is there a style for each of the components?
if (OpenLayers.Util.isArray(style)) {
// Draw Geometry with own style
rendered = this.drawGeometry(geometry.components[i], style[i], featureId) && rendered;
} else {
// Draw Geometry with common style
rendered = this.drawGeometry(geometry.components[i], style, featureId) && rendered;
}
}
return rendered;
}
// (...standard code...)
},
eraseGeometry: function (geometry, featureId) {
var cl = geometry.CLASS_NAME,
i, len;
if ((cl === "OpenLayers.Geometry.MultiPoint") ||
(cl === "OpenLayers.Geometry.MultiLineString") ||
(cl === "OpenLayers.Geometry.MultiPolygon") ||
(cl === "YourApp.Geometry.EndPointsPath") ||
(cl === "OpenLayers.Geometry.Collection")) {
for (i = 0, len = geometry.components.length; i < len; i++) {
this.eraseGeometry(geometry.components[i], featureId);
}
// (...standard code...)
}
}
});
As far as I can tell, to get this functionality you will need to extend the classes with your own.
First create an extension to OpenLayers.Feature.Vector, name it YourApp.Feature.MultiVector. You can see examples on how to extend classes by looking at the OpenLayers code. This class should accept an array of styles and the multiPolygon. It should have a method that will return a list of OpenLayers.Feature.Vectors each with their own style.
Second create an extension to OpenLayers.Layer.Vector, name it YourApp.Layer.VectorSupportingMultiStyledFeatures. You will need to override the "drawFeature" method. In the drawFeature method test to see if the type of the feature is a MultiVector. If it is, loop through each feature in the MultiVector and call renderer.drawFeature(feature). Otherwise call the super.drawFeature method.
So your code to call it would look like this:
var multiPol = new YourApp.Feature.MultiVector(
new OpenLayers.Geometry.MultiPolygon([polygonGeometry1,polygonGeometry2]),
[style1,style2,style3,style4]);
var layer = new YourApp.Layer.VectorSupportingMultiStyledFeatures("polygonLayer");
layer.addFeatures([multiPol]);
精彩评论