diff --git a/css/20_map.css b/css/20_map.css index 34061453f..4ab4dae1c 100644 --- a/css/20_map.css +++ b/css/20_map.css @@ -11,9 +11,10 @@ use { pointer-events: none; } #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 */ -g.point .shadow, -g.vertex .shadow, -g.midpoint .shadow { +.layer-points-group * { + pointer-events: none; +} +.layer-points-group.layer-points-targets * { pointer-events: all; } @@ -45,11 +46,11 @@ g.point.selected .shadow { stroke-opacity: 0.7; } -g.vertex.active, g.vertex.active *, +/*g.vertex.active, g.vertex.active *, g.point.active, g.point.active * { pointer-events: none; } - +*/ g.point ellipse.stroke { display: none; } @@ -89,10 +90,10 @@ g.midpoint .shadow { fill-opacity: 0; } -/*debug*/ -.vertex.target { - fill: #f00; - fill-opacity: 0.5; +.target { + color: rgba(0,0,0,0); + fill-opacity: 0.8; + fill: currentColor; } /*g.vertex.vertex-hover { @@ -120,7 +121,7 @@ g.midpoint .shadow { */ g.vertex.related:not(.selected) .shadow, -/*g.vertex.hover:not(.selected) .shadow,*/ +g.vertex.hover:not(.selected) .shadow, g.midpoint.related:not(.selected) .shadow, g.midpoint.hover:not(.selected) .shadow { fill-opacity: 0.5; diff --git a/modules/behavior/hover.js b/modules/behavior/hover.js index f7ea0b4eb..b9c4bfa5c 100644 --- a/modules/behavior/hover.js +++ b/modules/behavior/hover.js @@ -20,16 +20,16 @@ import { utilRebind } from '../util/rebind'; have the .hover class. */ export function behaviorHover(context) { - var dispatch = d3_dispatch('hover'), - _selection = d3_select(null), - newId = null, - buttonDown, - altDisables, - target; + var dispatch = d3_dispatch('hover'); + var _selection = d3_select(null); + var _newId = null; + var _buttonDown; + var _altDisables; + var _target; function keydown() { - if (altDisables && d3_event.keyCode === d3_keybinding.modifierCodes.alt) { + if (_altDisables && d3_event.keyCode === d3_keybinding.modifierCodes.alt) { _selection.selectAll('.hover') .classed('hover-suppressed', true) .classed('hover', false); @@ -43,7 +43,7 @@ export function behaviorHover(context) { function keyup() { - if (altDisables && d3_event.keyCode === d3_keybinding.modifierCodes.alt) { + if (_altDisables && d3_event.keyCode === d3_keybinding.modifierCodes.alt) { _selection.selectAll('.hover-suppressed') .classed('hover-suppressed', false) .classed('hover', true); @@ -51,14 +51,14 @@ export function behaviorHover(context) { _selection .classed('hover-disabled', false); - dispatch.call('hover', this, target ? target.id : null); + dispatch.call('hover', this, _target ? _target.id : null); } } var hover = function(selection) { _selection = selection; - newId = null; + _newId = null; _selection .on('mouseover.hover', mouseover) @@ -71,65 +71,65 @@ export function behaviorHover(context) { function mouseover() { - if (buttonDown) return; - var target = d3_event.target; - enter(target ? target.__data__ : null); + if (_buttonDown) return; + var _target = d3_event.target; + enter(_target ? _target.__data__ : null); } function mouseout() { - if (buttonDown) return; - var target = d3_event.relatedTarget; - enter(target ? target.__data__ : null); + if (_buttonDown) return; + var _target = d3_event.relatedTarget; + enter(_target ? _target.__data__ : null); } function mousedown() { - buttonDown = true; + _buttonDown = true; d3_select(window) .on('mouseup.hover', mouseup, true); } function mouseup() { - buttonDown = false; + _buttonDown = false; d3_select(window) .on('mouseup.hover', null, true); } function enter(d) { - if (d === target) return; - target = d; + if (d === _target) return; + _target = d; _selection.selectAll('.hover') .classed('hover', false); _selection.selectAll('.hover-suppressed') .classed('hover-suppressed', false); - if (target instanceof osmEntity && target.id !== newId) { + if (_target instanceof osmEntity && _target.id !== _newId) { // If drawing a way, don't hover on a node that was just placed. #3974 var mode = context.mode() && context.mode().id; - if ((mode === 'draw-line' || mode === 'draw-area') && !newId && target.type === 'node') { - newId = target.id; + if ((mode === 'draw-line' || mode === 'draw-area') && !_newId && _target.type === 'node') { + _newId = _target.id; return; } - var selector = '.' + target.id; + var selector = '.' + _target.id; - if (target.type === 'relation') { - target.members.forEach(function(member) { + if (_target.type === 'relation') { + _target.members.forEach(function(member) { selector += ', .' + member.id; }); } - var suppressed = altDisables && d3_event && d3_event.altKey; + var suppressed = _altDisables && d3_event && d3_event.altKey; _selection.selectAll(selector) .classed(suppressed ? 'hover-suppressed' : 'hover', true); - dispatch.call('hover', this, !suppressed && target.id); + dispatch.call('hover', this, !suppressed && _target.id); } else { dispatch.call('hover', this, null); @@ -147,7 +147,6 @@ export function behaviorHover(context) { selection .classed('hover-disabled', false); - selection .on('mouseover.hover', null) .on('mouseout.hover', null) @@ -160,8 +159,8 @@ export function behaviorHover(context) { hover.altDisables = function(_) { - if (!arguments.length) return altDisables; - altDisables = _; + if (!arguments.length) return _altDisables; + _altDisables = _; return hover; }; diff --git a/modules/core/context.js b/modules/core/context.js index ce0cf5787..95146e248 100644 --- a/modules/core/context.js +++ b/modules/core/context.js @@ -310,11 +310,12 @@ export function coreContext() { /* Debug */ var debugFlags = { - tile: false, - collision: false, - imagery: false, - imperial: false, - driveLeft: false + tile: false, // tile boundaries + collision: false, // label collision bounding boxes + imagery: false, // imagery bounding polygons + imperial: false, // imperial (not metric) bounding polygons + driveLeft: false, // driveLeft bounding polygons + target: false // touch targets }; context.debugFlags = function() { return debugFlags; diff --git a/modules/svg/debug.js b/modules/svg/debug.js index 9e1c82cb0..8ab5617d4 100644 --- a/modules/svg/debug.js +++ b/modules/svg/debug.js @@ -21,12 +21,13 @@ export function svgDebug(projection, context) { } function drawDebug(selection) { - var showsTile = context.getDebug('tile'), - showsCollision = context.getDebug('collision'), - showsImagery = context.getDebug('imagery'), - showsImperial = context.getDebug('imperial'), - showsDriveLeft = context.getDebug('driveLeft'), - path = d3_geoPath(projection); + var showsTile = context.getDebug('tile'); + var showsCollision = context.getDebug('collision'); + var showsImagery = context.getDebug('imagery'); + var showsImperial = context.getDebug('imperial'); + var showsDriveLeft = context.getDebug('driveLeft'); + var showsTouchTargets = context.getDebug('target'); + var path = d3_geoPath(projection); var debugData = []; @@ -45,6 +46,9 @@ export function svgDebug(projection, context) { if (showsDriveLeft) { debugData.push({ class: 'green', label: 'driveLeft' }); } + if (showsTouchTargets) { + debugData.push({ class: 'pink', label: 'touchTargets' }); + } var legend = d3_select('#content') @@ -84,14 +88,14 @@ export function svgDebug(projection, context) { .merge(layer); - var extent = context.map().extent(), - dataImagery = data.imagery || [], - availableImagery = showsImagery && multipolygons(dataImagery.filter(function(source) { - if (!source.polygon) return false; - return source.polygon.some(function(polygon) { - return geoPolygonIntersectsPolygon(polygon, extent, true); - }); - })); + var extent = context.map().extent(); + var dataImagery = data.imagery || []; + var availableImagery = showsImagery && multipolygons(dataImagery.filter(function(source) { + if (!source.polygon) return false; + return source.polygon.some(function(polygon) { + return geoPolygonIntersectsPolygon(polygon, extent, true); + }); + })); var imagery = layer.selectAll('path.debug-imagery') .data(showsImagery ? availableImagery : []); @@ -142,7 +146,8 @@ export function svgDebug(projection, context) { context.getDebug('collision') || context.getDebug('imagery') || context.getDebug('imperial') || - context.getDebug('driveLeft'); + context.getDebug('driveLeft') || + context.getDebug('target'); } else { return this; } diff --git a/modules/svg/vertices.js b/modules/svg/vertices.js index 707ed2414..85ab774ca 100644 --- a/modules/svg/vertices.js +++ b/modules/svg/vertices.js @@ -1,3 +1,4 @@ +import _assign from 'lodash-es/assign'; import _clone from 'lodash-es/clone'; import _values from 'lodash-es/values'; @@ -20,10 +21,11 @@ export function svgVertices(projection, context) { fill: [1, 1.5, 1.5, 1.5] }; - var _hover; + var _currHover; + var _currHoverSiblings = {}; - function draw(selection, vertices, klass, graph, siblings, filter) { + function draw(selection, graph, vertices, klass, siblings, filter) { siblings = siblings || {}; var icons = {}; var directions = {}; @@ -169,43 +171,9 @@ export function svgVertices(projection, context) { } - function drawVertices(selection, graph, entities, filter, extent) { - var wireframe = context.surface().classed('fill-wireframe'); - var zoom = ktoz(projection.scale()); - var siblings = getSiblingAndChildVertices(context.selectedIDs(), graph, extent, wireframe, zoom); - - // always render selected and sibling vertices.. - var vertices = _clone(siblings); - var filterWithSiblings = function(d) { return d.id in siblings || filter(d); }; - - // also render important vertices from the `entities` list.. - for (var i = 0; i < entities.length; i++) { - var entity = entities[i]; - var geometry = entity.geometry(graph); - - if ((geometry === 'point') && renderAsVertex(entity, graph, wireframe, zoom)) { - vertices[entity.id] = entity; - - } else if ((geometry === 'vertex') && - (entity.hasInterestingTags() || entity.isEndpoint(graph) || entity.isConnected(graph)) ) { - vertices[entity.id] = entity; - } - } - - selection.selectAll('.layer-points .layer-points-vertices') - .call(draw, _values(vertices), 'vertex-persistent', graph, siblings, filterWithSiblings); - - drawTargets(selection, graph, _values(vertices), filter, extent); - - } - - - function drawTargets(selection, graph, entities, filter, extent) { -// todo coming soon -return; - var layer = selection.selectAll('.layer-points .layer-points-targets'); - - var targets = layer.selectAll('g.vertex.target') + function drawTargets(selection, graph, entities, filter) { + var debugClass = 'pink'; + var targets = selection.selectAll('.target') .data(entities, osmEntity.key); // exit @@ -218,7 +186,8 @@ return; .attr('r', radiuses.shadow[3]) // just use the biggest one for now .attr('class', function(d) { return 'node vertex target ' + d.id; }) .merge(targets) - .attr('transform', svgPointTransform(projection)); + .attr('transform', svgPointTransform(projection)) + .classed(debugClass, context.getDebug('target')); } @@ -280,16 +249,66 @@ return; } + function drawVertices(selection, graph, entities, filter, extent) { + var wireframe = context.surface().classed('fill-wireframe'); + var zoom = ktoz(projection.scale()); + + var selected = getSiblingAndChildVertices(context.selectedIDs(), graph, extent, wireframe, zoom); + + // interesting vertices from the `entities` list.. + var interesting = {}; + for (var i = 0; i < entities.length; i++) { + var entity = entities[i]; + var geometry = entity.geometry(graph); + + if ((geometry === 'point') && renderAsVertex(entity, graph, wireframe, zoom)) { + interesting[entity.id] = entity; + + } else if ((geometry === 'vertex') && + (entity.hasInterestingTags() || entity.isEndpoint(graph) || entity.isConnected(graph)) ) { + interesting[entity.id] = entity; + } + } + + // 3 sets of vertices to consider + // - selected + siblings + // - hovered + siblings + // - interesting entities passed in + var all = _assign(selected, interesting, _currHoverSiblings); + + var filterWithSiblings = function(d) { + return d.id in selected || d.id in _currHoverSiblings || filter(d); + }; + selection.selectAll('.layer-points .layer-points-vertices') + .call(draw, graph, _values(all), 'vertex-persistent', {}, filterWithSiblings); + + + // draw touch targets for the hovered items only + var filterWithHover = function(d) { + return d.id in _currHoverSiblings || filter(d); + }; + selection.selectAll('.layer-points .layer-points-targets') + .call(drawTargets, graph, _values(_currHoverSiblings), filterWithHover); + } + + drawVertices.drawHover = function(selection, graph, target, extent) { - if (target === _hover) return; - _hover = target; + if (target === _currHover) return; var wireframe = context.surface().classed('fill-wireframe'); var zoom = ktoz(projection.scale()); - var hovered = _hover ? getSiblingAndChildVertices([_hover.id], graph, extent, wireframe, zoom) : {}; - var filter = function() { return true; }; + var prevHoverSiblings = _currHoverSiblings || {}; + var filter = function(d) { return d.id in prevHoverSiblings; }; - drawTargets(selection, graph, _values(hovered), filter, extent); + _currHover = target; + + if (_currHover) { + _currHoverSiblings = getSiblingAndChildVertices([_currHover.id], graph, extent, wireframe, zoom); + } else { + _currHoverSiblings = {}; + } + + drawVertices(selection, graph, _values(prevHoverSiblings), filter, extent); }; return drawVertices;