Skip to content

Commit 484ba62

Browse files
fix(core): disable pinch zoom inertia
1 parent 5971f24 commit 484ba62

2 files changed

Lines changed: 35 additions & 69 deletions

File tree

modules/core/src/controllers/controller.ts

Lines changed: 7 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ const NO_TRANSITION_PROPS = {
2121
const DEFAULT_INERTIA = 300;
2222
const INERTIA_EASING = t => 1 - (1 - t) * (1 - t);
2323
const MAX_PINCH_ZOOM_DELTA_PER_EVENT = 0.18;
24-
const MAX_PINCH_INERTIA_ZOOM_DELTA = 0.35;
2524

2625
const EVENT_TYPES = {
2726
WHEEL: ['wheel'],
@@ -655,9 +654,7 @@ export default abstract class Controller<ControllerState extends IViewState<Cont
655654
const newControllerState = this.controllerState.zoomStart({pos}).rotateStart({pos});
656655
// hack - hammer's `rotation` field doesn't seem to produce the correct angle
657656
pinchEventWorkaround._startPinchRotation = event.rotation;
658-
pinchEventWorkaround._lastPinchEvent = event;
659657
pinchEventWorkaround._smoothedPinchScaleLog = 0;
660-
pinchEventWorkaround._lastPinchScaleLog = 0;
661658
this.updateViewport(newControllerState, NO_TRANSITION_PROPS, {isDragging: true});
662659
return true;
663660
}
@@ -679,7 +676,6 @@ export default abstract class Controller<ControllerState extends IViewState<Cont
679676
const previousScaleLog = pinchEventWorkaround._smoothedPinchScaleLog ?? 0;
680677
const smoothedScaleLog =
681678
previousScaleLog + clampPinchZoomDelta(rawScaleLog - previousScaleLog);
682-
pinchEventWorkaround._lastPinchScaleLog = previousScaleLog;
683679
pinchEventWorkaround._smoothedPinchScaleLog = smoothedScaleLog;
684680
newControllerState = newControllerState.zoom({pos, scale: Math.pow(2, smoothedScaleLog)});
685681
}
@@ -696,59 +692,22 @@ export default abstract class Controller<ControllerState extends IViewState<Cont
696692
isZooming: this.touchZoom,
697693
isRotating: this.touchRotate
698694
});
699-
pinchEventWorkaround._lastPinchEvent = event;
700695
return true;
701696
}
702697

703698
protected _onPinchEnd(event: MjolnirGestureEvent): boolean {
704699
if (!this.isDragging()) {
705700
return false;
706701
}
707-
const {inertia} = this;
708-
const {_lastPinchEvent} = pinchEventWorkaround;
709-
if (this.touchZoom && inertia && _lastPinchEvent && event.scale !== _lastPinchEvent.scale) {
710-
const pos = this.getCenter(event);
711-
let newControllerState = this.controllerState.rotateEnd();
712-
const z = pinchEventWorkaround._smoothedPinchScaleLog ?? Math.log2(event.scale);
713-
const lastZ = pinchEventWorkaround._lastPinchScaleLog ?? Math.log2(_lastPinchEvent.scale);
714-
const deltaTime = Math.max(16, event.deltaTime - _lastPinchEvent.deltaTime);
715-
const velocityZ =
716-
(z - lastZ) / deltaTime;
717-
const inertiaZoomDelta = Math.max(
718-
-MAX_PINCH_INERTIA_ZOOM_DELTA,
719-
Math.min(MAX_PINCH_INERTIA_ZOOM_DELTA, (velocityZ * inertia) / 2)
720-
);
721-
const endScale = Math.pow(2, z + inertiaZoomDelta);
722-
newControllerState = newControllerState.zoom({pos, scale: endScale}).zoomEnd();
723-
724-
this.updateViewport(
725-
newControllerState,
726-
{
727-
...this._getTransitionProps({around: pos}),
728-
transitionDuration: inertia,
729-
transitionEasing: INERTIA_EASING
730-
},
731-
{
732-
isDragging: false,
733-
isPanning: this.touchZoom,
734-
isZooming: this.touchZoom,
735-
isRotating: false
736-
}
737-
);
738-
this.blockEvents(inertia);
739-
} else {
740-
const newControllerState = this.controllerState.zoomEnd().rotateEnd();
741-
this.updateViewport(newControllerState, null, {
742-
isDragging: false,
743-
isPanning: false,
744-
isZooming: false,
745-
isRotating: false
746-
});
747-
}
702+
const newControllerState = this.controllerState.zoomEnd().rotateEnd();
703+
this.updateViewport(newControllerState, null, {
704+
isDragging: false,
705+
isPanning: false,
706+
isZooming: false,
707+
isRotating: false
708+
});
748709
pinchEventWorkaround._startPinchRotation = null;
749-
pinchEventWorkaround._lastPinchEvent = null;
750710
pinchEventWorkaround._smoothedPinchScaleLog = null;
751-
pinchEventWorkaround._lastPinchScaleLog = null;
752711
return true;
753712
}
754713

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

Lines changed: 28 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -35,19 +35,7 @@ test('MapController#inertia', async () => {
3535
});
3636
});
3737

38-
test('MapController clamps noisy pinch zoom-out frames', () => {
39-
const controller = createTestController({
40-
view: new MapView({controller: true}),
41-
initialViewState: {
42-
longitude: -122.45,
43-
latitude: 37.78,
44-
zoom: 10,
45-
pitch: 30,
46-
bearing: -45,
47-
inertia: 300
48-
}
49-
});
50-
38+
test('MapController does not apply pinch zoom inertia after quick lift', () => {
5139
const makePinchEvent = (type: string, scale: number, deltaTime: number) => ({
5240
type,
5341
offsetCenter: {x: 50, y: 50},
@@ -58,14 +46,33 @@ test('MapController clamps noisy pinch zoom-out frames', () => {
5846
stopPropagation() {}
5947
});
6048

61-
controller.handleEvent(makePinchEvent('pinchstart', 1, 0) as any);
62-
controller.handleEvent(makePinchEvent('pinchmove', 0.01, 16) as any);
63-
controller.handleEvent(makePinchEvent('pinchend', 0.001, 17) as any);
64-
65-
expect(
66-
controller.props.zoom,
67-
'a noisy pinch-out should not jump more than the smoothed move plus capped inertia'
68-
).toBeGreaterThanOrEqual(9.47);
49+
for (const {moveScale, endScale} of [
50+
{moveScale: 0.01, endScale: 0.001},
51+
{moveScale: 100, endScale: 1000}
52+
]) {
53+
const controller = createTestController({
54+
view: new MapView({controller: true}),
55+
initialViewState: {
56+
longitude: -122.45,
57+
latitude: 37.78,
58+
zoom: 10,
59+
pitch: 30,
60+
bearing: -45,
61+
inertia: 300
62+
}
63+
});
64+
65+
controller.handleEvent(makePinchEvent('pinchstart', 1, 0) as any);
66+
controller.handleEvent(makePinchEvent('pinchmove', moveScale, 16) as any);
67+
const zoomAfterMove = controller.props.zoom;
68+
69+
controller.handleEvent(makePinchEvent('pinchend', endScale, 17) as any);
70+
71+
expect(
72+
controller.props.zoom,
73+
'quick two-finger lift should end at the last live pinch zoom'
74+
).toBeCloseTo(zoomAfterMove);
75+
}
6976
});
7077

7178
test('GlobeController', async () => {

0 commit comments

Comments
 (0)