Multi-Spy

Spyglass example using multiple layers.

by Thomas B.

HTML

<script src="http://ol3js.org/en/master/build/ol.js"></script>
<link rel="stylesheet" href="http://ol3js.org/en/master/css/ol.css">
<div id="map"></div>
<div id="controls">
  <label><input type="radio" name="layer" value="imagery" checked> imagery without labels</label>
  <label><input type="radio" name="layer" value="labeled"> imagery with labels</label>
<div>

CSS

html, body, #map {
    font-family: sans-serif;
    padding: 0;
    margin: 0;
    width: 100%;
    height: 100%;
}

#controls {
    position: absolute;
    top: 10px;
    width: 100%;
    text-align: center;
}

JavaScript

var key = 'Ak-dzM4wZjSqTlzveKz5u0d4IQ4bRzVI309GxmkgSVr1ewS6iPSrOvOKhA-CJlm3';

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

// get the pixel position with every move
var mousePosition = null;
map.on('pointermove', function(event) {
  mousePosition = event.pixel
  map.render();
});

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

// 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();
}

var inputs = document.querySelectorAll('input[type="radio"]');
for (var i = 0, ii = inputs.length; i < ii; ++i) {
  inputs[i].addEventListener('change', onRadioChange);
}
onRadioChange({target:...