Edit

Layer Swipe (WebGL)

swipe2 webgl12

Cropping a WebGL tile layer

The prerender and postrender events on a WebGL tile layer can be used to manipulate the WebGL context before and after rendering. In this case, the gl.scissor() method is called to clip the top layer based on the position of a slider.

main.js
import 'ol/ol.css';
import Map from 'ol/Map';
import OSM from 'ol/source/OSM';
import TileLayer from 'ol/layer/WebGLTile';
import View from 'ol/View';
import XYZ from 'ol/source/XYZ';
import {getRenderPixel} from 'ol/render';

const osm = new TileLayer({
  source: new OSM({wrapX: true}),
});

const key = 'Get your own API key at https://www.maptiler.com/cloud/';

const imagery = new TileLayer({
  source: new XYZ({
    url: 'https://api.maptiler.com/tiles/satellite/{z}/{x}/{y}.jpg?key=' + key,
    attributions:
      '<a href="https://www.maptiler.com/copyright/" target="_blank">&copy; MapTiler</a> ' +
      '<a href="https://www.openstreetmap.org/copyright" target="_blank">&copy; OpenStreetMap contributors</a>',
    maxZoom: 20,
  }),
});

const map = new Map({
  layers: [osm, imagery],
  target: 'map',
  view: new View({
    center: [0, 0],
    zoom: 2,
  }),
});

const swipe = document.getElementById('swipe');

imagery.on('prerender', function (event) {
  const gl = event.context;
  gl.enable(gl.SCISSOR_TEST);

  const mapSize = map.getSize(); // [width, height] in CSS pixels

  // get render coordinates and dimensions given CSS coordinates
  const bottomLeft = getRenderPixel(event, [0, mapSize[1]]);
  const topRight = getRenderPixel(event, [mapSize[0], 0]);

  const width = Math.round((topRight[0] - bottomLeft[0]) * (swipe.value / 100));
  const height = topRight[1] - bottomLeft[1];

  gl.scissor(bottomLeft[0], bottomLeft[1], width, height);
});

imagery.on('postrender', function (event) {
  const gl = event.context;
  gl.disable(gl.SCISSOR_TEST);
});

const listener = function () {
  map.render();
};
swipe.addEventListener('input', listener);
swipe.addEventListener('change', listener);
index.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <title>Layer Swipe (WebGL)</title>
    <!-- Pointer events polyfill for old browsers, see https://caniuse.com/#feat=pointer -->
    <script src="https://unpkg.com/elm-pep"></script>
    <!-- The lines below are only needed for old environments like Internet Explorer and Android 4.x -->
    <script src="https://cdn.polyfill.io/v3/polyfill.min.js?features=fetch,requestAnimationFrame,Element.prototype.classList,TextDecoder"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/core-js/3.18.3/minified.js"></script>
    <style>
      .map {
        width: 100%;
        height:400px;
      }
    </style>
  </head>
  <body>
    <div id="map" class="map"></div>
    <input id="swipe" type="range" style="width: 100%">
    <script src="main.js"></script>
  </body>
</html>
package.json
{
  "name": "webgl-layer-swipe",
  "dependencies": {
    "ol": "6.12.0"
  },
  "devDependencies": {
    "parcel": "^2.0.0"
  },
  "scripts": {
    "start": "parcel index.html",
    "build": "parcel build --public-url . index.html"
  }
}