Query progress of processing tasks with the .progress and .loading APIs.

  • Instance
  • Map (left)
  • Color layer
  • Elevation layer
  • Map (right)
  • Color layer
  • Elevation layer
100% © Mapbox

Use the loading and progress properties of various elements (Instance, Entity, Layer...) to track the loading of the data.
Each level of the hierarchy aggregates the state of its children (e.g the instance aggregates the state of all entities under its control).

index.js
import XYZ from "ol/source/XYZ.js";

import { MapControls } from "three/examples/jsm/controls/MapControls.js";

import Extent from "@giro3d/giro3d/core/geographic/Extent.js";
import Instance from "@giro3d/giro3d/core/Instance.js";
import TiledImageSource from "@giro3d/giro3d/sources/TiledImageSource.js";
import ColorLayer from "@giro3d/giro3d/core/layer/ColorLayer.js";
import ElevationLayer from "@giro3d/giro3d/core/layer/ElevationLayer.js";
import Map from "@giro3d/giro3d/entities/Map.js";
import Inspector from "@giro3d/giro3d/gui/Inspector.js";
import MapboxTerrainFormat from "@giro3d/giro3d/formats/MapboxTerrainFormat.js";

const extent = new Extent("EPSG:3857", -13611854, -13593262, 5806332, 5820603);

const instance = new Instance({
  target: "view",
  crs: "EPSG:3857",
});

function createMap(mapExtent, tileset) {
  const key =
    "pk.eyJ1IjoidG11Z3VldCIsImEiOiJjbGJ4dTNkOW0wYWx4M25ybWZ5YnpicHV6In0.KhDJ7W5N3d1z3ArrsDjX_A";
  const map = new Map({ extent: mapExtent });
  map.name = tileset;
  instance.add(map);

  // Adds a XYZ elevation layer with MapBox terrain RGB tileset
  const elevationLayer = new ElevationLayer({
    name: "xyz_elevation",
    extent,
    source: new TiledImageSource({
      format: new MapboxTerrainFormat(),
      source: new XYZ({
        url: `https://api.mapbox.com/v4/mapbox.terrain-rgb/{z}/{x}/{y}.pngraw?access_token=${key}`,
        projection: extent.crs,
        crossOrigin: "anonymous",
      }),
    }),
  });
  map.addLayer(elevationLayer);

  // Adds a XYZ color layer with MapBox satellite tileset
  const colorLayer = new ColorLayer({
    name: "xyz_color",
    extent,
    source: new TiledImageSource({
      source: new XYZ({
        url: `https://api.mapbox.com/v4/mapbox.${tileset}/{z}/{x}/{y}.webp?access_token=${key}`,
        projection: extent.crs,
        crossOrigin: "anonymous",
      }),
    }),
  });
  map.addLayer(colorLayer);

  return { map, colorLayer, elevationLayer };
}

const split = extent.split(2, 1);

const naip = createMap(split[0], "naip");
const satellite = createMap(split[1], "satellite");

const center = extent.centerAsVector3();
instance.view.camera.position.set(center.x, extent.north, 10000);

const controls = new MapControls(instance.view.camera, instance.domElement);
controls.target = center;
controls.saveState();
controls.enableDamping = true;
controls.dampingFactor = 0.2;
controls.maxPolarAngle = Math.PI / 2.3;
instance.view.setControls(controls);

const instanceProgress = document.getElementById("progress-instance");
const naipMapProgress = document.getElementById("progress-map1");
const color1Progress = document.getElementById("progress-color1");
const elevation1Progress = document.getElementById("progress-elevation1");
const satelliteMapProgress = document.getElementById("progress-map2");
const color2Progress = document.getElementById("progress-color2");
const elevation2Progress = document.getElementById("progress-elevation2");

function updateProgressBar(domElement, source) {
  domElement.style.width = `${Math.round(source.progress * 100)}%`;
}

// Let's poll the main loop: at each update, we can update the progress bars
instance.addEventListener("update-end", () => {
  updateProgressBar(instanceProgress, instance);

  updateProgressBar(naipMapProgress, naip.map);
  updateProgressBar(color1Progress, naip.colorLayer);
  updateProgressBar(elevation1Progress, naip.elevationLayer);

  updateProgressBar(satelliteMapProgress, satellite.map);
  updateProgressBar(color2Progress, satellite.colorLayer);
  updateProgressBar(elevation2Progress, satellite.elevationLayer);
});

