[GIS] Clusters strategy different labelling at different level

animationclusteringjavascriptopenlayers-2

What I did

I am trying to plot some points using cluster strategy of OpenLayers using animatedCluster plugin. I have gson data as given:

{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "id": "SITESECTOR.1",
      "geometry": {
        "type": "Point",
        "coordinates": [
          83.01156083999999,
          29.12400297
        ]
      },
      "geometry_name": "SP_GEOMETRY",
      "properties": {
        "siteid": "S3 ",
        "zone": "Z1 ",
        "district": "D1 ",
        "MI_STYLE": null
      }
    },
    {
      "type": "Feature",
      "id": "SITESECTOR.2",
      "geometry": {
        "type": "Point",
        "coordinates": [
          82.60901315999999,
          28.707924959999996
        ]
      },
      "geometry_name": "SP_GEOMETRY",
      "properties": {
        "siteid": "S8 ",
        "zone": "Z8 ",
        "district": "D8 ",
        "MI_STYLE": null
      }
    },
    {
      "type": "Feature",
      "id": "SITESECTOR.3",
      "geometry": {
        "type": "Point",
        "coordinates": [
          83.917305,
          29.00006496
        ]
      },
      "geometry_name": "SP_GEOMETRY",
      "properties": {
        "siteid": "S4 ",
        "zone": "Z2 ",
        "district": "D2 ",
        "MI_STYLE": null
      }
    },
    {
      "type": "Feature",
      "id": "SITESECTOR.4",
      "geometry": {
        "type": "Point",
        "coordinates": [
          84.14876916,
          28.725629039999998
        ]
      },
      "geometry_name": "SP_GEOMETRY",
      "properties": {
        "siteid": "S5 ",
        "zone": "Z3 ",
        "district": "D3 ",
        "MI_STYLE": null
      }
    },
    {
      "type": "Feature",
      "id": "SITESECTOR.5",
      "geometry": {
        "type": "Point",
        "coordinates": [
          83.50468884,
          28.58398497
        ]
      },
      "geometry_name": "SP_GEOMETRY",
      "properties": {
        "siteid": "S6 ",
        "zone": "Z6 ",
        "district": "D6 ",
        "MI_STYLE": null
      }
    },
    {
      "type": "Feature",
      "id": "SITESECTOR.6",
      "geometry": {
        "type": "Point",
        "coordinates": [
          83.08200887999999,
          29.40729102
        ]
      },
      "geometry_name": "SP_GEOMETRY",
      "properties": {
        "siteid": "S1 ",
        "zone": "Z1 ",
        "district": "D1 ",
        "MI_STYLE": null
      }
    },
    {
      "type": "Feature",
      "id": "SITESECTOR.7",
      "geometry": {
        "type": "Point",
        "coordinates": [
          82.73984112,
          29.159415
        ]
      },
      "geometry_name": "SP_GEOMETRY",
      "properties": {
        "siteid": "S2 ",
        "zone": "Z1 ",
        "district": "D1 ",
        "MI_STYLE": null
      }
    },
    {
      "type": "Feature",
      "id": "SITESECTOR.8",
      "geometry": {
        "type": "Point",
        "coordinates": [
          83.24302895999999,
          28.619397
        ]
      },
      "geometry_name": "SP_GEOMETRY",
      "properties": {
        "siteid": "S7 ",
        "zone": "Z7 ",
        "district": "D7 ",
        "MI_STYLE": null
      }
    }
  ],
  "crs": {
    "type": "EPSG",
    "properties": {
      "code": "4326"
    }
  }
}

I am trying to group these by it's property like zone or district which are its attributed as well as other polygons and style it appropriately. And when there is only a single feature I wanted to label it with siteid. I tried without animated cluster and with Bbox strategy the labelling is fine but when I add animated cluster it all fails with undefined label.

My code:

