OL5.3 | XYZ MVT vector editing.

by Dennis Bauszus

HTML

<script src="https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v5.3.0/build/ol.js"></script>
<link rel="stylesheet" href="https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v5.3.0/css/ol.css">
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">

<div id="map" class="map"></div>

<div class="btns">
  <button id="btnPoint" class="btn">
    <i class="material-icons">add_location</i>
  </button>
  <button id="btnLine" class="btn">
    <i class="material-icons">timeline</i>
  </button>
  <button id="btnPoly" class="btn">
    <i class="material-icons">signal_cellular_null</i>
  </button>
  <button id="btnDelete" class="btn">
    <i class="material-icons">delete</i>
  </button>
</div>

CSS

html,
body {
  height: 100%;
  width: 100%;
  padding: 0;
  margin: 0;
  border: 0;
}

.map {
  height: 100%;
  width: 100%;
}

.btns {
  position: absolute;
  top: 10px;
}

.btn {
  display: inline-block;
  margin-left: 10px;
  background-color: #EE266D;
  border-radius: 100%;
  border: none;
  width: 50px;
  height: 50px;
  color: #fff;
  box-shadow: 2px 2px 2px #0d47a1;
}

.btn.active {
  background-color: #0d47a1;
  box-shadow: 2px 2px 2px #EE266D;
}

JavaScript

const layerBase = new ol.layer.Tile({
  source: new ol.source.OSM({
    url: 'https://cartodb-basemaps-{a-d}.global.ssl.fastly.net/dark_nolabels/{z}/{x}/{y}.png',
    opaque: false,
    attributions: []
  })
});


const sourceMVT = new ol.source.VectorTile({
  cacheSize: 0,
  format: new ol.format.MVT(),
  url: 'https://geolytix.xyz/dev/api/layer/mvt/{z}/{x}/{y}?locale=GB&layer=Scratch&table=dev.scratch'
});

const layerMVT = new ol.layer.VectorTile({
  preload: 0,
  source: sourceMVT,
  style: new ol.style.Style({
      stroke: new ol.style.Stroke({
        color: '#090',
        width: 2
      }),
      fill: new ol.style.Fill({
        color: 'rgba(0, 0, 0, 0)'
      }),
      image: new ol.style.Circle({
        radius: 7,
        fill: new ol.style.Fill({
          color: 'rgba(0, 0, 0, 0.01)'
        }),
        stroke: new ol.style.Stroke({
          color: '#090',
          width: 2
        })
      })
    })
});

function clearTileCache() {
  sourceMVT.clear();
  sourceMVT.tileCache.clear();
  sourceMVT.refresh();
}


const sourceVector = new ol.source.Vector();

const layerVector = new ol.layer.Vector({
  source: sourceVector,
  style: new ol.style.Style({
    stroke: new ol.style.Stroke({
      color: '#EE266D',
      width: 2
    }),
    fill: new ol.style.Fill({
      color: 'rgba(0, 0, 0, 0.01)'
    }),
    image: new ol.style.Circle({
      radius: 7,
      fill: new ol.style.Fill({
        color: 'rgba(0, 0, 0, 0.01)'
      }),
      stroke: new ol.style.Stroke({
        color: '#EE266D',
        width: 2
      })
    })
  })
});


const geoJSON = new ol.format.GeoJSON();

const map = new ol.Map({
  target: 'map',
  controls: [],
  interactions: [
    new ol.interaction.MouseWheelZoom(),
    new ol.interaction.DragPan()
  ],
  layers: [layerBase, layerMVT, layerVector],
  view: new ol.View({
    center: ol.proj.fromLonLat([-3, 55]),
    zoom: 6
  })
});


const modifyInteraction = new ol.interaction.Modify({
  source:...