From f3e7bd9034936aa09a4698bdbb32152accd58f57 Mon Sep 17 00:00:00 2001 From: Quincy Morgan Date: Mon, 7 Oct 2019 16:13:35 +0200 Subject: [PATCH] Render line and vertex visual diff on shadow instead of above everything (re: #6843) Differentiate added lines and vertices from merely changed ones --- css/20_map.css | 101 +++++++++++++++++++++------------------- modules/svg/lines.js | 50 ++++++++++---------- modules/svg/vertices.js | 30 ++++++------ 3 files changed, 90 insertions(+), 91 deletions(-) diff --git a/css/20_map.css b/css/20_map.css index a0d82d1c4..e2e9113ab 100644 --- a/css/20_map.css +++ b/css/20_map.css @@ -339,111 +339,114 @@ g.vertex.highlighted .shadow { /* highlight-edited means 'visual diff activated' 'graphedited' class means that a geometric (dark green) change has occurred. - 'tagedited' means that a tagging change has occurred. - if both are true, the 'graphedited' class supersedes 'tagedited'. + 'tagedited' means that a tagging change has occurred. + if both are true, the 'graphedited' class supersedes 'tagedited'. - /*Vertex-related visual diffs*/ -.highlight-edited g.points > circle.vertex.graphedited { - color: rgb(87, 201, 44); - stroke: #333; - stroke-width: 1; - stroke-opacity: .5; +/*Vertex-related visual diffs*/ +.highlight-edited g.points g.node.vertex.added > circle.shadow, +.highlight-edited g.points g.node.vertex.retagged > circle.shadow, +.highlight-edited g.points g.node.vertex.moved > circle.shadow { fill-opacity: 1; } -.highlight-edited g.points > circle.vertex.tagedited { - color: rgb(160, 231, 134); - stroke: #fff; - stroke-width: 2; - stroke-opacity: .5; - fill-opacity: 1; +.highlight-edited g.points g.node.vertex.added > circle.shadow { + fill: rgb(9, 157, 0); +} +.highlight-edited g.points g.node.vertex.retagged > circle.shadow, +.highlight-edited g.points g.node.vertex.moved > circle.shadow { + fill: rgb(193, 84, 17); } -/*Line-related visual diffs*/ + +/*Line-related visual diffs*/ /*Make the edited stroke line thin so that the original road color can show around it.*/ -.highlight-edited g.lines > path.line.graphedited, -.highlight-edited g.areas > path.line.graphedited { - color: rgb(87, 201, 44); - stroke-width: 3 !important; +.highlight-edited g.lines > path.line.segment-edited, +.highlight-edited g.areas > path.line.segment-edited { + color: rgb(193, 84, 17); + stroke-width: 1.5 !important; stroke-opacity: 1; } -/*Make the stroke in whole-road graph edits thin and less apparent. */ -.highlight-edited g.linegroup.line-stroke > path.way.line.stroke.graphedited { - stroke: rgb(87, 201, 44); - stroke-width: 3 !important; - stroke-opacity: 1; +/* whole line edited styles */ +.highlight-edited g.linegroup.line-shadow > path.way.line.shadow.added, +.highlight-edited g.linegroup.line-shadow > path.way.line.shadow.retagged, +.highlight-edited g.linegroup.line-shadow > path.way.line.shadow.geometry-edited { + stroke-opacity: 0.8; +} +.highlight-edited.fill-wireframe g.linegroup.line-shadow > path.way.line.shadow.added, +.highlight-edited.fill-wireframe g.linegroup.line-shadow > path.way.line.shadow.retagged, +.highlight-edited.fill-wireframe g.linegroup.line-shadow > path.way.line.shadow.geometry-edited { + stroke-width: 3; +} +.highlight-edited g.linegroup.line-shadow > path.way.line.shadow.added { + stroke: rgb(133, 255, 103); +} +.highlight-edited g.linegroup.line-shadow > path.way.line.shadow.retagged, +.highlight-edited g.linegroup.line-shadow > path.way.line.shadow.geometry-edited { + stroke: rgb(255, 126, 46); +} +.highlight-edited g.linegroup.line-shadow > path.way.line.shadow.retagged:not(.geometry-edited) { + stroke-opacity: 0.55; } -/*Make the casing around tag edits wide enough to be a bit more visible. */ -.highlight-edited g.linegroup.line-casing > path.way.line.casing.tagedited { - stroke: rgb(87, 201, 44) !important; - stroke-width: 12 !important; - stroke-opacity: 1; -} - -.low-zoom.highlight-edited g.linegroup.line-casing > path.way.line.casing.tagedited { - stroke-width: 10 !important; -} - -/* Area-related visual diffs */ +/* Area-related visual diffs */ .highlight-edited g.areagroup.area-fill > path.way.area.fill.graphedited { - stroke-width: 45px; - stroke-opacity: .5; + stroke-width: 45px; + stroke-opacity: .5; } .highlight-edited g.areagroup.area-stroke > path.way.area.stroke.graphedited { stroke: rgb(87, 201, 44) !important; - stroke-width: 5 !important; + stroke-width: 5 !important; } .highlight-edited g.areagroup.area-stroke > path.way.area.stroke.tagedited { stroke: rgb(160, 231, 134) !important; - stroke-width: 3 !important; + stroke-width: 3 !important; } .highlight-edited g.areagroup.area-shadow > path.way.area.shadow.graphedited { fill: rgb(87, 201, 44); - opacity: .2; + opacity: .2; } .highlight-edited g.areagroup.area-shadow > path.way.area.shadow.tagedited { fill: rgb(87, 201, 44); - opacity: .1; + opacity: .1; } .highlight-edited g.areagroup.area-fill > path.way.area.fill.tagedited { - stroke-width: 30; + stroke-width: 30; } .low-zoom.highlight-edited.fill-wireframe g.areagroup.area-stroke > path.way.area.stroke.tagedited { - stroke-dasharray: 7; + stroke-dasharray: 7; stroke: rgb(87, 201, 44) !important; stroke-width: 4px; } .low-zoom.highlight-edited g.areagroup.area-stroke > path.way.area.stroke.tagedited { stroke: rgb(160, 231, 134); - stroke-width: 40; - stroke-dasharray: 25 !important; + stroke-width: 40; + stroke-dasharray: 25 !important; stroke-opacity: 1 !important; } .highlight-edited.fill-wireframe g.linegroup.line-stroke > path.way.line.stroke.tagedited { stroke: rgb(160, 231, 134); stroke-width: 10 !important; - stroke-dasharray: 25 !important; + stroke-dasharray: 25 !important; stroke-opacity: 1 !important; } .highlight-edited.fill-wireframe g.areagroup.area-shadow > path.way.area.shadow.graphedited, .highlight-edited.fill-wireframe g.areagroup.area-shadow > path.way.area.shadow.tagedited { - fill-opacity: .05; + fill-opacity: .05; } /*for low zoom levels, make the wireframe view 'tag edit' dashed line finer.*/ .low-zoom.highlight-edited.fill-wireframe g.linegroup.line-stroke > path.way.line.stroke.tagedited { stroke-dasharray: 7 !important; -} +} /*In wireframe mode, restrain the stroke width to something barely wider than normal.*/ .fill-wireframe.highlight-edited g.lines > path.line.graphedited, .fill-wireframe.highlight-edited g.linegroup.line-stroke > path.way.line.stroke.tagedited, diff --git a/modules/svg/lines.js b/modules/svg/lines.js index 3daa5c574..ad1e7209d 100644 --- a/modules/svg/lines.js +++ b/modules/svg/lines.js @@ -56,11 +56,17 @@ export function svgLines(projection, context) { targets.exit() .remove(); - var graphEditClass = function(d) { + var segmentEditClass = function(d) { + var wayID = d.properties.entity.id; + // if the whole line was edited, don't draw segment changes + if (!base.entities[wayID] || + !_isEqual(graph.entities[wayID].nodes, base.entities[wayID].nodes)) { + return ''; + } return d.properties.nodes.some(function(n) { return !base.entities[n.id] || graph.entities[n.id].loc !== base.entities[n.id].loc; - }) ? ' graphedited ': ''; + }) ? ' segment-edited ': ''; }; // enter/update @@ -69,7 +75,7 @@ export function svgLines(projection, context) { .merge(targets) .attr('d', getPath) .attr('class', function(d) { - return 'way line target target-allowed ' + targetClass + d.id + graphEditClass(d); + return 'way line target target-allowed ' + targetClass + d.id + segmentEditClass(d); }); // NOPE @@ -88,7 +94,7 @@ export function svgLines(projection, context) { .merge(nopes) .attr('d', getPath) .attr('class', function(d) { - return 'way line target target-nope ' + nopeClass + d.id + graphEditClass(d); + return 'way line target target-nope ' + nopeClass + d.id + segmentEditClass(d); }); } @@ -107,27 +113,6 @@ export function svgLines(projection, context) { } - // Class for styling currently tag-edited lines, not changes to geometry - var tagEditClass = function(d) { - if (graph.entities[d.id] && base.entities[d.id] && - !_isEqual(graph.entities[d.id].tags, base.entities[d.id].tags)) { - return ' tagedited '; - } - return ''; - }; - - - // Class for styling currently geometry-edited lines - var graphEditClass = function(d) { - if (!base.entities[d.id] || - (graph.entities[d.id] && base.entities[d.id] && - graph.entities[d.id].nodes !== base.entities[d.id].nodes)) { - return ' graphedited '; - } - return ''; - }; - - function drawLineGroup(selection, klass, isSelected) { // Note: Don't add `.selected` class in draw modes var mode = context.mode(); @@ -155,7 +140,20 @@ export function svgLines(projection, context) { } var oldMPClass = oldMultiPolygonOuters[d.id] ? 'old-multipolygon ' : ''; - return prefix + ' ' + klass + ' ' + selectedClass + oldMPClass + graphEditClass(d) + tagEditClass(d) + d.id; + return prefix + ' ' + klass + ' ' + selectedClass + oldMPClass + d.id; + }) + .classed('added', function(d) { + return !base.entities[d.id]; + }) + .classed('geometry-edited', function(d) { + return graph.entities[d.id] && + base.entities[d.id] && + !_isEqual(graph.entities[d.id].nodes, base.entities[d.id].nodes); + }) + .classed('retagged', function(d) { + return graph.entities[d.id] && + base.entities[d.id] && + !_isEqual(graph.entities[d.id].tags, base.entities[d.id].tags); }) .call(svgTagClasses()) .merge(lines) diff --git a/modules/svg/vertices.js b/modules/svg/vertices.js index 1fe7b2e63..e4006da9c 100644 --- a/modules/svg/vertices.js +++ b/modules/svg/vertices.js @@ -44,6 +44,7 @@ export function svgVertices(projection, context) { var zoom = geoScaleToZoom(projection.scale()); var z = (zoom < 17 ? 0 : zoom < 18 ? 1 : 2); var activeID = context.activeID(); + var base = context.history().base(); function getIcon(d) { @@ -129,9 +130,17 @@ export function svgVertices(projection, context) { .classed('sibling', function(d) { return d.id in sets.selected; }) .classed('shared', function(d) { return graph.isShared(d); }) .classed('endpoint', function(d) { return d.isEndpoint(graph); }) + .classed('added', function(d) { + return !base.entities[d.id]; // if it doesn't exist in the base graph, it's new + }) + .classed('moved', function(d) { + return base.entities[d.id] && graph.entities[d.id].loc !== base.entities[d.id].loc; + }) + .classed('retagged', function(d) { + return base.entities[d.id] && !_isEqual(graph.entities[d.id].tags, base.entities[d.id].tags); + }) .call(updateAttributes); - // Vertices with icons get a `use`. var iconUse = groups .selectAll('.icon') @@ -224,17 +233,6 @@ export function svgVertices(projection, context) { } }); - // Class for styling currently edited vertices - var editClass = function(d) { - if (!base.entities[d.id] || // if it doesn't exist in the base graph, it's new geometry - graph.entities[d.id].loc !== base.entities[d.id].loc) { - return 'graphedited'; - } else if (!_isEqual(graph.entities[d.id].tags, base.entities[d.id].tags)) { - return 'tagedited'; - } - return ''; - }; - // Targets allow hover and vertex snapping var targets = selection.selectAll('.vertex.target-allowed') .filter(function(d) { return filter(d.properties.entity); }) @@ -251,14 +249,14 @@ export function svgVertices(projection, context) { targets.enter() .append('circle') .attr('r', function(d) { - return isEditedEnt(d, base, graph) && threeFourths(_radii[d.id]) + return isEditedEntity(d, base, graph) && threeFourths(_radii[d.id]) || _radii[d.id] || radiuses.shadow[3]; }) .merge(targets) .attr('class', function(d) { return 'node vertex target target-allowed ' - + targetClass + d.id + ' ' + editClass(d); + + targetClass + d.id; }) .attr('transform', getTransform); @@ -293,7 +291,7 @@ export function svgVertices(projection, context) { } - function isEditedEnt(entity, base, head) { + function isEditedEntity(entity, base, head) { return head.entities[entity.id] !== base.entities[entity.id] || !_isEqual(head.entities[entity.id].tags, base.entities[entity.id].tags); } @@ -376,7 +374,7 @@ export function svgVertices(projection, context) { // a vertex of some importance.. } else if (geometry === 'vertex' && (entity.hasInterestingTags() || entity.isEndpoint(graph) || entity.isConnected(graph) - || isEditedEnt(entity, base, graph))) { + || isEditedEntity(entity, base, graph))) { _currPersistent[entity.id] = entity; keep = true; }