2

I have vector layer - WFS from GeoServer (Postgis). In the Postgis table there are some attributes e.g.: the_geom (of course), adr_adm, ... So I would like display label: adr_adm on features when they are unclustered. I'm looking for replay in:

Cluster Strategy different Labeling at Different Level

http://www.gistutor.com/openlayers/12-intermediate-openlayers-tutorials/40-styling-and-labeling-vector-layers-in-openlayers.html

http://openflights.org/blog/2009/10/21/customized-openlayers-cluster-strategies/ and many others

I wrote something like that but it still doesn't work. Label for unclustered features still undefined. When I remove cluster strategy features have properly labels.

(I can't get an attribute from an array of features clustered)

Please help me to improve my code.

Thanks for any reply. I greet.

My code:

    var map;
    var refresh = new OpenLayers.Strategy.Refresh({force: true, active: true});
    var extent = new OpenLayers.Bounds(
                2568598.39063282, 7000794.41264775,
                2586376.89361486, 7012360.91662176);
     OpenLayers.IMAGE_RELOAD_ATTEMPTS = 5;
    var colors = {
low: "#93b772", 
middle: "#f1d046",
high: "#fd9c73", 
s_low: "#465736", 
s_middle: "#9b862d", 
s_high: "#ac6a4e"
    };
    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.s_low,
    strokeOpacity: 0.2,
    strokeWidth: 9,
    pointRadius: 8,
    label: "${text}",
    context:{
        text: function(feature){ return feature.attributes.adr_adm; }
            }, 
    labelAlign: "cc",
    labelXOffset: 4,
    labelOutlineWidth: 0.5,
    fontColor: "#00376d",
    fontOpacity: 1,
    fontSize: "10px"
}
    });
    var lowRule = new OpenLayers.Rule({
filter: new OpenLayers.Filter.Comparison({
    type: OpenLayers.Filter.Comparison.BETWEEN,
    property: "count",
    lowerBoundary: 2,
    upperBoundary: 5
}),
symbolizer: {
    fillColor: colors.low,
    fillOpacity: 0.9, 
    strokeColor: colors.s_low,
    strokeOpacity: 0.2,
    strokeWidth: 11,
    pointRadius: 10,
    label: "${count}",
    labelOutlineWidth: 0.5,
    fontColor: "#00376d",
    fontOpacity: 1,
    fontSize: "10px"
}
    });
    var middleRule = new OpenLayers.Rule({
filter: new OpenLayers.Filter.Comparison({
    type: OpenLayers.Filter.Comparison.BETWEEN,
    property: "count",
    lowerBoundary: 5,
    upperBoundary: 15
}),
symbolizer: {
    fillColor: colors.middle,
    fillOpacity: 0.9, 
    strokeColor: colors.s_middle,
    strokeOpacity: 0.2,
    strokeWidth: 13,
    pointRadius: 12,
    label: "${count}",
    labelOutlineWidth: 0.5,
    fontColor: "#00376d",
    fontOpacity: 1,
    fontSize: "10px"
}
    });
    var highRule = new OpenLayers.Rule({
filter: new OpenLayers.Filter.Comparison({
    type: OpenLayers.Filter.Comparison.GREATER_THAN,
    property: "count",
    value: 15
}),
symbolizer: {
    fillColor: colors.high,
    fillOpacity: 0.9, 
    strokeColor: colors.s_high,
    strokeOpacity: 0.2,
    strokeWidth: 15,
    pointRadius: 14,
    label: "${count}",
    labelOutlineWidth: 0.5,
    fontColor: "#00376d",
    fontOpacity: 1,
    fontSize: "10px"
}
    });
    // 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({
    div: "map",
    layers: [
        new OpenLayers.Layer.OSM("OpenStreetMapa")
        ],
    controls: [
        new OpenLayers.Control.Navigation(),
        new OpenLayers.Control.PanZoomBar(),
        new OpenLayers.Control.OverviewMap(),
        new OpenLayers.Control.LayerSwitcher({ascending: false}),
        new OpenLayers.Control.KeyboardDefaults(),
        new OpenLayers.Control.ScaleLine(),
        new OpenLayers.Control.Attribution()
      ],
    projection: "EPSG:3857",
    restrictedExtent: extent,
    }
);

