Implement touch targets for midpoints and points

This commit is contained in:
Bryan Housel
2017-12-15 22:50:55 -05:00
parent 9d42d470ca
commit 5cb5456869
5 changed files with 98 additions and 43 deletions

View File

@@ -7,19 +7,19 @@ use { pointer-events: none; }
/* the above fill: none rule affects paths in <use> shadow dom only in Firefox */
.layer-osm use.icon path { fill: #333; } /* FF svg Maki icons */
.layer-osm .turn use path { fill: #000; } /* FF turn restriction icons */
#turn-only-shape2, #turn-only-u-shape2 { fill: #7092FF; } /* FF turn-only, turn-only-u */
#turn-no-shape2, #turn-no-u-shape2 { fill: #E06D5F; } /* FF turn-no, turn-no-u */
#turn-yes-shape2, #turn-yes-u-shape2 { fill: #8CD05F; } /* FF turn-yes, turn-yes-u */
#turn-only-shape2, #turn-only-u-shape2 { fill: #7092ff; } /* FF turn-only, turn-only-u */
#turn-no-shape2, #turn-no-u-shape2 { fill: #e06d5f; } /* FF turn-no, turn-no-u */
#turn-yes-shape2, #turn-yes-u-shape2 { fill: #8cd05f; } /* FF turn-yes, turn-yes-u */
.layer-points-group * {
pointer-events: none;
}
.layer-points-group.layer-points-midpoints *,
.layer-points-group.layer-points-targets * {
pointer-events: all;
}
path.shadow {
.layer-areas path.shadow,
.layer-lines path.shadow {
pointer-events: stroke;
}
@@ -47,11 +47,6 @@ g.point.selected .shadow {
stroke-opacity: 0.7;
}
/*g.vertex.active, g.vertex.active *,
g.point.active, g.point.active * {
pointer-events: none;
}
*/
g.point ellipse.stroke {
display: none;
}
@@ -108,13 +103,6 @@ g.vertex.selected .shadow {
fill-opacity: 0.7;
}
.mode-draw-area g.midpoint,
.mode-draw-line g.midpoint,
.mode-add-area g.midpoint,
.mode-add-line g.midpoint,
.mode-add-point g.midpoint {
display: none;
}
/* lines */

View File

@@ -249,7 +249,7 @@ export function modeDragNode(context) {
var behavior = behaviorDrag()
.selector('.vertex.target, g.point, g.midpoint')
.selector('.layer-points-targets .target')
.surface(d3_select('#map').node())
.origin(origin)
.on('start', start)

View File

@@ -15,17 +15,44 @@ import {
export function svgMidpoints(projection, context) {
return function drawMidpoints(selection, graph, entities, filter, extent) {
function drawTargets(selection, graph, entities, filter) {
var debugClass = 'pink';
var targets = selection.selectAll('.midpoint.target')
.filter(filter)
.data(entities, function key(d) { return d.id; });
// exit
targets.exit()
.remove();
// enter/update
targets.enter()
.append('circle')
.attr('r', 12)
.attr('class', function(d) { return 'midpoint target ' + d.id; })
.merge(targets)
.attr('transform', svgPointTransform(projection))
.classed(debugClass, context.getDebug('target'));
}
function drawMidpoints(selection, graph, entities, filter, extent) {
var layer = selection.selectAll('.layer-points .layer-points-midpoints');
var mode = context.mode();
if (mode && mode.id !== 'select') {
layer.selectAll('g.midpoint').remove();
layer.selectAll('g.midpoint')
.remove();
selection.selectAll('.layer-points .layer-points-targets .midpoint.target')
.remove();
return;
}
var poly = extent.polygon(),
midpoints = {};
var poly = extent.polygon();
var midpoints = {};
for (var i = 0; i < entities.length; i++) {
var entity = entities[i];
@@ -40,16 +67,16 @@ export function svgMidpoints(projection, context) {
var nodes = graph.childNodes(entity);
for (var j = 0; j < nodes.length - 1; j++) {
var a = nodes[j],
b = nodes[j + 1],
id = [a.id, b.id].sort().join('-');
var a = nodes[j];
var b = nodes[j + 1];
var id = [a.id, b.id].sort().join('-');
if (midpoints[id]) {
midpoints[id].parents.push(entity);
} else {
if (geoEuclideanDistance(projection(a.loc), projection(b.loc)) > 40) {
var point = geoInterp(a.loc, b.loc, 0.5),
loc = null;
var point = geoInterp(a.loc, b.loc, 0.5);
var loc = null;
if (extent.intersects(point)) {
loc = point;
@@ -107,22 +134,24 @@ export function svgMidpoints(projection, context) {
.insert('g', ':first-child')
.attr('class', 'midpoint');
enter.append('polygon')
enter
.append('polygon')
.attr('points', '-6,8 10,0 -6,-8')
.attr('class', 'shadow');
enter.append('polygon')
enter
.append('polygon')
.attr('points', '-3,4 5,0 -3,-4')
.attr('class', 'fill');
groups = groups
.merge(enter)
.attr('transform', function(d) {
var translate = svgPointTransform(projection),
a = graph.entity(d.edge[0]),
b = graph.entity(d.edge[1]),
angleVal = Math.round(geoAngle(a, b, projection) * (180 / Math.PI));
return translate(d) + ' rotate(' + angleVal + ')';
var translate = svgPointTransform(projection);
var a = graph.entity(d.edge[0]);
var b = graph.entity(d.edge[1]);
var angle = geoAngle(a, b, projection) * (180 / Math.PI);
return translate(d) + ' rotate(' + angle + ')';
})
.call(svgTagClasses().tags(
function(d) { return d.parents[0].tags; }
@@ -132,5 +161,11 @@ export function svgMidpoints(projection, context) {
groups.select('polygon.shadow');
groups.select('polygon.fill');
};
// Draw touch targets..
selection.selectAll('.layer-points .layer-points-targets')
.call(drawTargets, graph, _values(midpoints), midpointFilter);
}
return drawMidpoints;
}

View File

@@ -21,7 +21,31 @@ export function svgPoints(projection, context) {
}
return function drawPoints(selection, graph, entities, filter) {
function drawTargets(selection, graph, entities, filter) {
var debugClass = 'pink';
var targets = selection.selectAll('.point.target')
.filter(filter)
.data(entities, function key(d) { return d.id; });
// exit
targets.exit()
.remove();
// enter/update
targets.enter()
.append('rect')
.attr('x', -15)
.attr('y', -30)
.attr('width', 30)
.attr('height', 36)
.attr('class', function(d) { return 'node point target ' + d.id; })
.merge(targets)
.attr('transform', svgPointTransform(projection))
.classed(debugClass, context.getDebug('target'));
}
function drawPoints(selection, graph, entities, filter) {
var wireframe = context.surface().classed('fill-wireframe');
var zoom = ktoz(projection.scale());
@@ -95,5 +119,13 @@ export function svgPoints(projection, context) {
return '#' + picon + (isMaki ? '-11' : '');
}
});
};
// touch targets
selection.selectAll('.layer-points .layer-points-targets')
.call(drawTargets, graph, points, filter);
}
return drawPoints;
}

View File

@@ -14,7 +14,7 @@ function ktoz(k) { return Math.log(k * TAU) / Math.LN2 - 8; }
export function svgVertices(projection, context) {
var radiuses = {
// z16-, z17, z18+, tagged
// z16-, z17, z18+, w/icon
shadow: [6, 7.5, 7.5, 12],
stroke: [2.5, 3.5, 3.5, 8],
fill: [1, 1.5, 1.5, 1.5]
@@ -172,7 +172,7 @@ export function svgVertices(projection, context) {
function drawTargets(selection, graph, entities, filter) {
var debugClass = 'pink';
var targets = selection.selectAll('.target')
var targets = selection.selectAll('.vertex.target')
.filter(filter)
.data(entities, function key(d) { return d.id; });
@@ -211,14 +211,14 @@ export function svgVertices(projection, context) {
var i;
if (entity.type === 'way') {
for (i = 0; i < entity.nodes.length; i++) {
var child = context.hasEntity(entity.nodes[i]);
var child = graph.hasEntity(entity.nodes[i]);
if (child) {
addChildVertices(child);
}
}
} else if (entity.type === 'relation') {
for (i = 0; i < entity.members.length; i++) {
var member = context.hasEntity(entity.members[i].id);
var member = graph.hasEntity(entity.members[i].id);
if (member) {
addChildVertices(member);
}
@@ -230,7 +230,7 @@ export function svgVertices(projection, context) {
}
ids.forEach(function(id) {
var entity = context.hasEntity(id);
var entity = graph.hasEntity(id);
if (!entity) return;
if (entity.type === 'node') {
@@ -302,7 +302,7 @@ export function svgVertices(projection, context) {
function currentVisible(which) {
return Object.keys(which)
.map(context.hasEntity) // the current version of this entity
.map(graph.hasEntity, graph) // the current version of this entity
.filter(function (entity) { return entity && entity.intersects(extent, graph); });
}
}