6
A
回答
13
好吧,事实证明,这个功能在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"
});
1
OpenLayers.Strategy.Cluster.cluster方法仅重新计算,如果它是一个zoomechanged事件或簇对象不存在。删除群集对象并调用群集对象上的群集。
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;
//cluster() recalculate only if it is a zoomechanged event or clusters object does not exist.
clustering.clusters = null; //remove cluster object so that it calculates again.
clustering.cluster();
相关问题
- 1. 集群计算
- 2. 的OpenLayers放大集群
- 3. OpenLayers 4缩放到集群
- 4. Apache Ignite计算群集
- 5. F#+ MPI + MONO:集群计算
- 6. 在哈希集中计算集群
- 7. 集群系统上的Java并行处理(集群计算)
- 8. 所有群集计算库是否与星群集兼容?
- 9. 使用Microsoft Azure作为计算集群
- 10. 计算机集群中的python库
- 11. 计算的集装箱字段将不会重新计算
- 12. C#适用于群集计算繁重的应用程序吗?
- 13. .net在计算机集群上的并行计算
- 14. setInterval重新计算?
- 15. Excel重新计算
- 16. 刷新/重新计算CSS
- 17. 重新启动终止emr集群
- 18. 如何估算HPC群集上的计算时间
- 19. 强制重新列表重新计算
- 20. 如何估算Hadoop集群?
- 21. 计算时间差重新
- 22. 重新计算单元格
- 23. Excel中重新计算
- 24. 解释RDD重新计算
- 25. 缓存与重新计算
- 26. 重新计算预测
- 27. XML SDK重新计算值
- 28. 如何运行计算并计算远程Hadoop集群的进程?
- 29. OpenLayers如何计算边界框坐标?
- 30. D3集群布局设计
非常好,这正是我所需要的!几件事情...... 1)您可以将其添加到核心js(cluster.js),然后重新构建您自己的自定义OpenLayers.js以避免必须重新实现所有这些。或者.. 2)您可以将这些方法添加到课程中,而不必重新编写整个课程。 –
好点,@Matt。我的首选方法是将它作为OpenLayers的一部分。这是门票#3384,自2011-06-23开始运行。也许它会变成v2.13 ... :-) – Richard
如果我可以在票上投票,我会做;) –