feat(core): GlobeView pointer-anchored zoom (wheel + transitions)#10385
feat(core): GlobeView pointer-anchored zoom (wheel + transitions)#10385charlieforward9 wants to merge 9 commits into
Conversation
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.
c29d36e to
4b98253
Compare
…pout) Per #10307 review: zoomAround is a config option that always needs a value, unlike the transient gesture anchors guarded the same way. The !== undefined guard let a partial-props / HMR reconstruction drop the key, so _shouldZoomAroundPointer() saw undefined and silently reverted to center zoom.
ibgreen-openai
left a comment
There was a problem hiding this comment.
I wonder if this could be split into stacked PR, one that adds general things like zoomStart, zoomEnd and other plumbing, and then the globe specific feature could be a much smaller, easier review on top of that?
| }); | ||
| document.body.appendChild(overlay); | ||
|
|
||
| const controls = document.createElement('div'); |
There was a problem hiding this comment.
There is so much code here in the app, it feels like the framework is not doing enough?
Maybe split out a settings-control.ts to keep the HTML settings UI separate from the deck related logic?
There was a problem hiding this comment.
Most of this code seems to relate to UI switches to test different modes. Agreed it'll help review to split the deck and UI code changes
chrisgervang
left a comment
There was a problem hiding this comment.
Agree with @ibgreen, since this changes a lot of core functionality I'd prefer to split the PRs up and test each of them in the stack
| try { | ||
| localStorage.setItem(ZOOM_AROUND_STORAGE_KEY, zoomAround); | ||
| } catch { | ||
| // Ignore storage failures in sandboxed test apps. |
There was a problem hiding this comment.
Why wrap in a try/catch then?
Summary
Adds opt-in pointer-anchored zoom for
GlobeView, keeping the existing center-anchored behavior as the default.Changes
zoomAround?: 'center' | 'pointer'to controller options.GlobeViewport.panByGlobeAnchor— spherical (ray-to-sphere) pointer anchoring, with edge damping near the limb and a grace band so anchors don't snap when the cursor grazes the globe's edge.zoomStartmisses the globe and leaves the anchor empty, pointer mode recovers an anchor from the current event and persists it for the rest of the gesture (fixes a sporadic fallback to center-anchoring).LinearInterpolatortransitions anchored onGlobeViewport, so animated zooms respect the pointer anchor.Tests
controllers.spec,view-states.spec,globe-viewport.spec,linear-interpolator.spec— anchor math, gesture recovery, and transition anchoring.Follow-up