var map;        
// Define three colors that will be used to style the cluster features
// depending on the number of features they contain.
var colors = {
                low: "rgb(181, 226, 140)", 
                middle: "rgb(241, 211, 87)", 
                high: "rgb(253, 156, 115)"
};            
// Define three rules to style the cluster features.
var singleRule = new OpenLayers.Rule({ 
                filter: new OpenLayers.Filter.Comparison({
                                    type: OpenLayers.Filter.Comparison.EQUAL_TO,
                                    property: "count",
                                    value: 1
                                }),         
                symbolizer: {
                    fillColor: colors.low,
                    fillOpacity: 0.9, 
                    strokeColor: colors.low,
                    strokeOpacity: 0.5,
                    strokeWidth: 12,
                    pointRadius: 10,
                    label: "${siteId}",
                    labelOutlineWidth: 1,
                    fontColor: "#ffffff",
                    fontOpacity: 0.8,
                    fontSize: "12px"
                }
});
var lowRule = new OpenLayers.Rule({
                filter: new OpenLayers.Filter.Comparison({
                    type: OpenLayers.Filter.Comparison.BETWEEN,
                    property: "count",
                    lowerBoundary: 2,
                    upperBoundary: 15
                }),
                symbolizer: {
                    fillColor: colors.low,
                    fillOpacity: 0.9, 
                    strokeColor: colors.low,
                    strokeOpacity: 0.5,
                    strokeWidth: 12,
                    pointRadius: 10,
                    label: "${count}",
                    labelOutlineWidth: 1,
                    fontColor: "#ffffff",
                    fontOpacity: 0.8,
                    fontSize: "12px"
                }
});
var middleRule = new OpenLayers.Rule({
                filter: new OpenLayers.Filter.Comparison({
                    type: OpenLayers.Filter.Comparison.BETWEEN,
                    property: "count",
                    lowerBoundary: 15,
                    upperBoundary: 50
                }),
                symbolizer: {
                    fillColor: colors.middle,
                    fillOpacity: 0.9, 
                    strokeColor: colors.middle,
                    strokeOpacity: 0.5,
                    strokeWidth: 12,
                    pointRadius: 15,
                    label: "${count}",
                    labelOutlineWidth: 1,
                    fontColor: "#ffffff",
                    fontOpacity: 0.8,
                    fontSize: "12px"
                }
});
var highRule = new OpenLayers.Rule({
                filter: new OpenLayers.Filter.Comparison({
                    type: OpenLayers.Filter.Comparison.GREATER_THAN,
                    property: "count",
                    value: 50
                }),
                symbolizer: {
                    fillColor: colors.high,
                    fillOpacity: 0.9, 
                    strokeColor: colors.high,
                    strokeOpacity: 0.5,
                    strokeWidth: 12,
                    pointRadius: 20,
                    label: "${count}",
                    labelOutlineWidth: 1,
                    fontColor: "#ffffff",
                    fontOpacity: 0.8,
                    fontSize: "12px"
                }
});           
// Create a Style that uses the three previous rules
            var style = new OpenLayers.Style(null, {
                rules: [singleRule,lowRule, middleRule, highRule]
});   

function init() {               
    map = new OpenLayers.Map('map');
    var wms = new OpenLayers.Layer.WMS(
                    "District Band", "/geoserver/wms/",
                    {layers: 'data:ICT_BND'}
    );
    var layer = new OpenLayers.Layer.Vector("WFS", {                    
                    protocol: new OpenLayers.Protocol.WFS({
                        version: "1.1.0",
                        url:  "/geoserver/wfs",
                        featurePrefix: 'data', //geoserver workspace name
                        featureType: "sites",
                        featureNS: "www.wru.scl.com",
                        geometryName: "SP_GEOMETRY" 
                    }),
                    //new OpenLayers.Strategy.Fixed()
                      strategies: [
                                        new OpenLayers.Strategy.BBOX(),
                                        new OpenLayers.Strategy.AnimatedCluster({
                                            distance: 45,
                                            animationMethod: OpenLayers.Easing.Expo.easeOut,
                                            animationDuration: 10
                                        })
                                  ],
                    styleMap: new OpenLayers.StyleMap(style)
});

map.addLayers([wms, layer]);
map.setCenter(new OpenLayers.LonLat(85.522137, 27.629811), 10);

Intended Result:

Different labelling at different points. First the label should be zone and then district and then siteid

I am trying really hard to achieve this, is this possible?

Best Answer

Using context, you can customise label text. This way you can display district, zone and siteid simultaneously. By defining many styles, you can only activate one at a time, i.e, either district, zone or siteid.

Here is an example

getgroup =function(feature){
    if(feature.count==1){
        return "single";
    }else if(feature.count>1 && feature.count<15){
        return "low";
    }else if(feature.count>15 && feature.count<50){
        return "medium";
    }else{
        return "high";
    }
};
var SingleStyle = new OpenLayers.Style({
    fillColor: "${color}",
    fillOpacity: "${opacity}", 
    label: "${text}",
    context:{
        color: colors[getgroup(feature)],
        opacity: opacity[getgroup(feature)],
        text: function(group = getgroup(feature)){
            if(group=="single"){
                return feature.siteid;
            }else if(group=="low"){
                return feature.district;
            }else if(group=="medium"){
                return feature.district;
            }else{
                return feature.zone;
            }
        }
    }
});