Make drawing modes usable on touch devices

This commit is contained in:
Quincy Morgan
2020-03-06 15:17:11 -08:00
parent f8f69a777a
commit 6ed66fb3ce
2 changed files with 70 additions and 38 deletions

View File

@@ -92,7 +92,7 @@ export function behaviorDraw(context) {
d3_select(window).on('click.draw-block', null);
}, 500);
click();
click(d3_mouse(context.surface().node()));
}
}, true);
}
@@ -121,7 +121,7 @@ export function behaviorDraw(context) {
// - `mode/drag_node.js` `doMove()`
// - `behavior/draw.js` `click()`
// - `behavior/draw_way.js` `move()`
function click() {
function click(loc) {
var d = datum();
var target = d && d.properties && d.properties.entity;
@@ -133,7 +133,7 @@ export function behaviorDraw(context) {
} else if (target && target.type === 'way' && (mode.id !== 'add-point' || mode.preset.matchGeometry('vertex'))) { // Snap to a way
var choice = geoChooseEdge(
context.childNodes(target), context.mouse(), context.projection, context.activeID()
context.childNodes(target), loc, context.projection, context.activeID()
);
if (choice) {
var edge = [target.nodes[choice.index - 1], target.nodes[choice.index]];
@@ -141,12 +141,13 @@ export function behaviorDraw(context) {
return;
}
} else if (mode.id !== 'add-point' || mode.preset.matchGeometry('point')) {
dispatch.call('click', this, context.map().mouseCoordinates(), d);
var locLatLng = context.projection.invert(loc);
dispatch.call('click', this, locLatLng, d);
}
}
// treat a spacebar press like a click
function space() {
d3_event.preventDefault();
d3_event.stopPropagation();
@@ -172,7 +173,11 @@ export function behaviorDraw(context) {
d3_select(window).on('keyup.space-block', null);
});
click();
// get the current mouse position
var loc = context.map().mouse() ||
// or the map center if the mouse has never entered the map
context.projection(context.map().center());
click(loc);
}

View File

@@ -16,30 +16,41 @@ import { utilKeybinding } from '../util';
export function behaviorDrawWay(context, wayID, index, mode, startGraph, baselineGraph) {
var origWay = context.entity(wayID);
var _origWay = context.entity(wayID);
var annotation = t((origWay.isDegenerate() ?
var _annotation = t((_origWay.isDegenerate() ?
'operations.start.annotation.' :
'operations.continue.annotation.') + context.geometry(wayID)
);
var behavior = behaviorDraw(context);
behavior.hover().initialNodeID(index ? origWay.nodes[index] :
(origWay.isClosed() ? origWay.nodes[origWay.nodes.length - 2] : origWay.nodes[origWay.nodes.length - 1]));
behavior.hover().initialNodeID(index ? _origWay.nodes[index] :
(_origWay.isClosed() ? _origWay.nodes[_origWay.nodes.length - 2] : _origWay.nodes[_origWay.nodes.length - 1]));
var _tempEdits = 0;
var end = osmNode({ loc: context.map().mouseCoordinates() });
// The osmNode to be placed.
// This is temporary and just follows the mouse cursor until an "add" event occurs.
var _drawNode;
function createDrawNode(loc) {
// don't make the draw node until we actually need it
_drawNode = osmNode({ loc: loc });
context.pauseChangeDispatch();
// Add the drawing node to the graph.
// We must make sure to remove this edit later.
context.perform(_actionAddDrawNode(_drawNode));
_tempEdits++;
context.resumeChangeDispatch();
setActiveElements();
}
// Push an annotated state for undo to return back to.
// We must make sure to remove this edit later.
context.pauseChangeDispatch();
context.perform(actionNoop(), annotation);
_tempEdits++;
// Add the drawing node to the graph.
// We must make sure to remove this edit later.
context.perform(_actionAddDrawNode());
context.perform(actionNoop(), _annotation);
_tempEdits++;
context.resumeChangeDispatch();
@@ -80,24 +91,28 @@ export function behaviorDrawWay(context, wayID, index, mode, startGraph, baselin
// - `behavior/draw.js` `click()`
// - `behavior/draw_way.js` `move()`
function move(datum) {
var loc = context.map().mouseCoordinates();
if (!_drawNode) createDrawNode(loc);
context.surface().classed('nope-disabled', d3_event.altKey);
var targetLoc = datum && datum.properties && datum.properties.entity && allowsVertex(datum.properties.entity) && datum.properties.entity.loc;
var targetNodes = datum && datum.properties && datum.properties.nodes;
var loc = context.map().mouseCoordinates();
if (targetLoc) { // snap to node/vertex - a point target with `.loc`
loc = targetLoc;
} else if (targetNodes) { // snap to way - a line target with `.nodes`
var choice = geoChooseEdge(targetNodes, context.mouse(), context.projection, end.id);
var choice = geoChooseEdge(targetNodes, context.mouse(), context.projection, _drawNode.id);
if (choice) {
loc = choice.loc;
}
}
context.replace(actionMoveNode(end.id, loc));
end = context.entity(end.id);
context.replace(actionMoveNode(_drawNode.id, loc));
_drawNode = context.entity(_drawNode.id);
checkGeometry(false);
}
@@ -107,7 +122,7 @@ export function behaviorDrawWay(context, wayID, index, mode, startGraph, baselin
// `finishDraw` - Only checks the relevant line segments if finishing drawing
function checkGeometry(finishDraw) {
var nopeDisabled = context.surface().classed('nope-disabled');
var isInvalid = isInvalidGeometry(end, context.graph(), finishDraw);
var isInvalid = _drawNode ? isInvalidGeometry(_drawNode, context.graph(), finishDraw) : false;
if (nopeDisabled) {
context.surface()
@@ -128,7 +143,7 @@ export function behaviorDrawWay(context, wayID, index, mode, startGraph, baselin
var parent = parents[i];
var nodes = graph.childNodes(parent).slice(); // shallow copy
if (origWay.isClosed()) { // Check if Area
if (_origWay.isClosed()) { // Check if Area
if (finishDraw) {
if (nodes.length < 3) return false;
nodes.splice(-2, 1);
@@ -172,7 +187,9 @@ export function behaviorDrawWay(context, wayID, index, mode, startGraph, baselin
function setActiveElements() {
context.surface().selectAll('.' + end.id)
if (!_drawNode) return;
context.surface().selectAll('.' + _drawNode.id)
.classed('active', true);
}
@@ -243,20 +260,20 @@ export function behaviorDrawWay(context, wayID, index, mode, startGraph, baselin
};
function _actionAddDrawNode() {
function _actionAddDrawNode(drawNode) {
return function(graph) {
return graph
.replace(end)
.replace(origWay.addNode(end.id, index));
.replace(drawNode)
.replace(_origWay.addNode(drawNode.id, index));
};
}
function _actionReplaceDrawNode(newNode) {
function _actionReplaceDrawNode(drawNode, newNode) {
return function(graph) {
return graph
.replace(origWay.addNode(newNode.id, index))
.remove(end);
.replace(_origWay.addNode(newNode.id, index))
.remove(drawNode);
};
}
@@ -267,13 +284,19 @@ export function behaviorDrawWay(context, wayID, index, mode, startGraph, baselin
return; // can't click here
}
if (!_drawNode) createDrawNode(loc);
// always move the node to the final loc in case move wasn't consistently called (e.g. on touch devices)
context.replace(actionMoveNode(_drawNode.id, loc));
_drawNode = context.entity(_drawNode.id);
context.pauseChangeDispatch();
context.pop(_tempEdits);
_tempEdits = 0;
context.perform(
_actionAddDrawNode(),
annotation
_actionAddDrawNode(_drawNode),
_annotation
);
context.resumeChangeDispatch();
@@ -288,14 +311,16 @@ export function behaviorDrawWay(context, wayID, index, mode, startGraph, baselin
return; // can't click here
}
if (!_drawNode) createDrawNode();
context.pauseChangeDispatch();
context.pop(_tempEdits);
_tempEdits = 0;
context.perform(
_actionAddDrawNode(),
actionAddMidpoint({ loc: loc, edge: edge }, end),
annotation
_actionAddDrawNode(_drawNode),
actionAddMidpoint({ loc: loc, edge: edge }, _drawNode),
_annotation
);
context.resumeChangeDispatch();
@@ -310,13 +335,15 @@ export function behaviorDrawWay(context, wayID, index, mode, startGraph, baselin
return; // can't click here
}
if (!_drawNode) createDrawNode();
context.pauseChangeDispatch();
context.pop(_tempEdits);
_tempEdits = 0;
context.perform(
_actionReplaceDrawNode(node),
annotation
_actionReplaceDrawNode(_drawNode, node),
_annotation
);
context.resumeChangeDispatch();
@@ -378,7 +405,7 @@ export function behaviorDrawWay(context, wayID, index, mode, startGraph, baselin
drawWay.activeID = function() {
if (!arguments.length) return end.id;
if (!arguments.length) return _drawNode && _drawNode.id;
// no assign
return drawWay;
};