From 5cb5456869a07c0de38af4e16be50f907c3210cb Mon Sep 17 00:00:00 2001 From: Bryan Housel Date: Fri, 15 Dec 2017 22:50:55 -0500 Subject: [PATCH] Implement touch targets for midpoints and points --- css/20_map.css | 22 +++--------- modules/modes/drag_node.js | 2 +- modules/svg/midpoints.js | 69 ++++++++++++++++++++++++++++---------- modules/svg/points.js | 36 ++++++++++++++++++-- modules/svg/vertices.js | 12 +++---- 5 files changed, 98 insertions(+), 43 deletions(-) diff --git a/css/20_map.css b/css/20_map.css index cbff2a7f5..505b93f9b 100644 --- a/css/20_map.css +++ b/css/20_map.css @@ -7,19 +7,19 @@ use { pointer-events: none; } /* the above fill: none rule affects paths in 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 */ diff --git a/modules/modes/drag_node.js b/modules/modes/drag_node.js index 748bc97b9..81bc6c22a 100644 --- a/modules/modes/drag_node.js +++ b/modules/modes/drag_node.js @@ -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) diff --git a/modules/svg/midpoints.js b/modules/svg/midpoints.js index 27e548ca4..d6aaa0ab9 100644 --- a/modules/svg/midpoints.js +++ b/modules/svg/midpoints.js @@ -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; } diff --git a/modules/svg/points.js b/modules/svg/points.js index ab8f2361e..8f38733e8 100644 --- a/modules/svg/points.js +++ b/modules/svg/points.js @@ -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; } diff --git a/modules/svg/vertices.js b/modules/svg/vertices.js index d80302a0b..e2231b8c4 100644 --- a/modules/svg/vertices.js +++ b/modules/svg/vertices.js @@ -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); }); } }