因此,我在OpenLayers中聚集了许多项目。
我正在使用一种根据项目属性对项目进行聚类的策略。
我更改了项目的属性。
如何获得群集策略以重新计算群集?
最佳答案
好的,事实证明,从2.11RC1开始,此功能在OpenLayers中不可用。因此,我自己将其实现为Cluster类的影子。该代码也可以在OpenLayers Trac中作为补丁获得。
此答案末尾的代码可以直接放入javascript文件中,并将覆盖现有的OpenLayers OpenLayers.Strategy.Cluster
类。它添加了recluster
方法,该方法在被调用时将导致该策略重新计算其聚类。由于我们要更改Cluster
基类,因此任何派生类都应适当继承recluster
方法。
如何使用它的一个例子是:
var clustering=new OpenLayers.Strategy.Cluster()
var vectorlayer = new OpenLayers.Layer.Vector('Vectorlayer', {
strategies: [clustering]
});
//ADD_LOTS_OF_FEATURES_TO_VECTOR_LAYER
clustering.distance=value;
clustering.recluster();
替换类的代码为:
OpenLayers.Strategy.Cluster = OpenLayers.Class(OpenLayers.Strategy, {
/**
* APIProperty: distance
* {Integer} Pixel distance between features that should be considered a
* single cluster. Default is 20 pixels.
*/
distance: 20,
/**
* APIProperty: threshold
* {Integer} Optional threshold below which original features will be
* added to the layer instead of clusters. For example, a threshold
* of 3 would mean that any time there are 2 or fewer features in
* a cluster, those features will be added directly to the layer instead
* of a cluster representing those features. Default is null (which is
* equivalent to 1 - meaning that clusters may contain just one feature).
*/
threshold: null,
/**
* Property: features
* {Array(<OpenLayers.Feature.Vector>)} Cached features.
*/
features: null,
/**
* Property: clusters
* {Array(<OpenLayers.Feature.Vector>)} Calculated clusters.
*/
clusters: null,
/**
* Property: clustering
* {Boolean} The strategy is currently clustering features.
*/
clustering: false,
/**
* Property: resolution
* {Float} The resolution (map units per pixel) of the current cluster set.
*/
resolution: null,
/**
* Constructor: OpenLayers.Strategy.Cluster
* Create a new clustering strategy.
*
* Parameters:
* options - {Object} Optional object whose properties will be set on the
* instance.
*/
/**
* APIMethod: activate
* Activate the strategy. Register any listeners, do appropriate setup.
*
* Returns:
* {Boolean} The strategy was successfully activated.
*/
activate: function() {
var activated = OpenLayers.Strategy.prototype.activate.call(this);
if(activated) {
this.layer.events.on({
"beforefeaturesadded": this.cacheFeatures,
"moveend": this.cluster,
scope: this
});
}
return activated;
},
/**
* APIMethod: deactivate
* Deactivate the strategy. Unregister any listeners, do appropriate
* tear-down.
*
* Returns:
* {Boolean} The strategy was successfully deactivated.
*/
deactivate: function() {
var deactivated = OpenLayers.Strategy.prototype.deactivate.call(this);
if(deactivated) {
this.clearCache();
this.layer.events.un({
"beforefeaturesadded": this.cacheFeatures,
"moveend": this.cluster,
scope: this
});
}
return deactivated;
},
/**
* Method: cacheFeatures
* Cache features before they are added to the layer.
*
* Parameters:
* event - {Object} The event that this was listening for. This will come
* with a batch of features to be clustered.
*
* Returns:
* {Boolean} False to stop features from being added to the layer.
*/
cacheFeatures: function(event) {
var propagate = true;
if(!this.clustering) {
this.clearCache();
this.features = event.features;
this.cluster();
propagate = false;
}
return propagate;
},
/**
* Method: clearCache
* Clear out the cached features.
*/
clearCache: function() {
this.features = null;
},
/**
* Method: cluster
* Cluster features based on some threshold distance.
*
* Parameters:
* event - {Object} The event received when cluster is called as a
* result of a moveend event.
*/
cluster: function(event) {
if((!event || event.zoomChanged || (event && event.recluster)) && this.features) {
var resolution = this.layer.map.getResolution();
if(resolution != this.resolution || !this.clustersExist() || (event && event.recluster)) {
this.resolution = resolution;
var clusters = [];
var feature, clustered, cluster;
for(var i=0; i<this.features.length; ++i) {
feature = this.features[i];
if(feature.geometry) {
clustered = false;
for(var j=clusters.length-1; j>=0; --j) {
cluster = clusters[j];
if(this.shouldCluster(cluster, feature)) {
this.addToCluster(cluster, feature);
clustered = true;
break;
}
}
if(!clustered) {
clusters.push(this.createCluster(this.features[i]));
}
}
}
this.layer.removeAllFeatures();
if(clusters.length > 0) {
if(this.threshold > 1) {
var clone = clusters.slice();
clusters = [];
var candidate;
for(var i=0, len=clone.length; i<len; ++i) {
candidate = clone[i];
if(candidate.attributes.count < this.threshold) {
Array.prototype.push.apply(clusters, candidate.cluster);
} else {
clusters.push(candidate);
}
}
}
this.clustering = true;
// A legitimate feature addition could occur during this
// addFeatures call. For clustering to behave well, features
// should be removed from a layer before requesting a new batch.
this.layer.addFeatures(clusters);
this.clustering = false;
}
this.clusters = clusters;
}
}
},
/**
* Method: recluster
* User-callable function to recluster features
* Useful for instances where a clustering attribute (distance, threshold, ...)
* has changed
*/
recluster: function(){
var event={"recluster":true};
this.cluster(event);
},
/**
* Method: clustersExist
* Determine whether calculated clusters are already on the layer.
*
* Returns:
* {Boolean} The calculated clusters are already on the layer.
*/
clustersExist: function() {
var exist = false;
if(this.clusters && this.clusters.length > 0 &&
this.clusters.length == this.layer.features.length) {
exist = true;
for(var i=0; i<this.clusters.length; ++i) {
if(this.clusters[i] != this.layer.features[i]) {
exist = false;
break;
}
}
}
return exist;
},
/**
* 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 = cluster.geometry.getBounds().getCenterLonLat();
var fc = feature.geometry.getBounds().getCenterLonLat();
var distance = (
Math.sqrt(
Math.pow((cc.lon - fc.lon), 2) + Math.pow((cc.lat - fc.lat), 2)
) / this.resolution
);
return (distance <= this.distance);
},
/**
* Method: addToCluster
* Add a feature to a cluster.
*
* Parameters:
* cluster - {<OpenLayers.Feature.Vector>} A cluster.
* feature - {<OpenLayers.Feature.Vector>} A feature.
*/
addToCluster: function(cluster, feature) {
cluster.cluster.push(feature);
cluster.attributes.count += 1;
},
/**
* Method: createCluster
* Given a feature, create a cluster.
*
* Parameters:
* feature - {<OpenLayers.Feature.Vector>}
*
* Returns:
* {<OpenLayers.Feature.Vector>} A cluster.
*/
createCluster: function(feature) {
var center = feature.geometry.getBounds().getCenterLonLat();
var cluster = new OpenLayers.Feature.Vector(
new OpenLayers.Geometry.Point(center.lon, center.lat),
{count: 1}
);
cluster.cluster = [feature];
return cluster;
},
CLASS_NAME: "OpenLayers.Strategy.Cluster"
});
关于javascript - OpenLayers群集重新计算,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/6457437/