Skip to content

Commit 107de2e

Browse files
Fix orthographic scroll zoom transitions (#9769)
1 parent d5d3f72 commit 107de2e

File tree

2 files changed

+65
-1
lines changed

2 files changed

+65
-1
lines changed

modules/core/src/controllers/controller.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -533,10 +533,14 @@ export default abstract class Controller<ControllerState extends IViewState<Cont
533533
scale = 1 / scale;
534534
}
535535

536+
const transitionProps = smooth
537+
? {...this._getTransitionProps({around: pos}), transitionDuration: 250}
538+
: NO_TRANSITION_PROPS;
539+
536540
const newControllerState = this.controllerState.zoom({pos, scale});
537541
this.updateViewport(
538542
newControllerState,
539-
{...this._getTransitionProps({around: pos}), transitionDuration: smooth ? 250 : 1},
543+
transitionProps,
540544
{
541545
isZooming: true,
542546
isPanning: true

test/modules/core/controllers/controllers.spec.ts

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {
1010
FirstPersonView,
1111
_GlobeView as GlobeView
1212
} from '@deck.gl/core';
13+
import {Timeline} from '@luma.gl/engine';
1314

1415
import testController from './test-controller';
1516

@@ -96,6 +97,65 @@ test('OrthographicController#2d zoom', async t => {
9697
t.end();
9798
});
9899

100+
test('OrthographicController scroll zoom responds without transition lag', t => {
101+
const timeline = new Timeline();
102+
const view = new OrthographicView({controller: true});
103+
const baseProps = {
104+
id: 'test-view',
105+
x: 0,
106+
y: 0,
107+
width: 100,
108+
height: 100,
109+
target: [0, 0, 0],
110+
zoom: 0,
111+
scrollZoom: true
112+
};
113+
const controllerProps = {...view.controller, ...baseProps};
114+
const ControllerClass = controllerProps.type;
115+
116+
let currentProps = {...controllerProps};
117+
let lastViewState = currentProps;
118+
119+
const controller = new ControllerClass({
120+
timeline,
121+
onViewStateChange: ({viewState}) => {
122+
lastViewState = viewState;
123+
currentProps = {...currentProps, ...viewState};
124+
controller.setProps(currentProps);
125+
},
126+
onStateChange: () => {},
127+
makeViewport: viewState =>
128+
view.makeViewport({width: currentProps.width, height: currentProps.height, viewState})
129+
});
130+
131+
controller.setProps(currentProps);
132+
133+
const wheelEvent = {
134+
type: 'wheel',
135+
offsetCenter: {x: 50, y: 50},
136+
delta: -1,
137+
srcEvent: {preventDefault() {}},
138+
stopPropagation: () => {}
139+
};
140+
141+
controller.handleEvent(wheelEvent as any);
142+
143+
const speed = 0.01;
144+
const {delta} = wheelEvent;
145+
let scale = 2 / (1 + Math.exp(-Math.abs(delta * speed)));
146+
if (delta < 0 && scale !== 0) {
147+
scale = 1 / scale;
148+
}
149+
const expectedZoom = baseProps.zoom + Math.log2(scale);
150+
151+
t.ok(
152+
Math.abs((lastViewState.zoom as number) - expectedZoom) < 1e-6,
153+
'zoom level updates immediately when scroll zoom is not smooth'
154+
);
155+
156+
t.end();
157+
});
158+
99159
test('FirstPersonController', async t => {
100160
await testController(
101161
t,

0 commit comments

Comments
 (0)