[GIS] Using OpenLayers 3 spyglass

jqueryopenlayers

I would like to use OpenLayers 3 spyglass example inside my project.

The problem is when I want to use selection for layer, which will be inside spyglass circle. I can't get it working, I don't know how to update it on every user's selection correctly.

Anyone more skilled can help me?

Here is my fiddle with it partially working:
http://jsfiddle.net/dkcz/8a3pdavv/

Best Answer

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')});