diff --git a/css/20_map.css b/css/20_map.css index a4206260e..a36d9237b 100644 --- a/css/20_map.css +++ b/css/20_map.css @@ -33,7 +33,8 @@ /* `.target` objects are interactive */ /* They can be picked up, clicked, hovered, or things can connect to them */ -.node.target { +.node.target, +.turn .target { pointer-events: fill; fill-opacity: 0.8; fill: currentColor; @@ -50,6 +51,7 @@ stroke-linejoin: round; } + /* `.target-nope` objects are explicitly forbidden to join to */ .surface:not(.nope-disabled) .node.target.target-nope, .surface:not(.nope-disabled) .way.target.target-nope { @@ -269,15 +271,9 @@ g.vertex.highlighted .shadow { } /* Turn Restrictions */ -g.turn rect, -g.turn circle { +.points-group.turns g.turn rect, +.points-group.turns g.turn circle { fill: none; - pointer-events: all; -} - -.form-field-restrictions .vertex { - cursor: auto !important; - pointer-events: none; } /* Turn restriction paths and vertices */ diff --git a/modules/svg/touch.js b/modules/svg/touch.js index 33290f744..96bb1c871 100644 --- a/modules/svg/touch.js +++ b/modules/svg/touch.js @@ -2,7 +2,7 @@ export function svgTouch() { function drawTouch(selection) { selection.selectAll('.layer-touch') - .data(['areas', 'lines', 'points', 'notes']) + .data(['areas', 'lines', 'points', 'turns', 'notes']) .enter() .append('g') .attr('class', function(d) { return 'layer-touch ' + d; }); diff --git a/modules/svg/turns.js b/modules/svg/turns.js index c5aefc7bc..a0bc7e173 100644 --- a/modules/svg/turns.js +++ b/modules/svg/turns.js @@ -1,45 +1,69 @@ import { geoAngle, geoPathLength } from '../geo'; -export function svgTurns(projection) { +export function svgTurns(projection, context) { - return function drawTurns(selection, graph, turns) { + function icon(turn) { + var u = turn.u ? '-u' : ''; + if (turn.no) return '#iD-turn-no' + u; + if (turn.only) return '#iD-turn-only' + u; + return '#iD-turn-yes' + u; + } - function icon(turn) { - var u = turn.u ? '-u' : ''; - if (turn.no) return '#iD-turn-no' + u; - if (turn.only) return '#iD-turn-only' + u; - return '#iD-turn-yes' + u; + function drawTurns(selection, graph, turns) { + + function turnTransform(d) { + var pxRadius = 50; + var toWay = graph.entity(d.to.way); + var toPoints = graph.childNodes(toWay) + .map(function (n) { return n.loc; }) + .map(projection); + var toLength = geoPathLength(toPoints); + var mid = toLength / 2; // midpoint of destination way + + var toNode = graph.entity(d.to.node); + var toVertex = graph.entity(d.to.vertex); + var a = geoAngle(toVertex, toNode, projection); + var o = projection(toVertex.loc); + var r = d.u ? 0 // u-turn: no radius + : !toWay.__via ? pxRadius // leaf way: put marker at pxRadius + : Math.min(mid, pxRadius); // via way: prefer pxRadius, fallback to mid for very short ways + + return 'translate(' + (r * Math.cos(a) + o[0]) + ',' + (r * Math.sin(a) + o[1]) + ') ' + + 'rotate(' + a * 180 / Math.PI + ')'; } - var drawLayer = selection.selectAll('.layer-osm.points .points-group.turns'); + var drawLayer = selection.selectAll('.layer-osm.points .points-group.turns'); + var touchLayer = selection.selectAll('.layer-touch.turns'); + + // Draw turns.. var groups = drawLayer.selectAll('g.turn') .data(turns, function(d) { return d.key; }); + // exit groups.exit() .remove(); - - var enter = groups.enter() + // enter + var groupsEnter = groups.enter() .append('g') .attr('class', function(d) { return 'turn ' + d.key; }); - var nEnter = enter + var turnsEnter = groupsEnter .filter(function(d) { return !d.u; }); - nEnter.append('rect') + turnsEnter.append('rect') .attr('transform', 'translate(-22, -12)') .attr('width', '44') .attr('height', '24'); - nEnter.append('use') + turnsEnter.append('use') .attr('transform', 'translate(-22, -12)') .attr('width', '44') .attr('height', '24'); - - var uEnter = enter + var uEnter = groupsEnter .filter(function(d) { return d.u; }); uEnter.append('circle') @@ -50,41 +74,60 @@ export function svgTurns(projection) { .attr('width', '32') .attr('height', '32'); - + // update groups = groups - .merge(enter); - - groups - .attr('opacity', function(d) { - return d.direct === false ? '0.7' : null; - }) - .attr('transform', function(d) { - var pxRadius = 50; - var toWay = graph.entity(d.to.way); - var toPoints = graph.childNodes(toWay) - .map(function (n) { return n.loc; }) - .map(projection); - var toLength = geoPathLength(toPoints); - var mid = toLength / 2; // midpoint of destination way - - var toNode = graph.entity(d.to.node); - var toVertex = graph.entity(d.to.vertex); - var a = geoAngle(toVertex, toNode, projection); - var o = projection(toVertex.loc); - var r = d.u ? 0 // u-turn: no radius - : !toWay.__via ? pxRadius // leaf way: put marker at pxRadius - : Math.min(mid, pxRadius); // via way: prefer pxRadius, fallback to mid for very short ways - - return 'translate(' + (r * Math.cos(a) + o[0]) + ',' + (r * Math.sin(a) + o[1]) + ') ' + - 'rotate(' + a * 180 / Math.PI + ')'; - }); + .merge(groupsEnter) + .attr('opacity', function(d) { return d.direct === false ? '0.7' : null; }) + .attr('transform', turnTransform); groups.select('use') .attr('xlink:href', icon); - groups.select('rect'); - groups.select('circle'); + groups.select('rect'); // propagate bound data + groups.select('circle'); // propagate bound data + + + // Draw touch targets.. + var fillClass = context.getDebug('target') ? 'pink ' : 'nocolor '; + groups = touchLayer.selectAll('g.turn') + .data(turns, function(d) { return d.key; }); + + // exit + groups.exit() + .remove(); + + // enter + groupsEnter = groups.enter() + .append('g') + .attr('class', function(d) { return 'turn ' + d.key; }); + + turnsEnter = groupsEnter + .filter(function(d) { return !d.u; }); + + turnsEnter.append('rect') + .attr('class', 'target ' + fillClass) + .attr('transform', 'translate(-22, -12)') + .attr('width', '44') + .attr('height', '24'); + + uEnter = groupsEnter + .filter(function(d) { return d.u; }); + + uEnter.append('circle') + .attr('class', 'target ' + fillClass) + .attr('r', '16'); + + // update + groups = groups + .merge(groupsEnter) + .attr('transform', turnTransform); + + groups.select('rect'); // propagate bound data + groups.select('circle'); // propagate bound data + return this; - }; + } + + return drawTurns; }