Skip to content

Commit

Permalink
Continue zoom/pan of map when a down pointer moves off the map (re: #…
Browse files Browse the repository at this point in the history
…5505)

Fix possibly #6745
  • Loading branch information
quincylvania committed May 8, 2020
1 parent 509ee8f commit 5a8f573
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 27 deletions.
2 changes: 1 addition & 1 deletion modules/renderer/map.js
Original file line number Diff line number Diff line change
Expand Up @@ -555,7 +555,7 @@ export function rendererMap(context) {
y = y2;
k = k2;
eventTransform = d3_zoomIdentity.translate(x2, y2).scale(k2);
_selection.node().__zoom = eventTransform;
_zoomerPanner._transform(eventTransform);
}

}
Expand Down
58 changes: 32 additions & 26 deletions modules/util/zoom_pan.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

import { dispatch as d3_dispatch } from 'd3-dispatch';
import { interpolateZoom } from 'd3-interpolate';
import { event as d3_event, customEvent as d3_customEvent } from 'd3-selection';
import { event as d3_event, customEvent as d3_customEvent, select as d3_select } from 'd3-selection';
import { interrupt as d3_interrupt } from 'd3-transition';
import { zoomIdentity as d3_zoomIdentity } from 'd3-zoom';
import ZoomEvent from '../../node_modules/d3-zoom/src/event.js';
Expand All @@ -29,10 +29,6 @@ function defaultExtent() {
return [[0, 0], [e.clientWidth, e.clientHeight]];
}

function defaultTransform() {
return this.__zoom || d3_zoomIdentity;
}

