248 lines
8.4 KiB
JavaScript
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 += ' 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> • clazz ' + j + ': ' + clazzes[j] + ' feature' + plural_s;
|
|
}
|
|
} else {
|
|
info += ' 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;
|
|
}
|
|
}
|
|
})();
|