He intentado todo con mis (lamentablemente limitados) conocimientos de JavaScript para establecer el clip dinámicamente en la capa seleccionada. No he conseguido guardar y restaurar todo el contexto del lienzo, ni el de la capa. He intentado desvincular el evento de la capa, sin suerte. Tampoco strUser.un(evt, func)
o evt.stopPropagation()
se ha resuelto. Por ello, consideré que la capa recortada era irrecuperable y se me ocurrió un truco para resolver este problema.
He creado 3 capas recortadas junto con las 3 originales, y luego las he quitado y añadido sistemáticamente según la elección del usuario.
Entrada HTML:
<select onChange="change(this.value)" id="mySelect">
<option label="roads" value="roads" selected></option>
<option label="imagery" value="imagery"></option>
<option label="osm" value="osm" selected></option>
Creación de capas:
var roads = new ol.layer.Tile({
source: new ol.source.MapQuest({layer: 'sat'})
});
var roads_clipped = new ol.layer.Tile({
source: new ol.source.MapQuest({layer: 'sat'})
});
var imagery = new ol.layer.Tile({
source: new ol.source.Stamen({
layer: 'watercolor'
})
});
var imagery_clipped = new ol.layer.Tile({
source: new ol.source.Stamen({
layer: 'watercolor'
})
});
var osm = new ol.layer.Tile({
source: new ol.source.OSM(),
visible: true
});
var osm_clipped = new ol.layer.Tile({
source: new ol.source.OSM(),
visible: true
});
var map = new ol.Map({
layers: [roads, imagery, osm_clipped],
target: 'map',
view: new ol.View({
center: ol.proj.transform([-109, 46.5], 'EPSG:4326', 'EPSG:3857'),
zoom: 6
})
});
Tenga en cuenta que, he añadido la versión recortada del osm
en lugar de la versión normal, para inicializar el catalejo.
Eventos (posición del ratón y recorte):
var mousePosition = null;
$(map.getViewport()).on('mousemove', function (evt) {
mousePosition = map.getEventPixel(evt.originalEvent);
map.render();
}).on('mouseout', function () {
mousePosition = null;
map.render();
});
osm_clipped.on('precompose', function(event) {
var ctx = event.context;
var pixelRatio = event.frameState.pixelRatio;
ctx.save();
ctx.beginPath();
if (mousePosition) {
// only show a circle around the mouse
ctx.arc(mousePosition[0] * pixelRatio, mousePosition[1] * pixelRatio,
radius * pixelRatio, 0, 2 * Math.PI);
ctx.lineWidth = 5 * pixelRatio;
ctx.strokeStyle = 'rgba(0,0,0,0.5)';
ctx.stroke();
}
ctx.clip();
});
// after rendering the layer, restore the canvas context
osm_clipped.on('postcompose', function(event) {
var ctx = event.context;
ctx.restore();
});
imagery_clipped.on('precompose', function(event) {
var ctx = event.context;
var pixelRatio = event.frameState.pixelRatio;
ctx.save();
ctx.beginPath();
if (mousePosition) {
ctx.arc(mousePosition[0] * pixelRatio, mousePosition[1] * pixelRatio,
radius * pixelRatio, 0, 2 * Math.PI);
ctx.lineWidth = 5 * pixelRatio;
ctx.strokeStyle = 'rgba(0,0,0,0.5)';
ctx.stroke();
}
ctx.clip();
});
imagery_clipped.on('postcompose', function(event) {
var ctx = event.context;
ctx.restore();
});
roads_clipped.on('precompose', function(event) {
var ctx = event.context;
var pixelRatio = event.frameState.pixelRatio;
ctx.save();
ctx.beginPath();
if (mousePosition) {
ctx.arc(mousePosition[0] * pixelRatio, mousePosition[1] * pixelRatio,
radius * pixelRatio, 0, 2 * Math.PI);
ctx.lineWidth = 5 * pixelRatio;
ctx.strokeStyle = 'rgba(0,0,0,0.5)';
ctx.stroke();
}
ctx.clip();
});
roads_clipped.on('postcompose', function(event) {
var ctx = event.context;
ctx.restore();
});
Variable global para almacenar la última capa recortada:
var strUser = document.getElementById('mySelect').value;
Cambia de función:
function change(e) {
map.removeLayer(eval(strUser + '_clipped')); //remove the last added clipped layer
map.getLayers().getArray().splice(0,0,eval(strUser)); //add the normal version of it to the bottom of the stack
strUser = e; //get the new selection
map.removeLayer(eval(strUser)); //remove the normal version of the new selection
map.addLayer(eval(strUser + '_clipped')); //add the clipped version
};
También hay que tener en cuenta que se puede evaluar una cadena como variable con eval()
, si la variable existe con el mismo nombre que la cadena. Asegúrese de que el <option>
coinciden con los nombres de las variables de las capas.
Pista: uno de los principales desarrolladores de OL, @ erilem se puede encontrar en este sitio. Tal vez él puede proporcionar una solución adecuada, si usted le pide amablemente con el enlace a esta pregunta.