This example uses OpenLayers v10.9.0. The latest is v.
Edit

#### Image Load Events

image 8 events 3 loading 8

#####

Example using image load events.

Image sources fire events related to image loading. You can listen for `imageloadstart`, `imageloadend`, and `imageloaderror` type events to monitor image loading progress. This example registers listeners for these events and renders an image 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 View from 'ol/View.js';
    import ImageLayer from 'ol/layer/Image.js';
    import ImageWMS from 'ol/source/ImageWMS.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 = '0px';
      }, 250);
    };

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

    const source = new ImageWMS({
      url: 'https://ahocevar.com/geoserver/wms',
      params: {'LAYERS': 'topp:states'},
      serverType: 'geoserver',
    });

    source.on('imageloadstart', function () {
      progress.addLoading();
    });
    source.on(['imageloadend', 'imageloaderror'], function () {
      progress.addLoaded();
    });

    const map = new Map({
      layers: [new ImageLayer({source: source})],
      target: 'map',
      view: new View({
        center: [-10997148, 4569099],
        zoom: 4,
      }),
    });

    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>Image Load Events</title>
        <link rel="stylesheet" href="node_modules/ol/ol.css">
        <style>
          .map {
            width: 100%;
            height: 400px;
          }
          .map {
            background: #E0ECED;
          }
          .wrapper {
            position: relative;
          }
          #progress {
            position: absolute;
            bottom: 0;
            left: 0;
            height: 2px;
            background: rgba(0, 60, 136, 0.4);
            width: 0;
            transition: width 250ms;
          }
        </style>
      </head>
      <body>
        <div class="wrapper">
          <div id="map" class="map"></div>
          <div id="progress"></div>
        </div>

        <script type="module" src="main.js"></script>
      </body>
    </html>

##### package.json

    {
      "name": "image-load-events",
      "dependencies": {
        "ol": "10.9.0"
      },
      "devDependencies": {
        "vite": "^3.2.3"
      },
      "scripts": {
        "start": "vite",
        "build": "vite build"
      }
    }