Aragon, your answer pointed me in the right direction. Below is my final unclean code for adding layers to an array and then controling them.
In a javascript file I initialized the map and used a function to toggle visibility as follows:
//Layer array
var layersArray = [];
//Map view (Initial location)
var view = new ol.View2D({
// the view's initial state
center: ol.proj.transform([*Lat*,*Long*], 'EPSG:4326', 'EPSG:3857'),
zoom: 12
});
/* Map Initialization */
function initializeMap(){
var esribase = new ol.layer.Tile({
preload: Infinity,
source: new ol.source.XYZ({
url: 'http://server.arcgisonline.com/ArcGIS/rest/services/' +
'World_Topo_Map/MapServer/tile/{z}/{y}/{x}'
})
});
var poly1 = new ol.layer.Tile({
source: new ol.source.TileWMS({
url: 'http://localhost:8080/geoserver/wms',
params: {'LAYERS': '*Workspace*:*Layer*', 'TILED': true}
})
});
poly1.setVisible(false);
var poly2 = new ol.layer.Tile({
source: new ol.source.TileWMS({
url: 'http://localhost:8080/geoserver/wms',
params: {'LAYERS': '*Workspace*:*Layer*', 'TILED': true}
})
});
poly2.setVisible(false);
var poly3 = new ol.layer.Tile({
source: new ol.source.TileWMS({
url: 'http://localhost:8080/geoserver/wms',
params: {'LAYERS': '*Workspace*:*Layer*', 'TILED': true}
})
});
poly3.setVisible(false);
layersArray.push(esribase); //0
layersArray.push(poly1); //1
layersArray.push(poly2); //2
layersArray.push(poly3);//3
var map = new ol.Map({
controls: ol.control.defaults().extend([
new ol.control.ScaleLine({
units: ol.control.ScaleLineUnits.METRIC
})
]),
renderer: ol.RendererHint.CANVAS,
target: 'map',
layers: layersArray,
view:view
});
}
// Layer visibility function
function layerswitch(evt){
layersArray[evt.value].setVisible(evt.checked);
}
In the HTML I used simple checkboxes (example of poly1 toggle):
<input style='cursor:pointer' type="checkbox" value="1" onclick="javascript:layerswitch(this)" class="Cpoly1" name="poly1check" id="poly1check"/><label id="poly1checkLabel" for="poly1check">Polygon 1 Layer Switcher</label>
Here's an example that accomplishes what you want (I think):
http://jsfiddle.net/tschaub/Lkgx0qaa/
I've created a map with three layers, only the first one (named roads
) is visible:
var roads = new ol.layer.Tile({
source: new ol.source.BingMaps({key: key, imagerySet: 'Road'})
});
var clipped = {
imagery: new ol.layer.Tile({
source: new ol.source.BingMaps({key: key, imagerySet: 'Aerial'}),
visible: false
}),
labeled: new ol.layer.Tile({
source: new ol.source.BingMaps({key: key, imagerySet: 'AerialWithLabels'}),
visible: false
})
};
var map = new ol.Map({
layers: [roads, clipped.imagery, clipped.labeled],
target: 'map',
view: new ol.View({
center: ol.proj.transform([-109, 46.5], 'EPSG:4326', 'EPSG:3857'),
zoom: 6
})
});
The imagery
and labeled
layers are going to be toggled on/off with radio inputs. When a radio input is checked, the layer is made visible (with layer.setVisible(true)
), and listeners are registered for precompose
and postcompse
events (with layer.on(...)
).
In addition, any previously chosen layer will be made invisible (with layer.setVisible(false)
), and listeners will be unregistered (with layer.un(...)
).
The function that handles this radio change event looks like this:
var chosen;
function onRadioChange(event) {
if (chosen) {
chosen.un('precompose', onPreCompose);
chosen.un('postcompose', onPostCompose);
chosen.setVisible(false);
}
chosen = clipped[event.target.value];
chosen.on('precompose', onPreCompose);
chosen.on('postcompose', onPostCompose);
chosen.setVisible(true);
}
That's really the meat of the solution. The rest pretty much follows the hosted layer-spy.html example.
For completeness, I'll dump the rest below.
// get the pixel position with every move
var mousePosition = null;
map.on('pointermove', function(event) {
mousePosition = event.pixel
map.render();
});
// before rendering the layer, do some clipping
function onPreCompose(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,
75 * 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
function onPostCompose(event) {
var ctx = event.context;
ctx.restore();
}
// listen for change events on radio inputs
var inputs = document.querySelectorAll('input[type="radio"]');
for (var i = 0, ii = inputs.length; i < ii; ++i) {
inputs[i].addEventListener('change', onRadioChange);
}
// kick things off with the first checked radio input
onRadioChange({target: document.querySelector('input[type="radio"]:checked')});
Best Answer
I have been struggling with the same issue, but I seem to have come across a solution that works pretty well.
In the Docs there is no
visibility
style option for vector features. But you can set theopacity
of anol.style.Icon
or the alpha of thefill
andstroke
for anol.style.Circle
andol.style.RegularShape
How I got it to work was to set a style functions for my visible and invisible states. Here are a few options for points
Then for the feature you want to hide/unhide just set the style for that feature