Edit

Tile Load Events

tile9 events3 loading8

Example using tile load events.

Image tile sources fire events related to tile loading. You can listen for tileloadstart, tileloadend, and tileloaderror type events to monitor tile loading progress. This example registers listeners for these events and renders a tile loading progress bar at the bottom of the map. The progress bar is shown and hidden according to the map's loadstart and loadend events.

main.js
import Map from 'ol/Map.js';
import TileLayer from 'ol/layer/Tile.js';
import View from 'ol/View.js';
import XYZ from 'ol/source/XYZ.js';

/**
 * Renders a progress bar.
 * @param {HTMLElement} el The target element.
 * @class
 */
function Progress(el) {
  this.el = el;
  this.loading = 0;
  this.loaded = 0;
}

/**
 * Increment the count of loading tiles.
 */
Progress.prototype.addLoading = function () {
  ++this.loading;
  this.update();
};

/**
 * Increment the count of loaded tiles.
 */
Progress.prototype.addLoaded = function () {
  ++this.loaded;
  this.update();
};

/**
 * Update the progress bar.
 */
Progress.prototype.update = function () {
  const width = ((this.loaded / this.loading) * 100).toFixed(1) + '%';
  this.el.style.width = width;
};

/**
 * Show the progress bar.
 */
Progress.prototype.show = function () {
  this.el.style.visibility = 'visible';
};

/**
 * Hide the progress bar.
 */
Progress.prototype.hide = function () {
  const style = this.el.style;
  setTimeout(function () {
    style.visibility = 'hidden';
    style.width = 0;
  }, 250);
};

const progress = new Progress(document.getElementById('progress'));

const key = 'get_your_own_D6rA4zTHduk6KOKTXzGB';
const 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>';

const source = new XYZ({
  attributions: attributions,
  url: 'https://api.maptiler.com/maps/streets/{z}/{x}/{y}.png?key=' + key,
  tileSize: 512,
});

source.on('tileloadstart', function () {
  progress.addLoading();
});
source.on(['tileloadend', 'tileloaderror'], function () {
  progress.addLoaded();
});

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

map.on('loadstart', function () {
  progress.show();
});
map.on('loadend', function () {
  progress.hide();
});
index.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <title>Tile Load Events</title>
    <link rel="stylesheet" href="node_modules/ol/ol.css">
    <style>
      .map {
        width: 100%;
        height: 400px;
      }
      .map {
        background: #85ccf9;
      }
      .wrapper {
        position: relative;
      }
      #progress {
        position: absolute;
        bottom: 0;
        left: 0;
        height: 0;
        box-shadow: 0px 0px 1px 2px rgb(255,204,0);
        width: 0;
        transition: width 250ms;
      }
    </style>
  </head>
  <body>
    <div class="wrapper">
      <div id="map" class="map"></div>
      <div id="progress"></div>
    </div>
    <!-- Pointer events polyfill for old browsers, see https://caniuse.com/#feat=pointer -->
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/elm-pep.js"></script>
    <script type="module" src="main.js"></script>
  </body>
</html>
package.json
{
  "name": "tile-load-events",
  "dependencies": {
    "ol": "7.2.2"
  },
  "devDependencies": {
    "vite": "^3.2.3"
  },
  "scripts": {
    "start": "vite",
    "build": "vite build"
  }
}