我有一个带有矢量源的矢量层,其加载非常昂贵,但渲染却不那么昂贵。我的GUI中有一个按钮,用于切换图层的可见性。 问题是,首次将可见性设置为true时,加载会花费很长时间。 我想在加载其余数据(来自所有可见层)的同时预先加载该层的数据,以便当可见性设置为true时,它只需要呈现它即可。 在Openlayers中有可能吗?
我尝试了各种方法,例如在“ precompose”上将可见性设置为true,然后在发送HTTP请求后(使用自定义的“ loadend”事件)将其设置为false,但是我无法使其正常工作;我无法关闭该层了。我猜想发生这种情况是因为在第一次加载之后,它已经缓存了数据,所以我的自定义“ loadend”事件不再触发。 无论如何,我希望有一个更优雅的解决方案。
编辑:
我不能像Mike的答案那样预先发送请求,因为没有 请求。该请求取决于范围以及投影,因此是在向量源的loader
函数中做出的。
答案 0 :(得分:1)
如果数据不会更改,则可以在创建图层时对其进行预加载。
这是一个没有预加载的示例。打开地图5秒钟后,将显示三个数据层。只有这样,向量源中指定的url才会请求数据,然后可以看到它们以不同的速度加载,因为其中一层必须下载40mb KML文件。
var raster_OSM = new ol.layer.Tile({
source: new ol.source.OSM()
});
var resolutions = ol.tilegrid.createXYZ().getResolutions();
var style_Cnty = new ol.style.Style({
stroke: new ol.style.Stroke({
color: '#3399CC',
width: 1.25
})
});
var vector_Cnty = new ol.layer.Vector({
source: new ol.source.Vector({
url: 'https://raw.githubusercontent.com/tanhe03/kml/master/gz_2010_us_050_00_500k.kml',
format: new ol.format.KML({extractStyles: false})
}),
maxResolution: resolutions[3],
style: function(feature, resolution) {
var styles = [ style_Cnty ];
if (resolution < resolutions[8]) {
var geom = feature.getGeometry();
styles.push(
new ol.style.Style({
geometry: geom.getInteriorPoints ? geom.getInteriorPoints() : geom.getInteriorPoint(),
text: new ol.style.Text({
font: 'bold 16px sans-serif',
fill: new ol.style.Fill({
color: '#3399CC'
}),
backgroundFill: new ol.style.Fill({
color: 'rgba(255,255,255,0.5)'
}),
text: feature.get('Name')
})
})
)
}
return styles;
},
visible: false
});
var vector_State = new ol.layer.Vector({
source: new ol.source.Vector({
url: 'https://raw.githubusercontent.com/tanhe03/kml/master/gz_2010_us_040_00_500k.kml',
format: new ol.format.KML({extractStyles: false})
}),
maxResolution: resolutions[1],
style: new ol.style.Style({
stroke: new ol.style.Stroke({
color: 'purple',
width: 1.25
})
}),
visible: false
});
var vector_US = new ol.layer.Vector({
source: new ol.source.Vector({
url: 'https://raw.githubusercontent.com/tanhe03/kml/master/gz_2010_us_outline_500k.kml',
format: new ol.format.KML({extractStyles: false})
}),
style: new ol.style.Style({
stroke: new ol.style.Stroke({
color: '#3399CC',
width: 1.25
})
}),
visible: false
});
var map = new ol.Map({
layers: [raster_OSM, vector_Cnty, vector_State, vector_US],
target: 'map',
view: new ol.View({
center: ol.proj.transform([-96, 38], 'EPSG:4326', 'EPSG:3857'),
zoom: 4
})
});
setTimeout(function(){
vector_Cnty.setVisible(true);
vector_State.setVisible(true);
vector_US.setVisible(true);
}, 5000);
html, body, .map {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
}
<link href="https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v5.3.0/css/ol.css" rel="stylesheet" />
<script src="https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v5.3.0/build/ol.js"></script>
<div id="map" class="map"></div>
但是在本例中,数据的预加载是在创建图层时开始的。 XHR立即请求URL,解析响应并将功能添加到源。在5秒钟后使这些图层可见后,所有三个图层都应该已经加载。
var raster_OSM = new ol.layer.Tile({
source: new ol.source.OSM()
});
var resolutions = ol.tilegrid.createXYZ().getResolutions();
var style_Cnty = new ol.style.Style({
stroke: new ol.style.Stroke({
color: '#3399CC',
width: 1.25
})
});
var vector_Cnty = new ol.layer.Vector({
source: new ol.source.Vector({
format: new ol.format.KML({extractStyles: false})
}),
maxResolution: resolutions[3],
style: function(feature, resolution) {
var styles = [ style_Cnty ];
if (resolution < resolutions[8]) {
var geom = feature.getGeometry();
styles.push(
new ol.style.Style({
geometry: geom.getInteriorPoints ? geom.getInteriorPoints() : geom.getInteriorPoint(),
text: new ol.style.Text({
font: 'bold 16px sans-serif',
fill: new ol.style.Fill({
color: '#3399CC'
}),
backgroundFill: new ol.style.Fill({
color: 'rgba(255,255,255,0.5)'
}),
text: feature.get('Name')
})
})
)
}
return styles;
},
visible: false
});
var vector_State = new ol.layer.Vector({
source: new ol.source.Vector({
format: new ol.format.KML({extractStyles: false})
}),
maxResolution: resolutions[1],
style: new ol.style.Style({
stroke: new ol.style.Stroke({
color: 'purple',
width: 1.25
})
}),
visible: false
});
var vector_US = new ol.layer.Vector({
source: new ol.source.Vector({
format: new ol.format.KML({extractStyles: false})
}),
style: new ol.style.Style({
stroke: new ol.style.Stroke({
color: '#3399CC',
width: 1.25
})
}),
visible: false
});
var xhr = new XMLHttpRequest();
xhr.open('GET', 'https://raw.githubusercontent.com/tanhe03/kml/master/gz_2010_us_050_00_500k.kml');
xhr.onload = function() {
var source = vector_Cnty.getSource();
source.addFeatures(source.getFormat().readFeatures(this.responseText, {featureProjection: 'EPSG:3857'}));
}
xhr.send();
var xhr = new XMLHttpRequest();
xhr.open('GET', 'https://raw.githubusercontent.com/tanhe03/kml/master/gz_2010_us_040_00_500k.kml');
xhr.onload = function() {
var source = vector_State.getSource();
source.addFeatures(source.getFormat().readFeatures(this.responseText, {featureProjection: 'EPSG:3857'}));
}
xhr.send();
var xhr = new XMLHttpRequest();
xhr.open('GET', 'https://raw.githubusercontent.com/tanhe03/kml/master/gz_2010_us_outline_500k.kml');
xhr.onload = function() {
var source = vector_US.getSource();
source.addFeatures(source.getFormat().readFeatures(this.responseText, {featureProjection: 'EPSG:3857'}));
}
xhr.send();
var map = new ol.Map({
layers: [raster_OSM, vector_Cnty, vector_State, vector_US],
target: 'map',
view: new ol.View({
center: ol.proj.transform([-96, 38], 'EPSG:4326', 'EPSG:3857'),
zoom: 4
})
});
setTimeout(function(){
vector_Cnty.setVisible(true);
vector_State.setVisible(true);
vector_US.setVisible(true);
}, 5000);
html, body, .map {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
}
<link href="https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v5.3.0/css/ol.css" rel="stylesheet" />
<script src="https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v5.3.0/build/ol.js"></script>
<div id="map" class="map"></div>
答案 1 :(得分:1)
如果要动态加载图层,则必须使其可见,否则将不发送请求。 一种有效的方法是使图层可见,但防止绘制要素(在样式函数中返回空样式)
var visible = false; // turn it to true to have the features drawn
var vector = new ol.layer.Vector({
source: new ol.source.Vector({
// your source definition
}),
visible: true,
style: function(feature, resolution) {
if (!visible) {
return [];
} else {
return your_style_for_the_feature;
}
}
});
将加载并绘制该图层,但由于未绘制要素,因此将看不到任何内容。只需将visible设置为true即可在样式函数中返回样式并进行绘制。
您还必须使用changed
函数告诉源代码必须重绘:
// Draw the layer
visible = true;
vector.getSource().changed();