var wc_layer = new OpenLayers.Layer.Vector("WC parametry", {
    strategies: [ new OpenLayers.Strategy.Fixed(),
                  new OpenLayers.Strategy.Cluster({distance: 40}), 
                  refresh],
                protocol: new OpenLayers.Protocol.WFS({
                url: "http://localhost/wfs_ant",  
                featureType: "v_wezly_param",   
                featureNS: "http://mapy.telemetria/"  
                })
                ,styleMap: new OpenLayers.StyleMap(style)
                ,attribution: '   © BB'
                ,extractAttributes: true
});
map.addLayer(wc_layer);

setInterval(function () { refresh.refresh(); },20000);

if(!map.getCenter()){
        map.zoomToExtent(extent);  
    }
         }
1

Clustered features do not have the same attributes as unclustered features. In your singleRule the attributes are in:

label: "${text}",
context:{
    text: function(feature) {
        return feature.cluster[0].attributes.adr_adm;
    }
}, 

Alternatively, you could adapt your context to take care of this:

label: "${text}",
context:{
    text: function(feature) {
        if(feature.cluster && feature.cluster.length == 1)
            return feature.cluster[0].attributes.adr_adm;
        else if(!feature.cluster)
            return feature.attributes.adr_adm;
        return feature.attributes.count;
    }
}, 

Note that you can also set a threshold in your strategy to not cluster the points have no neighbour. this way you will have access to the attributes when the feature is not in a cluster:

new OpenLayers.Strategy.Cluster({
    distance: 40,
    threshold: 1
})
  • Thanks alot for Your answer. Tomorrow I will look at it's. – Bear Dec 10 '13 at 14:06
1

And I have answer for my question. May someone be useful...

block context should be placed after styling block, e.g.:

    var style = new OpenLayers.Style(
    { fillColor: ...,
      label: "${val}"
    } ,
    { context: {
        val: function(feature) {
        if(feature.cluster.length > 1) 
            {
        var sumValue = 0;
        for (var i=0; i<feature.cluster.length; i++) 
         {
              sumValue += parseFloat(feature.cluster[i].attributes.tzewn);
         }
        var averageValue = (sumValue/feature.cluster.length).toFixed(1);
        return averageValue;
            } 
        else  
        var Value = feature.cluster[0].attributes.tzewn;
        return Value; //"1";
                                      }
          }
    }
    );

or in separate blocks: rule, styles

    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, 
    label: "${val} [st.C]", 
                }
    });

    var style = new OpenLayers.Style(null, {
     rules: [singleRule, lowRule, middleRule, highRule], 
     context: {
            val: function(feature) {
                if(feature.cluster.length > 1) {
                    var sumValue = 0;
                    for (var i=0; i<feature.cluster.length; i++) 
                    {
                        sumValue += parseFloat(feature.cluster[i].attributes.tzewn);
                    }
                    var averageValue = (sumValue/feature.cluster.length).toFixed(1);
                    return averageValue; 
                                                } 
                else  
                    var Value = feature.cluster[0].attributes.tzewn;
                    return Value; //"1";
                                    }
        }

} );

0

I'm doing something wrong. Even when I'll put:

    context:{ 
    text: function(feature) { 
    if(feature.cluster && feature.cluster.length == 1)
              return "1"; 
    else if(!feature.cluster)
              return "2"; 
                        }
            },      

I have still undefined unclustered feature.
If you were so kind as to check the correctness of my code above. Maybe I insert context:{} in wrong place... I don't know.

Many thanks in anticipation. And have a nice day (:

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.