Skip to content

feat(examples): add tile loading indicator - #624

Merged
kylebarron merged 16 commits into
mainfrom
kyle/tile-loading-indicator
Sep 23, 2026
Merged

kylebarron merged 16 commits into
mainfrom
kyle/tile-loading-indicator

Conversation

@kylebarron

@kylebarron kylebarron commented Jul 13, 2026 •

Copy link
Copy Markdown
Member
Screen.Recording.2026-09-23.at.3.32.15.PM.mov

Note

This PR description was written by Claude (Claude Code) on behalf of @kylebarron, not by @kylebarron.

Closes #599.

Shows a spinner in the example apps while map tiles are loading, using deck.gl's built-in LoadingWidget from @deck.gl/widgets.

What changed

  • examples/_shared/styles/loading-widget.ts exports loadingWidgetProps. It places the widget top-right (the control panel sits top-left) and sets deck.gl's widget theme variables to match the Chakra control panel.

  • Each wired example imports @deck.gl/widgets/stylesheet.css and passes the widget to the shared overlay:

    <DeckGlOverlay
      layers={layers}
      widgets={[new LoadingWidget(loadingWidgetProps)]}
      interleaved
    />
  • Wired into every example that renders through DeckGlOverlay:

    • COGLayer: cog-basic, cog-globe, land-cover, usgs-topo-cutline, vermont-cog-comparison
    • MosaicLayer of COGLayers: naip-mosaic
    • MultiCOGLayer: sentinel-2
    • ZarrLayer: aef-mosaic, dynamical-zarr-ecmwf, nldas-icechunk, zarr-sentinel2-tci

    globe-view and titiler-cog don't use DeckGlOverlay, so they're unchanged.

How it works

LoadingWidget checks isLoaded on every layer deck has applied, on each redraw. That signal already covers nested layers:

  • TileLayer.isLoaded requires every selected tile and the sublayers drawn for it to be loaded.
  • A composite layer is loaded only when all of its sublayers are.

So in naip-mosaic the spinner waits for each source's image tiles, not just the GeoTIFF headers. #667 made COGLayer, MultiCOGLayer and ZarrLayer report "not loaded" while their metadata is still loading, so the spinner also covers the header or metadata fetch.

Why not the first version of this PR

The first version turned loading on from the map's onMoveStart and off from the layer's onViewportLoad. That broke in three ways:

  • The spinner could stay on forever. onViewportLoad only fires when the set of visible tiles changes, so a small pan left it stuck.
  • naip-mosaic cleared too early. Its onViewportLoad fires once the GeoTIFF headers are open, before any imagery has loaded.
  • Loads that don't come from moving the map were missed, e.g. changing the year in aef-mosaic.

Known behavior

  • During a long fly-to (a new COG in cog-basic, or a new location in aef-mosaic), the spinner can disappear for part of the flight. While the target is off-screen or the map is zoomed out below the layer's minZoom, there are no tiles to wait for. It comes back as soon as the new area needs tiles.
  • If naip-mosaic's STAC query fails, the example drops the widget. With no layers, deck never redraws, so the widget would otherwise keep spinning.

Testing

  • pnpm -r typecheck and pnpm check pass.
  • Checked in Chrome: every wired example shows the spinner on first load and clears it once imagery renders. Also checked:
    • cog-basic: switching COG;
    • naip-mosaic: a blocked STAC request;
    • aef-mosaic: year change, band sliders and location fly-to.
  • zarr-sentinel2-tci needs locally served GeoZarr data, so it was only typechecked.
  • The Zarr examples (aef-mosaic, dynamical-zarr-ecmwf, nldas-icechunk) were checked against production builds. Under vite dev they currently fail with WebGL context already attached, a React StrictMode issue that exists without this PR. That will be investigated separately.

🤖 Written by Claude Code

kylebarron and others added 7 commits July 10, 2026 14:57
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions github-actions Bot added the feat label Jul 13, 2026
@charlieforward9

Copy link
Copy Markdown

Seems related to visgl/deck.gl#10359 but external to the layer rendering. Interested in getting a review pass on it to see if it could land by 9.4 @kylebarron

@willjnz

willjnz commented Sep 23, 2026

Copy link
Copy Markdown
Contributor

This would be helpful. The default view of the AEF example takes a long time to render the first view
Screenshot 2026-09-23 at 12 38 27 pm

kylebarron and others added 8 commits September 23, 2026 12:27
Revises the tile loading indicator spec to use deck.gl's LoadingWidget.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Replaced by deck.gl's LoadingWidget.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Wires deck.gl's LoadingWidget into every example that renders through
DeckGlOverlay, and updates the spec's scope to match.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@kylebarron
kylebarron merged commit 063f6ae into main Sep 23, 2026
5 checks passed
@kylebarron
kylebarron deleted the kyle/tile-loading-indicator branch September 23, 2026 19:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Spinner in examples to have a UI element to show tiles are loading

3 participants