Use pointer events for node dragging and drawing (re: #5505)

Enable dragging nodes with touches and styluses (close #7415)
This commit is contained in:
Quincy Morgan
2020-03-05 15:18:39 -08:00
parent 1147438d12
commit 83a51a4192
5 changed files with 42 additions and 47 deletions
+14 -20
View File
@@ -5,8 +5,7 @@ import {
event as d3_event,
mouse as d3_mouse,
select as d3_select,
selection as d3_selection,
touches as d3_touches
selection as d3_selection
} from 'd3-selection';
import { osmNote } from '../osm';
@@ -37,6 +36,8 @@ export function behaviorDrag() {
var _target;
var _surface;
// use pointer events on supported platforms; fallback to mouse events
var _pointerPrefix = 'PointerEvent' in window ? 'pointer' : 'mouse';
var d3_event_userSelectProperty = utilPrefixCSSProperty('UserSelect');
var d3_event_userSelectSuppress = function() {
@@ -68,15 +69,14 @@ export function behaviorDrag() {
_event = eventOf(_target, arguments);
var eventTarget = d3_event.target;
var touchId = d3_event.touches ? d3_event.changedTouches[0].identifier : null;
var offset;
var startOrigin = point();
var started = false;
var selectEnable = d3_event_userSelectSuppress(touchId !== null ? 'drag-' + touchId : 'drag');
var selectEnable = d3_event_userSelectSuppress();
d3_select(window)
.on(touchId !== null ? 'touchmove.drag-' + touchId : 'mousemove.drag', dragmove)
.on(touchId !== null ? 'touchend.drag-' + touchId : 'mouseup.drag', dragend, true);
.on(_pointerPrefix + 'move.drag', dragmove)
.on(_pointerPrefix + 'up.drag', dragend, true);
if (_origin) {
offset = _origin.apply(_target, arguments);
@@ -85,16 +85,12 @@ export function behaviorDrag() {
offset = [0, 0];
}
if (touchId === null) {
d3_event.stopPropagation();
}
d3_event.stopPropagation();
function point() {
var p = _surface || _target.parentNode;
return touchId !== null ? d3_touches(p).filter(function(p) {
return p.identifier === touchId;
})[0] : d3_mouse(p);
return d3_mouse(p);
}
@@ -134,8 +130,8 @@ export function behaviorDrag() {
}
d3_select(window)
.on(touchId !== null ? 'touchmove.drag-' + touchId : 'mousemove.drag', null)
.on(touchId !== null ? 'touchend.drag-' + touchId : 'mouseup.drag', null);
.on(_pointerPrefix + 'move.drag', null)
.on(_pointerPrefix + 'up.drag', null);
selectEnable();
}
@@ -171,15 +167,13 @@ export function behaviorDrag() {
}
selection
.on('mousedown.drag' + _selector, delegate)
.on('touchstart.drag' + _selector, delegate);
.on(_pointerPrefix + 'down.drag' + _selector, delegate);
}
behavior.off = function(selection) {
selection
.on('mousedown.drag' + _selector, null)
.on('touchstart.drag' + _selector, null);
.on(_pointerPrefix + 'down.drag' + _selector, null);
};
@@ -199,8 +193,8 @@ export function behaviorDrag() {
behavior.cancel = function() {
d3_select(window)
.on('mousemove.drag', null)
.on('mouseup.drag', null);
.on(_pointerPrefix + 'move.drag', null)
.on(_pointerPrefix + 'up.drag', null);
return behavior;
};
+17 -19
View File
@@ -3,8 +3,7 @@ import { dispatch as d3_dispatch } from 'd3-dispatch';
import {
event as d3_event,
mouse as d3_mouse,
select as d3_select,
touches as d3_touches
select as d3_select
} from 'd3-selection';
import { behaviorEdit } from './edit';
@@ -35,6 +34,9 @@ export function behaviorDraw(context) {
var _mouseLeave = false;
var _lastMouse = null;
// use pointer events on supported platforms; fallback to mouse events
var _pointerPrefix = 'PointerEvent' in window ? 'pointer' : 'mouse';
// related code
// - `mode/drag_node.js` `datum()`
@@ -57,29 +59,25 @@ export function behaviorDraw(context) {
}
function mousedown() {
function pointerdown() {
function point() {
var p = context.container().node();
return touchId !== null ? d3_touches(p).filter(function(p) {
return p.identifier === touchId;
})[0] : d3_mouse(p);
return d3_mouse(context.container().node());
}
var element = d3_select(this);
var touchId = d3_event.touches ? d3_event.changedTouches[0].identifier : null;
var t1 = +new Date();
var p1 = point();
element.on('mousemove.draw', null);
element.on(_pointerPrefix + 'move.draw', null);
d3_select(window).on('mouseup.draw', function() {
d3_select(window).on(_pointerPrefix + 'up.draw', function() {
var t2 = +new Date();
var p2 = point();
var dist = geoVecLength(p1, p2);
element.on('mousemove.draw', mousemove);
d3_select(window).on('mouseup.draw', null);
element.on(_pointerPrefix + 'move.draw', pointermove);
d3_select(window).on(_pointerPrefix + 'up.draw', null);
if (dist < closeTolerance || (dist < tolerance && (t2 - t1) < 500)) {
// Prevent a quick second click
@@ -100,7 +98,7 @@ export function behaviorDraw(context) {
}
function mousemove() {
function pointermove() {
_lastMouse = d3_event;
dispatch.call('move', this, datum());
}
@@ -120,7 +118,7 @@ export function behaviorDraw(context) {
}
// related code
// - `mode/drag_node.js` `doMode()`
// - `mode/drag_node.js` `doMove()`
// - `behavior/draw.js` `click()`
// - `behavior/draw_way.js` `move()`
function click() {
@@ -215,8 +213,8 @@ export function behaviorDraw(context) {
selection
.on('mouseenter.draw', mouseenter)
.on('mouseleave.draw', mouseleave)
.on('mousedown.draw', mousedown)
.on('mousemove.draw', mousemove);
.on(_pointerPrefix + 'down.draw', pointerdown)
.on(_pointerPrefix + 'move.draw', pointermove);
d3_select(document)
.call(keybinding);
@@ -238,11 +236,11 @@ export function behaviorDraw(context) {
selection
.on('mouseenter.draw', null)
.on('mouseleave.draw', null)
.on('mousedown.draw', null)
.on('mousemove.draw', null);
.on(_pointerPrefix + 'down.draw', null)
.on(_pointerPrefix + 'move.draw', null);
d3_select(window)
.on('mouseup.draw', null);
.on(_pointerPrefix + 'up.draw', null);
// note: keyup.space-block, click.draw-block should remain
d3_select(document)
+1 -1
View File
@@ -76,7 +76,7 @@ export function behaviorDrawWay(context, wayID, index, mode, startGraph, baselin
// related code
// - `mode/drag_node.js` `doMode()`
// - `mode/drag_node.js` `doMove()`
// - `behavior/draw.js` `click()`
// - `behavior/draw_way.js` `move()`
function move(datum) {
+1 -1
View File
@@ -192,7 +192,7 @@ export function modeDragNode(context) {
if (!_nudgeInterval) { // If not nudging at the edge of the viewport, try to snap..
// related code
// - `mode/drag_node.js` `doMode()`
// - `mode/drag_node.js` `doMove()`
// - `behavior/draw.js` `click()`
// - `behavior/draw_way.js` `move()`
var d = datum();
+9 -6
View File
@@ -64,6 +64,9 @@ export function rendererMap(context) {
// whether a pointerdown event started the zoom
var _pointerDown = false;
// use pointer events on supported platforms; fallback to mouse events
var _pointerPrefix = 'PointerEvent' in window ? 'pointer' : 'mouse';
// use pointer event interaction if supported; fallback to touch/mouse events in d3-zoom
var _zoomerPannerFunction = 'PointerEvent' in window ? utilZoomPan : d3_zoom;
@@ -169,27 +172,27 @@ export function rendererMap(context) {
_gestureTransformStart = projection.transform();
})
.on('gesturechange.surface', gestureChange)
.on('mousedown.zoom', function() {
.on(_pointerPrefix + 'down.zoom', function() {
if (d3_event.button === 2) {
d3_event.stopPropagation();
}
}, true)
.on('mouseup.zoom', function() {
.on(_pointerPrefix + 'up.zoom', function() {
if (resetTransform()) {
immediateRedraw();
}
})
.on('mousemove.map', function() {
.on(_pointerPrefix + 'move.map', function() {
_mouseEvent = d3_event;
})
.on('mouseover.vertices', function() {
.on(_pointerPrefix + 'over.vertices', function() {
if (map.editableDataEnabled() && !_isTransformed) {
var hover = d3_event.target.__data__;
surface.call(drawVertices.drawHover, context.graph(), hover, map.extent());
dispatch.call('drawn', this, { full: false });
}
})
.on('mouseout.vertices', function() {
.on(_pointerPrefix + 'out.vertices', function() {
if (map.editableDataEnabled() && !_isTransformed) {
var hover = d3_event.relatedTarget && d3_event.relatedTarget.__data__;
surface.call(drawVertices.drawHover, context.graph(), hover, map.extent());
@@ -898,7 +901,7 @@ export function rendererMap(context) {
map.startEase = function() {
utilBindOnce(surface, 'mousedown.ease', function() {
utilBindOnce(surface, _pointerPrefix + 'down.ease', function() {
map.cancelEase();
});
return map;