function defaultWheelDelta() {
return -d3_event.deltaY * (d3_event.deltaMode === 1 ? 0.05 : d3_event.deltaMode ? 1 : 0.002);
}
Expand All @@ -57,22 +53,24 @@ export function utilZoomPan() {
translateExtent = [[-Infinity, -Infinity], [Infinity, Infinity]],
interpolate = interpolateZoom,
listeners = d3_dispatch('start', 'zoom', 'end'),
_wheelDelay = 150;
_wheelDelay = 150,
_transform = d3_zoomIdentity,
_activeGesture;

function zoom(selection) {
selection
.property('__zoom', defaultTransform)
.on('pointerdown.zoom', pointerdown)
.on('pointermove.zoom', pointermove)
.on('pointerup.zoom pointercancel.zoom', pointerup)
.on('wheel.zoom', wheeled)
.style('touch-action', 'none')
.style('-webkit-tap-highlight-color', 'rgba(0,0,0,0)');

d3_select(window)
.on('pointermove.zoompan', pointermove)
.on('pointerup.zoompan pointercancel.zoompan', pointerup);
}

zoom.transform = function(collection, transform, point) {
var selection = collection.selection ? collection.selection() : collection;
selection.property('__zoom', defaultTransform);
if (collection !== selection) {
schedule(collection, transform, point);
} else {
Expand All @@ -87,7 +85,7 @@ export function utilZoomPan() {

zoom.scaleBy = function(selection, k, p) {
zoom.scaleTo(selection, function() {
var k0 = this.__zoom.k,
var k0 = _transform.k,
k1 = typeof k === 'function' ? k.apply(this, arguments) : k;
return k0 * k1;
}, p);
Expand All @@ -96,7 +94,7 @@ export function utilZoomPan() {
zoom.scaleTo = function(selection, k, p) {
zoom.transform(selection, function() {
var e = extent.apply(this, arguments),
t0 = this.__zoom,
t0 = _transform,
p0 = p == null ? centroid(e) : typeof p === 'function' ? p.apply(this, arguments) : p,
p1 = t0.invert(p0),
k1 = typeof k === 'function' ? k.apply(this, arguments) : k;
Expand All @@ -106,7 +104,7 @@ export function utilZoomPan() {

zoom.translateBy = function(selection, x, y) {
zoom.transform(selection, function() {
return constrain(this.__zoom.translate(
return constrain(_transform.translate(
typeof x === 'function' ? x.apply(this, arguments) : x,
typeof y === 'function' ? y.apply(this, arguments) : y
), extent.apply(this, arguments), translateExtent);
Expand All @@ -116,7 +114,7 @@ export function utilZoomPan() {
zoom.translateTo = function(selection, x, y, p) {
zoom.transform(selection, function() {
var e = extent.apply(this, arguments),
t = this.__zoom,
t = _transform,
p0 = p == null ? centroid(e) : typeof p === 'function' ? p.apply(this, arguments) : p;
return constrain(d3_zoomIdentity.translate(p0[0], p0[1]).scale(t.k).translate(
typeof x === 'function' ? -x.apply(this, arguments) : -x,
Expand Down Expand Up @@ -150,7 +148,7 @@ export function utilZoomPan() {
e = extent.apply(that, args),
p = point == null ? centroid(e) : typeof point === 'function' ? point.apply(that, args) : point,
w = Math.max(e[1][0] - e[0][0], e[1][1] - e[0][1]),
a = that.__zoom,
a = _transform,
b = typeof transform === 'function' ? transform.apply(that, args) : transform,
i = interpolate(a.invert(p).concat(w / a.k), b.invert(p).concat(w / b.k));
return function(t) {
Expand All @@ -162,7 +160,7 @@ export function utilZoomPan() {
}

function gesture(that, args, clean) {
return (!clean && that.__zooming) || new Gesture(that, args);
return (!clean && _activeGesture) || new Gesture(that, args);
}

function Gesture(that, args) {
Expand All @@ -175,7 +173,7 @@ export function utilZoomPan() {
Gesture.prototype = {
start: function() {
if (++this.active === 1) {
this.that.__zooming = this;
_activeGesture = this;
this.emit('start');
}
return this;
Expand All @@ -184,26 +182,26 @@ export function utilZoomPan() {
if (this.mouse && key !== 'mouse') this.mouse[1] = transform.invert(this.mouse[0]);
if (this.pointer0 && key !== 'touch') this.pointer0[1] = transform.invert(this.pointer0[0]);
if (this.pointer1 && key !== 'touch') this.pointer1[1] = transform.invert(this.pointer1[0]);
this.that.__zoom = transform;
_transform = transform;
this.emit('zoom');
return this;
},
end: function() {
if (--this.active === 0) {
delete this.that.__zooming;
_activeGesture = null;
this.emit('end');
}
return this;
},
emit: function(type) {
d3_customEvent(new ZoomEvent(zoom, type, this.that.__zoom), listeners.apply, listeners, [type, this.that, this.args]);
d3_customEvent(new ZoomEvent(zoom, type, _transform), listeners.apply, listeners, [type, this.that, this.args]);
}
};

function wheeled() {
if (!filter.apply(this, arguments)) return;
var g = gesture(this, arguments),
t = this.__zoom,
t = _transform,
k = Math.max(scaleExtent[0], Math.min(scaleExtent[1], t.k * Math.pow(2, wheelDelta.apply(this, arguments)))),
p = utilFastMouse(this)(d3_event);

Expand Down Expand Up @@ -251,7 +249,7 @@ export function utilZoomPan() {
d3_event.stopImmediatePropagation();
_pointerLocGetter = utilFastMouse(this);
var loc = _pointerLocGetter(d3_event);
var p = [loc, this.__zoom.invert(loc), d3_event.pointerId];
var p = [loc, _transform.invert(loc), d3_event.pointerId];
if (!g.pointer0) {
g.pointer0 = p;
started = true;
Expand All @@ -267,7 +265,9 @@ export function utilZoomPan() {
}

function pointermove() {
if (!this.__zooming || !_pointerLocGetter) return;
if (!_downPointerIDs.has(d3_event.pointerId)) return;

if (!_activeGesture || !_pointerLocGetter) return;

var g = gesture(this, arguments);

Expand All @@ -292,7 +292,7 @@ export function utilZoomPan() {
if (isPointer0) g.pointer0[0] = loc;
else if (isPointer1) g.pointer1[0] = loc;

t = g.that.__zoom;
t = _transform;
if (g.pointer1) {
var p0 = g.pointer0[0], l0 = g.pointer0[1],
p1 = g.pointer1[0], l1 = g.pointer1[1],
Expand All @@ -310,9 +310,11 @@ export function utilZoomPan() {
}

function pointerup() {
if (!_downPointerIDs.has(d3_event.pointerId)) return;

_downPointerIDs.delete(d3_event.pointerId);

if (!this.__zooming) return;
if (!_activeGesture) return;

var g = gesture(this, arguments);

Expand All @@ -325,7 +327,7 @@ export function utilZoomPan() {
g.pointer0 = g.pointer1;
delete g.pointer1;
}
if (g.pointer0) g.pointer0[1] = this.__zoom.invert(g.pointer0[0]);
if (g.pointer0) g.pointer0[1] = _transform.invert(g.pointer0[0]);
else {
g.end();
}
Expand Down Expand Up @@ -359,6 +361,10 @@ export function utilZoomPan() {
return arguments.length ? (interpolate = _, zoom) : interpolate;
};

zoom._transform = function(_) {
return arguments.length ? (_transform = _, zoom) : _transform;
};

zoom.on = function() {
var value = listeners.on.apply(listeners, arguments);
return value === listeners ? zoom : value;
Expand Down

0 comments on commit 5a8f573

Please sign in to comment.