add an Extend Cluster Strategy example, provided by Marc Jansen, no functional change to the library, r=me (closes #2865)
git-svn-id: http://svn.openlayers.org/trunk/openlayers@10811 dc9f47b5-9b13-0410-9fdd-eb0c1a62fdaf
This commit is contained in:
122
examples/strategy-cluster-extended.html
Normal file
122
examples/strategy-cluster-extended.html
Normal file
@@ -0,0 +1,122 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Extended clustering example</title>
|
||||
<link rel="stylesheet" href="../theme/default/style.css" type="text/css">
|
||||
<link rel="stylesheet" href="style.css" type="text/css">
|
||||
<style type="text/css">
|
||||
label {
|
||||
cursor: pointer
|
||||
}
|
||||
|
||||
#wrap {
|
||||
width: 925px;
|
||||
margin: 10px;
|
||||
}
|
||||
|
||||
#strategy-chooser, #generalinfo, #info {
|
||||
width: 400px;
|
||||
padding: 0;
|
||||
float: right;
|
||||
clear: right;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
#map {
|
||||
float: left;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1 id="title">Extended clustering</h1>
|
||||
<div id="tags">
|
||||
cluster, advanced
|
||||
</div>
|
||||
<p id="shortdesc">
|
||||
Shows the usage of custom classes for a fine grained control about
|
||||
the clustering behaviour.
|
||||
</p>
|
||||
<div id="wrap">
|
||||
<div id="map" class="smallmap">
|
||||
</div>
|
||||
<div id="strategy-chooser">
|
||||
<p>
|
||||
Select the desired clustering strategy:
|
||||
</p>
|
||||
<label>
|
||||
<input type="radio" name="strategy" value="none" id="no-strategy" checked="checked">No strategy
|
||||
</label>
|
||||
<br/>
|
||||
<label>
|
||||
<input type="radio" name="strategy" value="cluster" id="cluster-strategy">Simple cluster-strategy
|
||||
</label>
|
||||
<br/>
|
||||
<label>
|
||||
<input type="radio" name="strategy" value="attribute-cluster" id="attributive-cluster-strategy">Attributive cluster-strategy
|
||||
</label>
|
||||
<br/>
|
||||
<label>
|
||||
<input type="radio" name="strategy" value="rule-cluster" id="rulebased-cluster-strategy">Rulebased cluster-strategy
|
||||
</label>
|
||||
</div>
|
||||
<div id="generalinfo">
|
||||
</div>
|
||||
<div id="info">
|
||||
</div>
|
||||
</div>
|
||||
<div id="docs" style="clear: both; padding-top: 10px">
|
||||
<p>
|
||||
The vectorlayer in this example contains random data with an
|
||||
attribute "clazz" that can take the values 1, 2, 3 and 4. The
|
||||
features with clazz = 4 are considered more important than the
|
||||
others.
|
||||
</p>
|
||||
<p>
|
||||
The radiobuttons on the right of the map control the
|
||||
cluster strategy to be applied to the features.
|
||||
</p>
|
||||
<ul>
|
||||
<li>
|
||||
<strong>No strategy</strong>
|
||||
means that all features are
|
||||
rendered, no clustering shall be applied
|
||||
</li>
|
||||
<li>
|
||||
<strong>Simple cluster-strategy</strong>
|
||||
applies the cluster
|
||||
strategy with default options to the layer. You should notice
|
||||
that many of the important features with clazz = 4 are getting
|
||||
lost, since clustering happens regardless of feature attributes
|
||||
</li>
|
||||
<li>
|
||||
<strong>Attributive cluster-strategy</strong>
|
||||
uses a
|
||||
customized cluster strategy. This strategy is configured to
|
||||
cluster features of the same clazz only. You should be able to see all
|
||||
red points (clazz = 4) even though the data is clustered. A
|
||||
cluster now contains only features of the same clazz.
|
||||
</li>
|
||||
<li>
|
||||
<strong>Rulebased cluster-strategy</strong>
|
||||
uses another
|
||||
customized cluster strategy. This strategy is configured to
|
||||
cluster features that follow a certain rule only. In this case only
|
||||
features with a clazz different from 4 are considered as
|
||||
candidates for clustering. That means that usually you have fewer
|
||||
clusters on the map, yet all with clazz = 4 are easily
|
||||
distinguishable
|
||||
</li>
|
||||
</ul>
|
||||
<p>
|
||||
Hover over the features to get a short infomation about the
|
||||
feature or cluster of features.
|
||||
</p>
|
||||
</div>
|
||||
<p>
|
||||
View the <a href="strategy-cluster-extended.js" target="_blank">strategy-cluster-extended.js</a>
|
||||
source to see how this is done.
|
||||
</p>
|
||||
<script type="text/javascript" src="../lib/OpenLayers.js"></script>
|
||||
<script type="text/javascript" src="strategy-cluster-extended.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
247
examples/strategy-cluster-extended.js
Normal file
247
examples/strategy-cluster-extended.js
Normal file
@@ -0,0 +1,247 @@
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
$('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.';
|
||||
$('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;
|
||||
}
|
||||
}
|
||||
})();
|
||||
Reference in New Issue
Block a user