Files
openlayers/examples/strategy-cluster-extended.js

248 lines
8.4 KiB
JavaScript

/**
* Class: OpenLayers.Strategy.AttributeCluster
* Strategy for vector feature clustering based on feature attributes.
*
* Inherits from:
* - <OpenLayers.Strategy.Cluster>
*/
OpenLayers.Strategy.AttributeCluster = OpenLayers.Class(OpenLayers.Strategy.Cluster, {
/**
* the attribute to use for comparison
*/
attribute: null,
/**
* Method: shouldCluster
* Determine whether to include a feature in a given cluster.
*
* Parameters:
* cluster - {<OpenLayers.Feature.Vector>} A cluster.
* feature - {<OpenLayers.Feature.Vector>} A feature.
*
* Returns:
* {Boolean} The feature should be included in the cluster.
*/
shouldCluster: function(cluster, feature) {
var cc_attrval = cluster.cluster[0].attributes[this.attribute];
var fc_attrval = feature.attributes[this.attribute];
var superProto = OpenLayers.Strategy.Cluster.prototype;
return cc_attrval === fc_attrval &&
superProto.shouldCluster.apply(this, arguments);
},
CLASS_NAME: "OpenLayers.Strategy.AttributeCluster"
});
/**
* Class: OpenLayers.Strategy.RuleCluster
* Strategy for vector feature clustering according to a given rule.
*
* Inherits from:
* - <OpenLayers.Strategy.Cluster>
*/
OpenLayers.Strategy.RuleCluster = OpenLayers.Class(OpenLayers.Strategy.Cluster, {
/**
* the rule to use for comparison
*/
rule: null,
/**
* Method: shouldCluster
* Determine whether to include a feature in a given cluster.
*
* Parameters:
* cluster - {<OpenLayers.Feature.Vector>} A cluster.
* feature - {<OpenLayers.Feature.Vector>} A feature.
*
* Returns:
* {Boolean} The feature should be included in the cluster.
*/
shouldCluster: function(cluster, feature) {
var superProto = OpenLayers.Strategy.Cluster.prototype;
return this.rule.evaluate(cluster.cluster[0]) &&
this.rule.evaluate(feature) &&
superProto.shouldCluster.apply(this, arguments);
},
CLASS_NAME: "OpenLayers.Strategy.RuleCluster"
});
// global variables
var map, vectorlayer, features, stylemap, select;
// wrap the instanciation code in an anonymous function that gets executed
// immeadeately
(function(){
// The function that gets called on feature selection: shows information
// about the feature/cluser in a div on the page
var showInformation = function(evt){
var feature = evt.feature;
var info = 'Last hovered feature:<br>';
if (feature.cluster) {
info += '&nbsp;&nbsp;Cluster of ' + feature.attributes.count + ' features:';
var clazzes = {
'1': 0,
'2': 0,
'3': 0,
'4': 0
};
for (var i = 0; i < feature.attributes.count; i++) {
var feat = feature.cluster[i];
clazzes[feat.attributes.clazz]++;
}
for (var j=1; j<=4; j++) {
var plural_s = (clazzes[j] !== 1) ? 's' : '';
info += '<br>&nbsp;&nbsp;&nbsp;&nbsp;&bull;&nbsp;clazz ' + j + ': ' + clazzes[j] + ' feature' + plural_s;
}
} else {
info += '&nbsp;&nbsp;Single feature of clazz = ' + feature.attributes.clazz;
}
document.getElementById('info').innerHTML = info;
};
// The function that gets called on feature selection. Shows information
// about the number of "points" on the map.
var updateGeneralInformation = function() {
var info = 'Currently ' + vectorlayer.features.length + ' points are shown on the map.';
document.getElementById('generalinfo').innerHTML = info;
};
// instanciate the map
map = new OpenLayers.Map("map");
// background WMS
var ol_wms = new OpenLayers.Layer.WMS("OpenLayers WMS", "http://vmap0.tiles.osgeo.org/wms/vmap0", {
layers: "basic"
});
// context to style the vectorlayer
var context = {
getColor: function(feature){
var color = '#aaaaaa';
if (feature.attributes.clazz && feature.attributes.clazz === 4) {
color = '#ee0000';
} else if(feature.cluster) {
var onlyFour = true;
for (var i = 0; i < feature.cluster.length; i++) {
if (onlyFour && feature.cluster[i].attributes.clazz !== 4) {
onlyFour = false;
}
}
if (onlyFour === true) {
color = '#ee0000';
}
}
return color;
}
};
// style the vectorlayer
stylemap = new OpenLayers.StyleMap({
'default': new OpenLayers.Style({
pointRadius: 5,
fillColor: "${getColor}",
fillOpacity: 0.7,
strokeColor: "#666666",
strokeWidth: 1,
strokeOpacity: 1,
graphicZIndex: 1
}, {
context: context
}),
'select' : new OpenLayers.Style({
pointRadius: 5,
fillColor: "#ffff00",
fillOpacity: 1,
strokeColor: "#666666",
strokeWidth: 1,
strokeOpacity: 1,
graphicZIndex: 2
})
});
// the vectorlayer
vectorlayer = new OpenLayers.Layer.Vector('Vectorlayer', {styleMap: stylemap, strategies: []});
// the select control
select = new OpenLayers.Control.SelectFeature(
vectorlayer, {hover: true}
);
map.addControl(select);
select.activate();
vectorlayer.events.on({"featureselected": showInformation});
map.addLayers([ol_wms, vectorlayer]);
map.addControl(new OpenLayers.Control.LayerSwitcher());
map.zoomToMaxExtent();
features = [];
// adding lots of features:
for (var i = 0; i < 700; i++) {
var r1 = Math.random();
var r2 = Math.random();
var r3 = Math.random();
var r4 = Math.random();
var px = r1 * 180 * ((r2 < 0.5) ? -1 : 1);
var py = r3 * 90 * ((r4 < 0.5) ? -1 : 1);
var p = new OpenLayers.Geometry.Point(px, py);
var clazz = (i % 10 === 0) ? 4 : Math.ceil(r4 * 3);
var f = new OpenLayers.Feature.Vector(p, {clazz: clazz});
features.push(f);
}
vectorlayer.addFeatures(features);
updateGeneralInformation();
// the behaviour and methods for the radioboxes
var changeStrategy = function() {
var strategies = [];
// this is the checkbox
switch(this.value) {
case 'cluster':
// standard clustering
strategies.push(new OpenLayers.Strategy.Cluster());
break;
case 'attribute-cluster':
// use the custom class: only cluster features of the same clazz
strategies.push(new OpenLayers.Strategy.AttributeCluster({
attribute:'clazz'
}));
break;
case 'rule-cluster':
// use the custom class: only cluster features that have a
// clazz smaller than 4
strategies.push(new OpenLayers.Strategy.RuleCluster({
rule: new OpenLayers.Rule({
filter: new OpenLayers.Filter.Comparison({
type: OpenLayers.Filter.Comparison.LESS_THAN,
property: "clazz",
value: 4
})
})
}));
break;
}
// remove layer and control
map.removeLayer(vectorlayer);
map.removeControl(select);
// rebuild layer
vectorlayer = new OpenLayers.Layer.Vector('Vectorlayer', {styleMap: stylemap, strategies: strategies});
map.addLayer( vectorlayer );
vectorlayer.addFeatures(features);
// rebuild select control
select = new OpenLayers.Control.SelectFeature(
vectorlayer, {hover: true}
);
map.addControl(select);
select.activate();
vectorlayer.events.on({"featureselected": showInformation});
// update meta information
updateGeneralInformation();
};
// bind the behviour to the radios
var inputs = document.getElementsByTagName('input');
for( var cnt = 0; cnt < inputs.length; cnt++) {
var input = inputs[cnt];
if (input.name === 'strategy') {
input.onclick = changeStrategy;
}
}
})();