Skip to content

feat(core): GlobeView pointer-anchored zoom (wheel + transitions)#10307

Open
charlieforward9 wants to merge 8 commits into
visgl:masterfrom
NEW-HEAT:codex/globe-anchored-zoom
Open

feat(core): GlobeView pointer-anchored zoom (wheel + transitions)#10307
charlieforward9 wants to merge 8 commits into
visgl:masterfrom
NEW-HEAT:codex/globe-anchored-zoom

Conversation

@charlieforward9

@charlieforward9 charlieforward9 commented May 16, 2026

Copy link
Copy Markdown
Collaborator

Summary

Adds opt-in pointer-anchored zoom for GlobeView while preserving the existing center-anchored default.

Screen.Recording.2026-06-06.at.3.53.35.PM.mov

Changes

  • Adds zoomAround?: 'center' | 'pointer' to controller options.
  • Uses GlobeViewport.panByGlobeAnchor for spherical pointer anchoring during wheel, pinch, and double-click zoom.
  • Adds shared globe ray/sphere helpers plus GlobeViewport.isPointOnGlobe and panByGlobeAnchor.
  • Adds a small near-limb grace band so pointer zoom does not fall back to center when the cursor barely misses the rendered sphere.
  • Anchors LinearInterpolator transitions on GlobeViewport without changing the requested final view state.
  • Keeps runtime controller option updates, such as deck.setProps({controller: {zoomAround}}), ahead of persisted controller state.
  • Fixes pointer zoom after constrained globe pans by treating startZoom: null as cleared state.
  • Updates the bare GlobeView starter demo with a persisted Center / Pointer zoom-anchor toggle.

Validation

  • yarn vitest run --project headless test/modules/core/viewports/globe-viewport.spec.ts test/modules/core/transitions/linear-interpolator.spec.ts test/modules/core/controllers/controllers.spec.ts
  • Targeted ESLint on modules/core/src/controllers/globe-controller.ts
  • Pre-commit hook: module/test/example ESLint + Prettier checks and node smoke tests passed with existing repo warnings only.
  • Manual local check in the globe starter for persisted Pointer mode and constrained-pan pointer zoom.

Merge Notes

Default remains zoomAround: 'center', so existing GlobeView behavior is unchanged unless users opt in.


Note

Medium Risk
Touches core globe viewport, controller zoom, and transition interpolation; behavior is opt-in with center as default, but pointer anchoring affects camera math at the limb and after constrained pans.

Overview
Adds opt-in pointer-anchored zoom for GlobeView via a new controller option zoomAround: 'center' | 'pointer' (default remains center).

When set to 'pointer', wheel, pinch, and double-click zoom keep the lng/lat under the cursor fixed using new GlobeViewport helpers (isPointOnGlobe, panByGlobeAnchor) with shared ray–sphere math, near-limb damping, and a grace band so anchors slightly off the rendered sphere still work. Off-globe pointers fall back to center zoom.

GlobeState gains zoomStart / zoomEnd and pointer-aware zoom; LinearInterpolator now anchors globe transitions the same way instead of warning that around is unsupported. Controller state construction merges props after state so runtime deck.setProps({ controller: { zoomAround } }) wins over persisted state.

The pure-js globe starter demo adds a persisted Center/Pointer toggle; API docs describe the option.

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

@coveralls

coveralls commented May 16, 2026

Copy link
Copy Markdown

Coverage Status

coverage: 83.416% (+0.03%) from 83.391% — NEW-HEAT:codex/globe-anchored-zoom into visgl:master

@charlieforward9 charlieforward9 self-assigned this May 16, 2026
Replace the `log.warn('around not supported in GlobeView')` no-op
with real spherical anchoring, mirroring the existing planar branch:
- `initializeProps`: when the start viewport is a GlobeViewport and the
  screen anchor falls on the globe (`isPointOnGlobe`), unproject it to
  lng/lat and stash it as `aroundLngLat`.
- `interpolateProps`: each frame, call `panByGlobeAnchor(aroundLngLat,
  lerp(start.around, end.around, t))` so the geographic point stays
  pinned under the anchor screen point during the transition.

This makes the `_onDoubleClick` zoom transition (`_getTransitionProps
({around: pos})`) actually anchor on GlobeView. Previously the warn
fired and the LERP ran without anchor maintenance, which read as a
center-anchored zoom-in regardless of where the user tapped.

Tests cover the on-globe anchored path and the off-globe fall-through.
- Consolidate stray imports at the top of the file.
- Document the two GLOBE_ZOOM_ANCHOR_* constants so the empirical
  damping behavior (start damping at 0.75 of the limb, never below
  35% strength) is self-explanatory.
- Add a JSDoc to _getRayToGlobe explaining it as the shared ray/sphere
  math helper for unproject + isPointOnGlobe + panByGlobeAnchor.
@charlieforward9 charlieforward9 changed the title feat(core): add GlobeView pointer zoom option feat(core): GlobeView pointer-anchored zoom (wheel + transitions) May 22, 2026
Comment thread examples/get-started/pure-js/globe/app.js Outdated
Comment thread modules/core/src/viewports/globe-viewport.ts

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Fix All in Cursor

Reviewed by Cursor Bugbot for commit 4ad99ed. Configure here.

Comment thread modules/core/src/controllers/globe-controller.ts Outdated
Comment thread modules/core/src/transitions/linear-interpolator.ts
* `rotateSpeedX` (number) - speed of rotation using shift + left/right arrow keys, in degrees. Default `15`.
* `rotateSpeedY` (number) - speed of rotation using shift + up/down arrow keys, in degrees. Default `10`.
* `dragMode` (string) - drag behavior without pressing function keys, one of `pan` and `rotate`.
* `zoomAround` (`'center' | 'pointer'`) - zoom anchor mode when supported by the controller. Default depends on the controller.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe zoomAround: pointer is default behavior for most controllers - not sure if this is necessary.

@chrisgervang chrisgervang mentioned this pull request Jun 11, 2026
53 tasks
@chrisgervang chrisgervang added this to the v9.4 milestone Jun 11, 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.

3 participants