当我在Openlayers中加载超过500个矢量功能时,平板电脑和电话上的性能会大大降低。我的解决方案是清除地图moveend
事件中的源。这种方法有效,但是会导致令人讨厌的闪烁,大概是在清除源和重新加载源之间。
对此“闪烁” here的较早解决方案不再起作用,它导致对WFS的递归调用。
这是我当前的代码:
import {GeoJSON} from 'ol/format';
import {bbox as bboxStrategy} from 'ol/loadingstrategy.js';
import VectorSource from 'ol/source/Vector.js';
import VectorLayer from 'ol/layer/Vector';
var vectorSource = new VectorSource({
format: new GeoJSON({ dataProjection: layerProjection }),
loader: function(extent, resolution, projection) {
var proj = projection.getCode();
var url = 'https://xxx.xxx/geoserver/wfs?service=WFS' +
'&version=1.1.0&request=GetFeature&typename=' + layer +
'&maxFeatures=200&outputFormat=application/json&srsname=' + proj +
'&bbox=' + extent.join(',') + ',' + proj;
var xhr = new XMLHttpRequest();
xhr.open('GET', url);
var onError = function() {
vectorSource.removeLoadedExtent(extent);
}
xhr.onerror = onError;
xhr.onload = function() {
if (xhr.status == 200) {
//vectorSource.clear();// Causes recursion
vectorSource.addFeatures(
vectorSource.getFormat().readFeatures(xhr.responseText));
} else {
onError();
}
}
xhr.send();
},
strategy: bboxStrategy
});
var vector = new VectorLayer({
source: vectorSource,
style: style,
visible: visible
});
map.on('moveend', function(evt) {
console.log('refreshing vector');
vectorSource.clear()
});
有没有办法避免Openlayers 5中的清除/重新加载闪存?还是我应该使用另一种方法来加载矢量层(我拥有的层通常是具有5000到10000个要素的点层)。
[编辑] @ahocevar发表评论后,这是我使用的样式:
import {Style, Circle, Fill, Stroke} from 'ol/style';
import Defaults from './PointDefaults';
export default function() {
return new Style({
image: new Circle({
radius: Defaults.radius,
fill: new Fill({
color: 'green',
}),
stroke: new Stroke({
color: Defaults.strokeColor,
width: Defaults.strokeWidth
})
}),
});
}
答案 0 :(得分:1)
不要清除每个moveend上的源,只有当它超过许多功能max
时,这才可以防止重新加载太频繁:
map.on('moveend', function(evt) {
if (vectorSource.getFeatures().length > max) {
vectorSource.clear()
}
});
即使在速度较慢的设备上,Openlayers也应能够显示500多个功能。
renderMode: 'image'
选项,以便在交互和动画期间更快地渲染。例如,即使在移动设备上,此网站也显示超过18.000个点要素:https://c-conforme.fr
答案 1 :(得分:1)
问题在于,您正在为每个渲染帧上的每个功能创建具有新Style
图像的新Circle
。在您的情况下,您甚至不需要样式功能,因为所有功能的样式都相同。因此,您的style
模块应导出样式,而不是返回样式的函数:
import {Style, Circle, Fill, Stroke} from 'ol/style';
import Defaults from './PointDefaults';
export default new Style({
image: new Circle({
radius: Defaults.radius,
fill: new Fill({
color: 'green',
}),
stroke: new Stroke({
color: Defaults.strokeColor,
width: Defaults.strokeWidth
})
})
});
答案 2 :(得分:0)
2 年后,我找到了一个解决方案,它不是非常“浮华”,但有点(我认为我对这个问题的措辞一定太含糊了)。
我正在使用 vectorSource.refresh()
给这个:
map.on('moveend', function(evt) {
console.log('refreshing vector');
vectorSource.refresh()
});
我现在使用的 OpenLayers 版本是 v6.5.0