Skip to content

Commit

Permalink
Fix drag handlers to gracefully handle interruptions (#6125)
Browse files Browse the repository at this point in the history
Cherry picking #6113 into master 
Closes #6106
  • Loading branch information
anandthakker authored Feb 9, 2018
1 parent b88ec9d commit adfc154
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 9 deletions.
19 changes: 13 additions & 6 deletions src/ui/handler/drag_pan.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ class DragPanHandler {
_active: boolean;
_pos: Point;
_previousPos: Point;
_startPos: Point;
_inertia: Array<[number, Point]>;
_lastMoveEvent: MouseEvent | TouchEvent | void;

Expand Down Expand Up @@ -107,18 +106,27 @@ class DragPanHandler {
window.addEventListener('blur', this._onMouseUp);

this._active = false;
this._startPos = this._previousPos = DOM.mousePos(this._el, e);
this._inertia = [[browser.now(), this._startPos]];
this._previousPos = DOM.mousePos(this._el, e);
this._inertia = [[browser.now(), this._previousPos]];
}

_onMove(e: MouseEvent | TouchEvent) {
if (this._ignoreEvent(e)) return;
this._lastMoveEvent = e;
e.preventDefault();

this._pos = DOM.mousePos(this._el, e);
const pos = DOM.mousePos(this._el, e);
this._drainInertiaBuffer();
this._inertia.push([browser.now(), this._pos]);
this._inertia.push([browser.now(), pos]);

// if the dragging animation was interrupted (e.g. by another handler),
// we need to reestablish a _previousPos before we can resume dragging
if (!this._previousPos) {
this._previousPos = pos;
return;
}

this._pos = pos;

if (!this.isActive()) {
// we treat the first move event (rather than the mousedown event)
Expand Down Expand Up @@ -160,7 +168,6 @@ class DragPanHandler {

this._active = false;
delete this._lastMoveEvent;
delete this._startPos;
delete this._previousPos;
delete this._pos;

Expand Down
13 changes: 10 additions & 3 deletions src/ui/handler/drag_rotate.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ class DragRotateHandler {
_lastMoveEvent: MouseEvent;
_pos: Point;
_previousPos: Point;
_startPos: Point;
_inertia: Array<[number, number]>;
_center: Point;

Expand Down Expand Up @@ -132,15 +131,23 @@ class DragRotateHandler {

this._active = false;
this._inertia = [[browser.now(), this._map.getBearing()]];
this._startPos = this._previousPos = DOM.mousePos(this._el, e);
this._previousPos = DOM.mousePos(this._el, e);
this._center = this._map.transform.centerPoint; // Center of rotation

e.preventDefault();
}

_onMove(e: MouseEvent) {
this._lastMoveEvent = e;
this._pos = DOM.mousePos(this._el, e);
const pos = DOM.mousePos(this._el, e);
// if the dragging animation was interrupted (e.g. by another handler),
// we need to reestablish a _previousPos before we can resume dragging
if (!this._previousPos) {
this._previousPos = pos;
return;
}

this._pos = pos;

if (!this.isActive()) {
this._active = true;
Expand Down
19 changes: 19 additions & 0 deletions test/unit/ui/handler/drag_pan.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,22 @@ test('DragPanHandler requests a new render frame after each mousemove event', (t
t.equal(update.callCount, 1);
t.end();
});

test('DragPanHandler recovers after interruption by another handler', (t) => {
// https://github.com/mapbox/mapbox-gl-js/issues/6106
const map = createMap();
const initialCenter = map.getCenter();
simulate.mousedown(map.getCanvas(), {bubbles: true, buttons: 2, clientX: 10, clientY: 10});
simulate.mousemove(map.getCanvas(), {bubbles: true, buttons: 2, clientX: 12, clientY: 10});
map._updateCamera();

// simluates another handler taking over
map.stop();

simulate.mousemove(map.getCanvas(), {bubbles: true, buttons: 2, clientX: 14, clientY: 10});
simulate.mousemove(map.getCanvas(), {bubbles: true, buttons: 2, clientX: 16, clientY: 10});
map._updateCamera();
t.equalWithPrecision(map.getCenter().lng, initialCenter.lng - 2.8125, 1e-4);
t.end();
});

17 changes: 17 additions & 0 deletions test/unit/ui/handler/drag_rotate.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -361,3 +361,20 @@ test('DragRotateHandler ends rotation if the window blurs (#3389)', (t) => {

t.end();
});

test('DragRotateHandler recovers after interruptino by another handler', (t) => {
// https://github.com/mapbox/mapbox-gl-js/issues/6106
const map = createMap();
const initialBearing = map.getBearing();
simulate.mousedown(map.getCanvas(), {bubbles: true, buttons: 2, button: 2, clientX: 10, clientY: 10});
simulate.mousemove(map.getCanvas(), {bubbles: true, buttons: 2, clientX: 12, clientY: 10});
map._updateCamera();

// simluates another handler taking over
map.stop();
simulate.mousemove(map.getCanvas(), {bubbles: true, buttons: 2, clientX: 12, clientY: 10});
simulate.mousemove(map.getCanvas(), {bubbles: true, buttons: 2, clientX: 14, clientY: 10});
map._updateCamera();
t.equalWithPrecision(map.getBearing(), initialBearing + 3.2, 1e-6);
t.end();
});

0 comments on commit adfc154

Please sign in to comment.