Skip to content

Commit c29d36e

Browse files
fix(core): recover globe pointer zoom anchors
1 parent 10efe94 commit c29d36e

2 files changed

Lines changed: 37 additions & 4 deletions

File tree

modules/core/src/controllers/globe-controller.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ class GlobeState extends MapState {
175175
}): MapState {
176176
const state = this.getState();
177177
const {startZoom} = state;
178-
let {startZoomLngLat} = state;
178+
const initialStartZoomLngLat = state.startZoomLngLat as [number, number] | undefined;
179179
const hasZoomStart = startZoom !== null && startZoom !== undefined;
180180
const startZoomValue = hasZoomStart ? startZoom : this.getViewportProps().zoom;
181181
const zoom = this._constrainZoom(startZoomValue + Math.log2(scale));
@@ -184,9 +184,10 @@ class GlobeState extends MapState {
184184
return this._getUpdatedState({zoom});
185185
}
186186

187-
if (!startZoomLngLat && !hasZoomStart) {
188-
startZoomLngLat = this._unprojectZoomAnchor(startPos) || this._unprojectZoomAnchor(pos);
189-
}
187+
const startZoomLngLat =
188+
initialStartZoomLngLat ??
189+
this._unprojectZoomAnchor(startPos) ??
190+
this._unprojectZoomAnchor(pos);
190191

191192
if (!startZoomLngLat) {
192193
return this._getUpdatedState({zoom});
@@ -195,6 +196,7 @@ class GlobeState extends MapState {
195196
const zoomedViewport = this.makeViewport({...this.getViewportProps(), zoom});
196197
return this._getUpdatedState({
197198
zoom,
199+
...(hasZoomStart && !initialStartZoomLngLat ? {startZoomLngLat} : {}),
198200
...this._panByZoomAnchor(zoomedViewport, startZoomLngLat, pos)
199201
});
200202
}

test/modules/core/controllers/view-states.spec.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
OrbitController,
99
FirstPersonController,
1010
_GlobeController as GlobeController,
11+
_GlobeViewport as GlobeViewport,
1112
OrbitViewport,
1213
OrthographicController,
1314
Viewport
@@ -173,6 +174,36 @@ test('GlobeViewState', () => {
173174
expect(viewportProps.zoom > 12, 'small bounds#zoom is adjusted').toBeTruthy();
174175
});
175176

177+
test('GlobeViewState recovers pointer anchored zoom when zoomStart misses the globe', () => {
178+
const GlobeViewState = new GlobeController({} as any).ControllerState;
179+
const makeViewport = (props: any) => new GlobeViewport(props);
180+
181+
const pos: [number, number] = [500, 300];
182+
const missedStartPos: [number, number] = [0, 0];
183+
const startProps = {
184+
width: 800,
185+
height: 600,
186+
longitude: 0,
187+
latitude: 0,
188+
zoom: 2,
189+
zoomAround: 'pointer',
190+
makeViewport
191+
};
192+
const anchor = makeViewport(startProps).unproject(pos);
193+
const zoomed = new GlobeViewState(startProps)
194+
.zoomStart({pos: missedStartPos})
195+
.zoom({pos, scale: 1.25})
196+
.getViewportProps();
197+
const anchorPosition = makeViewport(zoomed).project(anchor);
198+
199+
expect(
200+
makeViewport(startProps).isPointOnGlobe(missedStartPos),
201+
'test starts outside the globe surface'
202+
).toBe(false);
203+
expect(anchorPosition[0], 'recovered pointer anchor keeps cursor x fixed').toBeCloseTo(pos[0]);
204+
expect(anchorPosition[1], 'recovered pointer anchor keeps cursor y fixed').toBeCloseTo(pos[1]);
205+
});
206+
176207
test('OrbitViewState', () => {
177208
const OrbitViewState = new OrbitController({} as any).ControllerState;
178209
const makeViewport = (props: any) => new OrbitViewport(props);

0 commit comments

Comments
 (0)