Skip to content

Commit 2fd0227

Browse files
committed
Avoid binding multiple touch listeners for zoom.
For a two-finger pinch, if two touchstart events fire, this results in two touchmove and touchend listeners. The first will have a single location in the locations variable, but its touchmove listener will fire with two touches, causing it to fail due to not finding the location of the second touch. If the first listener fires before the second, this exception breaks touch zooming (as no further listeners will be called), but the order is undefined so may be browser/device dependent (for reproducing the bug). Since zooming only ever involves a single gesture at a time, it makes more sense to only have one listener of each type at a time, unlike dragging, which involves multiple drag gestures at once.
1 parent dddef32 commit 2fd0227

3 files changed

Lines changed: 6 additions & 5 deletions

File tree

d3.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1232,7 +1232,7 @@ d3 = function() {
12321232
}
12331233
}
12341234
function touchstarted() {
1235-
var target = this, event_ = event.of(target, arguments), touches = d3.touches(target), locations = {}, distance0 = 0, scale0 = scale, now = Date.now(), name = "zoom-" + d3.event.changedTouches[0].identifier, touchmove = "touchmove." + name, touchend = "touchend." + name, w = d3.select(d3_window).on(touchmove, moved).on(touchend, ended), t = d3.select(target).on(mousedown, null), dragRestore = d3_event_dragSuppress();
1235+
var target = this, event_ = event.of(target, arguments), touches = d3.touches(target), locations = {}, distance0 = 0, scale0 = scale, now = Date.now(), touchmove = "touchmove.zoom", touchend = "touchend.zoom", w = d3.select(d3_window).on(touchmove, moved).on(touchend, ended), t = d3.select(target).on(mousedown, null), dragRestore = d3_event_dragSuppress();
12361236
touches.forEach(function(t) {
12371237
locations[t.identifier] = location(t);
12381238
});
@@ -1266,6 +1266,7 @@ d3 = function() {
12661266
dispatch(event_);
12671267
}
12681268
function ended() {
1269+
if (d3.event.touches.length) return;
12691270
w.on(touchmove, null).on(touchend, null);
12701271
t.on(mousedown, mousedowned);
12711272
dragRestore();

0 commit comments

Comments
 (0)