Skip to content

Commit 3b39c58

Browse files
ansiskarimnaaji
authored andcommitted
map.isMoving() match move events fix #9647 (#9679)
* map.isMoving() match move events fix #9647 Previously isMoving() would return true if any interaction handler was active. Handlers are sometimes active even if they haven't changed the map yet. This resulted in the isMoving() returning true when the map hasn't moved. This makes isMoving aligned with movestart/move/moveend events. Since move events may be fired after several mouse events have been batched, the camera changes a mouseevent will *later* cause won't be reflected in isMoving() when that mouseevent is fired. * lint * fix test
1 parent 1f1b8a5 commit 3b39c58

File tree

5 files changed

+68
-9
lines changed

5 files changed

+68
-9
lines changed

src/ui/handler_manager.js

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,10 @@ class HandlerManager {
259259
return !!this._eventsInProgress.rotate;
260260
}
261261

262+
isMoving() {
263+
return Boolean(isMoving(this._eventsInProgress)) || this.isZooming();
264+
}
265+
262266
_blockedByActive(activeHandlers: { [string]: Handler }, allowed: Array<string>, myName: string) {
263267
for (const name in activeHandlers) {
264268
if (name === myName) continue;
@@ -430,17 +434,23 @@ class HandlerManager {
430434
const wasMoving = isMoving(this._eventsInProgress);
431435
const nowMoving = isMoving(newEventsInProgress);
432436

433-
if (!wasMoving && nowMoving) {
434-
this._fireEvent('movestart', nowMoving.originalEvent);
435-
}
437+
const startEvents = {};
436438

437439
for (const eventName in newEventsInProgress) {
438440
const {originalEvent} = newEventsInProgress[eventName];
439-
const isStart = !this._eventsInProgress[eventName];
440-
this._eventsInProgress[eventName] = newEventsInProgress[eventName];
441-
if (isStart) {
442-
this._fireEvent(`${eventName}start`, originalEvent);
441+
if (!this._eventsInProgress[eventName]) {
442+
startEvents[`${eventName}start`] = originalEvent;
443443
}
444+
this._eventsInProgress[eventName] = newEventsInProgress[eventName];
445+
}
446+
447+
// fire start events only after this._eventsInProgress has been updated
448+
if (!wasMoving && nowMoving) {
449+
this._fireEvent('movestart', nowMoving.originalEvent);
450+
}
451+
452+
for (const name in startEvents) {
453+
this._fireEvent(name, startEvents[name]);
444454
}
445455

446456
if (newEventsInProgress.rotate) this._bearingChanged = true;
@@ -454,16 +464,22 @@ class HandlerManager {
454464
this._fireEvent(eventName, originalEvent);
455465
}
456466

467+
const endEvents = {};
468+
457469
let originalEndEvent;
458470
for (const eventName in this._eventsInProgress) {
459471
const {handlerName, originalEvent} = this._eventsInProgress[eventName];
460472
if (!this._handlersById[handlerName].isActive()) {
461473
delete this._eventsInProgress[eventName];
462474
originalEndEvent = deactivatedHandlers[handlerName] || originalEvent;
463-
this._fireEvent(`${eventName}end`, originalEndEvent);
475+
endEvents[`${eventName}end`] = originalEndEvent;
464476
}
465477
}
466478

479+
for (const name in endEvents) {
480+
this._fireEvent(name, endEvents[name]);
481+
}
482+
467483
const stillMoving = isMoving(this._eventsInProgress);
468484
if ((wasMoving || nowMoving) && !stillMoving) {
469485
this._updatingCamera = true;

src/ui/map.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -853,7 +853,7 @@ class Map extends Camera {
853853
* var isMoving = map.isMoving();
854854
*/
855855
isMoving(): boolean {
856-
return this._moving || this.handlers.isActive();
856+
return this._moving || this.handlers.isMoving();
857857
}
858858

859859
/**

test/unit/ui/handler/drag_rotate.test.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,9 +273,11 @@ test('DragRotateHandler ensures that map.isMoving() returns true during drag', (
273273

274274
simulate.mousedown(map.getCanvas(), {buttons: 2, button: 2});
275275
simulate.mousemove(map.getCanvas(), {buttons: 2, clientX: 10, clientY: 10});
276+
map._renderTaskQueue.run();
276277
t.ok(map.isMoving());
277278

278279
simulate.mouseup(map.getCanvas(), {buttons: 0, button: 2});
280+
map._renderTaskQueue.run();
279281
t.ok(!map.isMoving());
280282

281283
map.remove();

test/unit/ui/map/isMoving.test.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,18 @@ test('Map#isMoving returns true during a camera zoom animation', (t) => {
3636
test('Map#isMoving returns true when drag panning', (t) => {
3737
const map = createMap(t);
3838

39+
map.on('movestart', () => {
40+
t.equal(map.isMoving(), true);
41+
});
3942
map.on('dragstart', () => {
4043
t.equal(map.isMoving(), true);
4144
});
4245

4346
map.on('dragend', () => {
4447
t.equal(map.isMoving(), false);
48+
});
49+
map.on('moveend', () => {
50+
t.equal(map.isMoving(), false);
4551
map.remove();
4652
t.end();
4753
});
@@ -62,12 +68,18 @@ test('Map#isMoving returns true when drag rotating', (t) => {
6268
// Prevent inertial rotation.
6369
t.stub(browser, 'now').returns(0);
6470

71+
map.on('movestart', () => {
72+
t.equal(map.isMoving(), true);
73+
});
6574
map.on('rotatestart', () => {
6675
t.equal(map.isMoving(), true);
6776
});
6877

6978
map.on('rotateend', () => {
7079
t.equal(map.isMoving(), false);
80+
});
81+
map.on('moveend', () => {
82+
t.equal(map.isMoving(), false);
7183
map.remove();
7284
t.end();
7385
});

test/unit/ui/map_events.test.js

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -601,3 +601,32 @@ test(`Map#on click fires subsequent click event if there is no corresponding mou
601601
map.remove();
602602
t.end();
603603
});
604+
605+
test("Map#isMoving() returns false in mousedown/mouseup/click with no movement", (t) => {
606+
const map = createMap(t, {interactive: true, clickTolerance: 4});
607+
let mousedown, mouseup, click;
608+
map.on('mousedown', () => { mousedown = map.isMoving(); });
609+
map.on('mouseup', () => { mouseup = map.isMoving(); });
610+
map.on('click', () => { click = map.isMoving(); });
611+
612+
const canvas = map.getCanvas();
613+
const MouseEvent = window(canvas).MouseEvent;
614+
615+
canvas.dispatchEvent(new MouseEvent('mousedown', {bubbles: true, clientX: 100, clientY: 100}));
616+
t.equal(mousedown, false);
617+
map._renderTaskQueue.run();
618+
t.equal(mousedown, false);
619+
620+
canvas.dispatchEvent(new MouseEvent('mouseup', {bubbles: true, clientX: 100, clientY: 100}));
621+
t.equal(mouseup, false);
622+
map._renderTaskQueue.run();
623+
t.equal(mouseup, false);
624+
625+
canvas.dispatchEvent(new MouseEvent('click', {bubbles: true, clientX: 100, clientY: 100}));
626+
t.equal(click, false);
627+
map._renderTaskQueue.run();
628+
t.equal(click, false);
629+
630+
map.remove();
631+
t.end();
632+
});

0 commit comments

Comments
 (0)