以下问题已在“OL3 Dev”上提出,但已移至StackOverflow以符合组策略。
我一直在使用OpenLayers 3并实现了一个简单的测试应用程序,我在其中模拟地图上几个对象的移动。 我使用Vector层和相应的Vector源。
假设我有大约1000个ol.geom.Point几何特征,每20-30秒更新一次。
我可以通过修改几何坐标获得非常好的结果,结果很流畅并且工作正常。
现在,我尝试使用群集功能对已关闭的功能进行分组。不幸的是,在这种情况下,结果非常缓慢且不规则。 我认为问题是由于每次更改单个特征的几何时都会触发change()事件,所以我想知道:
有没有办法阻止群集立即考虑修改某个功能,并且只在特定时间间隔内触发?
下面你可以找到两个例子,第一个没有Cluster源,第二个带有它。
无群集:http://jsfiddle.net/sparezenny/dwLpmqvc/
var mySource = new ol.source.Vector({
features : new Array()
});
var myLayer = new ol.layer.Vector({
source: mySource,
style: function(feature, resolution) {
var myStyle = [new ol.style.Style({
image: new ol.style.Circle({
radius: 10,
stroke: new ol.style.Stroke({
color: '#fff'
}),
fill: new ol.style.Fill({
color: '#3399CC'
})
})
})];
return myStyle;
}
});
var map = new ol.Map({
target: 'map',
layers: [
new ol.layer.Tile({
source: new ol.source.MapQuest({layer: 'sat'})
}),
myLayer
],
view: new ol.View({
center: ol.proj.transform([37.41, 8.82], 'EPSG:4326', 'EPSG:3857'),
zoom: 4
})
});
var positions = new Array();
function Mock(id, longitude, latitude){
this.id=id;
this.latitude=latitude;
this.longitude=longitude;
};
function updatePositions(mocks){
var featuresToBeAdded = new Array();
for (var i=0; i < mocks.length; i++){
var mock = mocks[i];
var id = mock.id;
var previousPosition = positions[id];
var resultFeature;
var position;
// new
if (previousPosition==undefined || previousPosition==null){
position = ol.proj.transform([ mock.longitude, mock.latitude ],
'EPSG:4326', 'EPSG:3857');
positions[id] = mock;
resultFeature = new ol.Feature({
geometry: new ol.geom.Point(position)
});
featuresToBeAdded.push(resultFeature);
}
// update
else{
resultFeature = positions[id].feature;
positions[id] = mock;
position = ol.proj.transform([ mock.longitude, mock.latitude ],
'EPSG:4326', 'EPSG:3857');
resultFeature.getGeometry().setCoordinates(position);
}
positions[id].feature = resultFeature;
}
if (featuresToBeAdded.length>0){
mySource.addFeatures(featuresToBeAdded);
}
//map.render();
}
var myMocks = new Array(1000);
for (var i=0; i<1000; i++){
myMocks[i] = new Mock(i,
37.41+(Math.random()>0.5?0.01:-0.01)*i,
8.82 +(Math.random()>0.5?0.01:-0.01)*i);
}
setInterval(
function(){
var j = Math.round(Math.random()*980);
for (var i=0; i<20; i++){
myMocks[j+i].latitude = myMocks[j+i].latitude + (Math.random()>0.5?0.01:-0.01);
myMocks[j+i].longitude = myMocks[j+i].longitude + (Math.random()>0.5?0.01:-0.01);
}
console.debug("updatePositions..");
updatePositions(myMocks);
}, 5000);
群集:http://jsfiddle.net/sparezenny/gh7ox9nj/
var mySource = new ol.source.Vector({
features : new Array()
});
var clusterSource = new ol.source.Cluster({
distance: 10,
source: mySource
});
var myLayer = new ol.layer.Vector({
source: clusterSource,
style: function(feature, resolution) {
var clusteredFeatures = feature.get('features');
var size = feature.get('features').length;
var myStyle = [new ol.style.Style({
image: new ol.style.Circle({
radius: 10,
stroke: new ol.style.Stroke({
color: '#fff'
}),
fill: new ol.style.Fill({
color: '#3399CC'
})
}),
text: new ol.style.Text({
text: size.toString(),
fill: new ol.style.Fill({
color: '#fff'
})
})
})];
return myStyle;
}
});
var map = new ol.Map({
target: 'map',
layers: [
new ol.layer.Tile({
source: new ol.source.MapQuest({layer: 'sat'})
}),
myLayer
],
view: new ol.View({
center: ol.proj.transform([37.41, 8.82], 'EPSG:4326', 'EPSG:3857'),
zoom: 4
})
});
var positions = new Array();
function Mock(id, longitude, latitude){
this.id=id;
this.latitude=latitude;
this.longitude=longitude;
};
function updatePositions(mocks){
var featuresToBeAdded = new Array();
for (var i=0; i < mocks.length; i++){
var mock = mocks[i];
var id = mock.id;
var previousPosition = positions[id];
var resultFeature;
var position;
// new
if (previousPosition==undefined || previousPosition==null){
position = ol.proj.transform([ mock.longitude, mock.latitude ],
'EPSG:4326', 'EPSG:3857');
positions[id] = mock;
resultFeature = new ol.Feature({
geometry: new ol.geom.Point(position)
});
featuresToBeAdded.push(resultFeature);
}
// update
else{
resultFeature = positions[id].feature;
positions[id] = mock;
position = ol.proj.transform([ mock.longitude, mock.latitude ],
'EPSG:4326', 'EPSG:3857');
resultFeature.getGeometry().setCoordinates(position);
}
positions[id].feature = resultFeature;
}
if (featuresToBeAdded.length>0){
mySource.addFeatures(featuresToBeAdded);
}
//map.render();
}
var myMocks = new Array(1000);
for (var i=0; i<1000; i++){
myMocks[i] = new Mock(i,
37.41+(Math.random()>0.5?0.01:-0.01)*i,
8.82 +(Math.random()>0.5?0.01:-0.01)*i);
}
setInterval(
function(){
var j = Math.round(Math.random()*980);
for (var i=0; i<20; i++){
myMocks[j+i].latitude = myMocks[j+i].latitude + (Math.random()>0.5?Math.random()*0.01:-Math.random()*0.01);
myMocks[j+i].longitude = myMocks[j+i].longitude + (Math.random()>0.5?Math.random()*0.01:-Math.random()*0.01);
}
console.debug("updatePositions..");
updatePositions(myMocks);
}, 5000);
你可以看到我有1000个功能,我尝试每5秒更新一次20个的位置。 在第一种情况下,与地图的交互是平滑的,而在第二种情况下,它经常停止或减慢。
有关如何避免这种情况的任何线索或建议?
提前致谢
答案 0 :(得分:1)
现在这是一个旧链接,但由于我遇到了完全相同的问题,我认为我会发布我的解决方案。
这个想法是削弱群集源中的违规事件处理程序,并且每帧渲染时只触发相同的代码。
请注意所显示的代码:
if (ol.source.Cluster.prototype.onSourceChange_)
{
// Make a new pointer to the old sourceChange function.
ol.source.Cluster.prototype.newSourceChange =
ol.source.Cluster.prototype.onSourceChange_;
// Nuke the old function reference.
ol.source.Cluster.prototype.onSourceChange_ = function() {};
}
if (ol.source.Cluster.prototype.Ra)
{
// As above, but for non-debug code.
ol.source.Cluster.prototype.newSourceChange =
ol.source.Cluster.prototype.Ra;
ol.source.Cluster.prototype.Ra = function() {};
}
// Later on..
map.on('postrender', clusterSource.newSourceChange, clusterSource);
正如您所看到的,即使更新时间为100毫秒,也能轻松处理1000个功能。