Skip to content

fix(mapbox,google-maps): use css-dpr pixel sizing in overlaid mode to prevent basemap misalignment#10370

Open
chrisgervang wants to merge 6 commits into
masterfrom
chr/deckgl-fix-evaluation
Open

fix(mapbox,google-maps): use css-dpr pixel sizing in overlaid mode to prevent basemap misalignment#10370
chrisgervang wants to merge 6 commits into
masterfrom
chr/deckgl-fix-evaluation

Conversation

@chrisgervang

@chrisgervang chrisgervang commented Jun 11, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Passes pixelSizeSource: 'css-dpr' to the luma.gl canvas context in overlaid (non-interleaved) mode for both MapboxOverlay and GoogleMapsOverlay
  • This makes luma.gl derive pixel sizes using CSS dimensions × DPR instead of the exact devicePixelContentBoxSize, matching how Mapbox GL, MapLibre, and Google Maps compute their canvas drawing buffer dimensions
  • Fixes visible drift between the deck.gl overlay canvas and the basemap at fractional browser zoom levels (90%, 110%, 33%, etc.)
  • Bumps @luma.gl/* to 9.3.4 which ships the pixelSizeSource prop (visgl/luma.gl#2588)

Remaining luma.gl fix needed

visgl/luma.gl#2675: The css-dpr mode in luma.gl 9.3.4 has two bugs:

  1. The ResizeObserver still watches device-pixel-content-box even in css-dpr mode — this causes major canvas misalignment during real browser zoom (Cmd+/-) due to race conditions in the observer callback
  2. Uses Math.round instead of Math.floor — causes 1px mismatch at certain DPR values since Mapbox truncates via implicit canvas.width assignment

Both issues are confirmed fixed by patching luma.gl locally. Once luma.gl ships the fix, this PR will fully resolve #10173.

Impact by environment

Environment Effect
Pure deck.gl (standalone, no basemap) No change — default pixelSizeSource remains 'exact'
Mapbox/MapLibre overlaid Fixed — overlay canvas now matches basemap sizing
Mapbox/MapLibre interleaved No change — deck sets width: null, height: null, map owns canvas
Google Maps non-interleaved (raster & vector positioning) Fixed — same treatment
Google Maps interleaved (WebGL overlay) No change — gl prop present, deviceProps not injected
ArcGIS No change — renders to external FBO

Root cause

At fractional browser zoom, window.devicePixelRatio becomes non-integer. Mapbox/MapLibre compute canvas pixel size as Math.floor(cssWidth * dpr) (via implicit truncation), while luma.gl's ResizeObserver with device-pixel-content-box reports the true physical pixel count. These can differ significantly, causing the two canvases to have different drawing buffer dimensions and visible misalignment.

The larger issue is that device-pixel-content-box observation fires during DPR changes with potentially stale/racey values, causing the deck.gl canvas to resize out of sync with Mapbox's canvas.

Test plan

  • Verify no regression at 100% browser zoom with Mapbox overlay
  • Verify drawing buffer dimensions match at fractional DPR (confirmed Math.floor matches Mapbox)
  • Verify misalignment is fixed at 50%, 25% browser zoom (requires luma.gl#2675 fix)
  • Verify Google Maps overlay renders correctly at fractional zoom
  • Verify standalone deck.gl (no basemap) continues to use exact pixel sizing
  • Verify interleaved mode is unaffected

Closes #10173 (pending luma.gl#2675)

🤖 Generated with Claude Code


Note

Medium Risk
Touches canvas sizing for all overlaid Mapbox and non-interleaved Google Maps integrations; standalone deck and interleaved modes are scoped out but wrong DPR behavior would show as misalignment or blur.

Overview
Fixes deck.gl overlay drift vs Mapbox/MapLibre/Google Maps basemaps at fractional browser zoom by sizing the deck canvas like the basemap (CSS × DPR) instead of luma’s default exact device-pixel-content-box sizing.

MapboxOverlay (overlaid mode) and GoogleMapsOverlay (when no shared gl / non-interleaved) now pass deviceProps.createCanvasContext.pixelSizeSource: 'css-dpr', merging with any existing deviceProps. Interleaved / external-GL paths are unchanged.

Monorepo @luma.gl/* dependencies are bumped 9.3.3 → 9.3.4 (lockfile resolves to 9.3.5). A manual test/apps/fractional-zoom-alignment Mapbox + ScatterplotLayer app compares map vs deck canvas dimensions for #10173.

Reviewed by Cursor Bugbot for commit 0f2789a. Bugbot is set up for automated code reviews on this repo. Configure here.

… prevent basemap misalignment

At fractional browser zoom levels, luma.gl's exact device-pixel-content-box sizing
diverges from the Math.round(css * dpr) approach used by Mapbox GL, MapLibre, and
Google Maps, causing visible drift between the deck.gl overlay canvas and the basemap.

Pass pixelSizeSource: 'css-dpr' when creating the canvas context in overlaid (non-interleaved)
mode so luma.gl derives pixel sizes using the same rounding as the underlying basemap.

Depends on visgl/luma.gl#2588 (pixelSizeSource prop, merged to master, pending release).

Closes #10173

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@chrisgervang chrisgervang requested a review from ibgreen June 12, 2026 00:11
chrisgervang and others added 2 commits June 11, 2026 17:11
…release

The pixelSizeSource prop is available in luma.gl >9.3.3 (visgl/luma.gl#2588)
but not yet in the currently pinned @luma.gl/core@9.3.3 types.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
luma.gl 9.3.4 ships the pixelSizeSource prop (visgl/luma.gl#2588),
so the ts-expect-error suppression is no longer needed.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@chrisgervang chrisgervang changed the title fix(mapbox,google-maps): use css-dpr pixel sizing to prevent basemap misalignment at fractional zoom fix(mapbox,google-maps): use css-dpr pixel sizing in overlaid mode to prevent basemap misalignment Jun 13, 2026
@coveralls

coveralls commented Jun 13, 2026

Copy link
Copy Markdown

Coverage Status

coverage: 83.424%. remained the same — chr/deckgl-fix-evaluation into master

@chrisgervang chrisgervang marked this pull request as ready for review June 13, 2026 23:37
chrisgervang and others added 2 commits June 18, 2026 20:58
- Update yarn.lock to pull in @luma.gl/core 9.3.5 which includes the
  css-dpr observer box fix (visgl/luma.gl#2676)
- Add test/apps/fractional-zoom-alignment for manual verification of
  issue #10173 (basemap misalignment at fractional browser zoom)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…uation

Resolved conflicts: took @loaders.gl ^4.4.3 (from master) and
@luma.gl ^9.3.4 (from this branch).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@chrisgervang chrisgervang added this to the v9.4 milestone Jun 28, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] Misalignment/drift in MapboxOverlay at fractional zoom levels

2 participants