Inspector.attach("inspector", instance);
index.html
<!doctype html>
<html lang="en">
  <head>
    <title>Tracking progress</title>
    <meta charset="UTF-8" />
    <meta name="name" content="tracking_progress" />
    <meta
      name="description"
      content="Query progress of processing tasks with the &lt;code&gt;.progress&lt;/code&gt; and &lt;code&gt;.loading&lt;/code&gt; APIs."
    />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />

    <link rel="icon" href="https://giro3d.org/images/favicon.svg" />
    <link
      href="https://giro3d.org/assets/bootstrap-custom.css"
      rel="stylesheet"
    />
    <script src="https://giro3d.org/assets/bootstrap.bundle.min.js"></script>
    <link
      rel="stylesheet"
      type="text/css"
      href="https://giro3d.org/latest/examples/css/example.css"
    />
  </head>

  <body>
    <div id="view" class="m-0 p-0 w-100 h-100"></div>
    <div
      id="inspector"
      class="position-absolute top-0 start-0 mh-100 overflow-auto"
    ></div>

    <div class="side-pane-with-status-bar">
      <ul class="list-group mh-100 overflow-y-auto">
        <li
          class="list-group-item d-flex justify-content-between align-items-center"
        >
          <span>Instance</span>
          <div class="progress" style="width: 100px">
            <div
              id="progress-instance"
              class="progress-bar"
              style="width: 100%"
            ></div>
          </div>
        </li>

        <li
          class="list-group-item d-flex justify-content-between align-items-center"
        >
          <span class="mx-3">Map (left)</span>
          <div class="progress" style="width: 100px">
            <div
              id="progress-map1"
              class="progress-bar"
              style="width: 100%"
            ></div>
          </div>
        </li>

        <li
          class="list-group-item d-flex justify-content-between align-items-center"
        >
          <span class="mx-5">Color layer</span>
          <div class="progress" style="width: 100px">
            <div
              id="progress-color1"
              class="progress-bar"
              style="width: 100%"
            ></div>
          </div>
        </li>

        <li
          class="list-group-item d-flex justify-content-between align-items-center"
        >
          <span class="mx-5">Elevation layer</span>
          <div class="progress" style="width: 100px">
            <div
              id="progress-elevation1"
              class="progress-bar"
              style="width: 100%"
            ></div>
          </div>
        </li>

        <li
          class="list-group-item d-flex justify-content-between align-items-center"
        >
          <span class="mx-3">Map (right)</span>
          <div class="progress" style="width: 100px">
            <div
              id="progress-map2"
              class="progress-bar"
              style="width: 100%"
            ></div>
          </div>
        </li>

        <li
          class="list-group-item d-flex justify-content-between align-items-center"
        >
          <span class="mx-5">Color layer</span>
          <div class="progress" style="width: 100px">
            <div
              id="progress-color2"
              class="progress-bar"
              style="width: 100%"
            ></div>
          </div>
        </li>

        <li
          class="list-group-item d-flex justify-content-between align-items-center"
        >
          <span class="mx-5">Elevation layer</span>
          <div class="progress" style="width: 100px">
            <div
              id="progress-elevation2"
              class="progress-bar"
              style="width: 100%"
            ></div>
          </div>
        </li>
      </ul>
    </div>

    <script type="module" src="index.js"></script>
    <script>
      /* activate popovers */
      const popoverTriggerList = [].slice.call(
        document.querySelectorAll('[data-bs-toggle="popover"]'),
      );
      popoverTriggerList.map(
        // bootstrap is used as script in the template, disable warning about undef
        // eslint-disable-next-line no-undef
        (popoverTriggerEl) =>
          new bootstrap.Popover(popoverTriggerEl, {
            trigger: "hover",
            placement: "left",
            content: document.getElementById(
              popoverTriggerEl.getAttribute("data-bs-content"),
            ).innerHTML,
            html: true,
          }),
      );
    </script>
  </body>
</html>
package.json
{
    "name": "tracking_progress",
    "dependencies": {
        "@giro3d/giro3d": "0.41.0"
    },
    "devDependencies": {
        "vite": "^3.2.3"
    },
    "scripts": {
        "start": "vite",
        "build": "vite build"
    }
}