Merge pull request #3917 from openstreetmap/draw-selected-last

Draw selected objects after not-selected objects
This commit is contained in:
Bryan Housel
2017-03-21 14:23:35 -04:00
committed by GitHub
6 changed files with 105 additions and 67 deletions
+3 -3
View File
@@ -55,13 +55,13 @@ path.casing.tag-bridge {
}
path.shadow.tag-bridge {
stroke-width: 22;
stroke-width: 24;
}
path.casing.tag-bridge {
stroke-width: 16;
}
.low-zoom path.shadow.tag-bridge {
stroke-width: 14;
stroke-width: 16;
}
.low-zoom path.casing.tag-bridge {
stroke-width: 10;
@@ -78,7 +78,7 @@ path.shadow.tag-highway-steps.tag-bridge,
path.shadow.tag-highway-footway.tag-bridge,
path.shadow.tag-highway-cycleway.tag-bridge,
path.shadow.tag-highway-bridleway.tag-bridge {
stroke-width: 17;
stroke-width: 18;
}
path.casing.line.tag-railway.tag-bridge,
path.casing.tag-highway-living_street.tag-bridge,
+8 -11
View File
@@ -28,20 +28,17 @@ export function behaviorHash(context) {
q = _.omit(utilStringQs(window.location.hash.substring(1)), 'comment'),
newParams = {};
if (mode && mode.id === 'browse') {
delete q.id;
} else {
var selected = context.selectedIDs().filter(function(id) {
return !context.entity(id).isNew();
});
if (selected.length) {
newParams.id = selected.join(',');
}
delete q.id;
var selected = context.selectedIDs().filter(function(id) {
return !context.entity(id).isNew();
});
if (selected.length) {
newParams.id = selected.join(',');
}
newParams.map = zoom.toFixed(2) +
'/' + center[1].toFixed(precision) +
'/' + center[0].toFixed(precision);
'/' + center[1].toFixed(precision) +
'/' + center[0].toFixed(precision);
return '#' + utilQsString(_.assign(q, newParams), true);
};
+2
View File
@@ -477,6 +477,8 @@ export function modeSelect(context, selectedIDs) {
var loc = extent.center();
context.map().centerEase(loc);
} else if (singular() && singular().type === 'way') {
context.map().pan([0,0]); // full redraw, to adjust z-sorting #2914
}
timeout = window.setTimeout(function() {
+1 -1
View File
@@ -42,7 +42,7 @@ export function rendererMap(context) {
drawLayers = svgLayers(projection, context),
drawPoints = svgPoints(projection, context),
drawVertices = svgVertices(projection, context),
drawLines = svgLines(projection),
drawLines = svgLines(projection, context),
drawAreas = svgAreas(projection, context),
drawMidpoints = svgMidpoints(projection, context),
drawLabels = svgLabels(projection, context),
+80 -41
View File
@@ -7,11 +7,11 @@ import {
svgTagClasses
} from './index';
import { osmEntity, osmSimpleMultipolygonOuterMember } from '../osm/index';
import { osmEntity, osmSimpleMultipolygonOuterMember } from '../osm';
import { utilDetect } from '../util/detect';
export function svgLines(projection) {
export function svgLines(projection, context) {
var detected = utilDetect();
var highway_stack = {
@@ -29,17 +29,65 @@ export function svgLines(projection) {
footway: 11
};
function waystack(a, b) {
var as = 0, bs = 0;
if (a.tags.highway) { as -= highway_stack[a.tags.highway]; }
if (b.tags.highway) { bs -= highway_stack[b.tags.highway]; }
return as - bs;
}
function drawLines(selection, graph, entities, filter) {
return function drawLines(selection, graph, entities, filter) {
var ways = [], pathdata = {}, onewaydata = {},
getPath = svgPath(projection, graph);
function waystack(a, b) {
var selected = context.selectedIDs(),
scoreA = selected.indexOf(a.id) !== -1 ? 20 : 0,
scoreB = selected.indexOf(b.id) !== -1 ? 20 : 0;
if (a.tags.highway) { scoreA -= highway_stack[a.tags.highway]; }
if (b.tags.highway) { scoreB -= highway_stack[b.tags.highway]; }
return scoreA - scoreB;
}
function drawLineGroup(selection, klass, isSelected) {
var lines = selection
.selectAll('path')
.filter(filter)
.data(getPathData(isSelected), osmEntity.key);
lines.exit()
.remove();
// Optimization: call simple TagClasses only on enter selection. This
// works because osmEntity.key is defined to include the entity v attribute.
lines.enter()
.append('path')
.attr('class', function(d) {
return 'way line ' + klass + ' ' + d.id + (isSelected ? ' selected' : '');
})
.call(svgTagClasses())
.merge(lines)
.sort(waystack)
.attr('d', getPath)
.call(svgTagClasses().tags(svgRelationMemberTags(graph)));
return selection;
}
function getPathData(isSelected) {
return function() {
var layer = this.parentNode.__data__;
var data = pathdata[layer] || [];
return data.filter(function(d) {
if (isSelected)
return context.selectedIDs().indexOf(d.id) !== -1;
else
return context.selectedIDs().indexOf(d.id) === -1;
});
};
}
var getPath = svgPath(projection, graph),
ways = [],
pathdata = {},
onewaydata = {};
for (var i = 0; i < entities.length; i++) {
var entity = entities[i],
@@ -52,7 +100,6 @@ export function svgLines(projection) {
}
ways = ways.filter(getPath);
pathdata = _.groupBy(ways, function(way) { return way.layer(); });
_.forOwn(pathdata, function(v, k) {
@@ -63,6 +110,7 @@ export function svgLines(projection) {
.valueOf();
});
var layer = selection.selectAll('.layer-lines');
var layergroup = layer
@@ -74,38 +122,27 @@ export function svgLines(projection) {
.attr('class', function(d) { return 'layergroup layer' + String(d); })
.merge(layergroup);
var linegroup = layergroup
layergroup
.selectAll('g.linegroup')
.data(['shadow', 'casing', 'stroke']);
linegroup = linegroup.enter()
.data(['shadow', 'casing', 'stroke', 'shadow-highlighted', 'casing-highlighted', 'stroke-highlighted'])
.enter()
.append('g')
.attr('class', function(d) { return 'linegroup line-' + d; })
.merge(linegroup);
.attr('class', function(d) { return 'linegroup line-' + d; });
var lines = linegroup
.selectAll('path')
.filter(filter)
.data(
function() { return pathdata[this.parentNode.__data__] || []; },
osmEntity.key
);
layergroup.selectAll('g.line-shadow')
.call(drawLineGroup, 'shadow', false);
layergroup.selectAll('g.line-casing')
.call(drawLineGroup, 'casing', false);
layergroup.selectAll('g.line-stroke')
.call(drawLineGroup, 'stroke', false);
lines.exit()
.remove();
// Optimization: call simple TagClasses only on enter selection. This
// works because osmEntity.key is defined to include the entity v attribute.
lines.enter()
.append('path')
.attr('class', function(d) { return 'way line ' + this.parentNode.__data__ + ' ' + d.id; })
.call(svgTagClasses())
.merge(lines)
.sort(waystack)
.attr('d', getPath)
.call(svgTagClasses().tags(svgRelationMemberTags(graph)));
layergroup.selectAll('g.line-shadow-highlighted')
.call(drawLineGroup, 'shadow', true);
layergroup.selectAll('g.line-casing-highlighted')
.call(drawLineGroup, 'casing', true);
layergroup.selectAll('g.line-stroke-highlighted')
.call(drawLineGroup, 'stroke', true);
var onewaygroup = layergroup
@@ -117,7 +154,6 @@ export function svgLines(projection) {
.attr('class', 'onewaygroup')
.merge(onewaygroup);
var oneways = onewaygroup
.selectAll('path')
.filter(filter)
@@ -139,5 +175,8 @@ export function svgLines(projection) {
if (detected.ie) {
oneways.each(function() { this.parentNode.insertBefore(this, this); });
}
};
}
return drawLines;
}
+11 -11
View File
@@ -22,7 +22,7 @@ describe('iD.svgLines', function () {
line = iD.Way({nodes: [a.id, b.id]}),
graph = iD.Graph([a, b, line]);
surface.call(iD.svgLines(projection), graph, [line], all);
surface.call(iD.svgLines(projection, context), graph, [line], all);
expect(surface.select('path.way')).to.be.classed('way');
expect(surface.select('path.line')).to.be.classed('line');
@@ -34,7 +34,7 @@ describe('iD.svgLines', function () {
line = iD.Way({nodes: [a.id, b.id], tags: {highway: 'residential'}}),
graph = iD.Graph([a, b, line]);
surface.call(iD.svgLines(projection), graph, [line], all);
surface.call(iD.svgLines(projection, context), graph, [line], all);
expect(surface.select('.line')).to.be.classed('tag-highway');
expect(surface.select('.line')).to.be.classed('tag-highway-residential');
@@ -47,7 +47,7 @@ describe('iD.svgLines', function () {
relation = iD.Relation({members: [{id: line.id}], tags: {type: 'multipolygon', natural: 'wood'}}),
graph = iD.Graph([a, b, line, relation]);
surface.call(iD.svgLines(projection), graph, [line], all);
surface.call(iD.svgLines(projection, context), graph, [line], all);
expect(surface.select('.stroke')).to.be.classed('tag-natural-wood');
});
@@ -60,7 +60,7 @@ describe('iD.svgLines', function () {
r = iD.Relation({members: [{id: w.id}], tags: {type: 'multipolygon'}}),
graph = iD.Graph([a, b, c, w, r]);
surface.call(iD.svgLines(projection), graph, [w], all);
surface.call(iD.svgLines(projection, context), graph, [w], all);
expect(surface.select('.stroke')).to.be.classed('tag-natural-wood');
});
@@ -74,7 +74,7 @@ describe('iD.svgLines', function () {
r = iD.Relation({members: [{id: o.id, role: 'outer'}, {id: i.id, role: 'inner'}], tags: {type: 'multipolygon'}}),
graph = iD.Graph([a, b, c, o, i, r]);
surface.call(iD.svgLines(projection), graph, [i], all);
surface.call(iD.svgLines(projection, context), graph, [i], all);
expect(surface.select('.stroke')).to.be.classed('tag-natural-wood');
});
@@ -90,7 +90,7 @@ describe('iD.svgLines', function () {
]);
it('stacks higher lines above lower ones in a single render', function () {
surface.call(iD.svgLines(projection), graph, [graph.entity('lo'), graph.entity('hi')], none);
surface.call(iD.svgLines(projection, context), graph, [graph.entity('lo'), graph.entity('hi')], none);
var selection = surface.selectAll('g.line-stroke > path.line');
expect(selection.nodes()[0].__data__.id).to.eql('lo');
@@ -98,7 +98,7 @@ describe('iD.svgLines', function () {
});
it('stacks higher lines above lower ones in a single render (reverse)', function () {
surface.call(iD.svgLines(projection), graph, [graph.entity('hi'), graph.entity('lo')], none);
surface.call(iD.svgLines(projection, context), graph, [graph.entity('hi'), graph.entity('lo')], none);
var selection = surface.selectAll('g.line-stroke > path.line');
expect(selection.nodes()[0].__data__.id).to.eql('lo');
@@ -106,8 +106,8 @@ describe('iD.svgLines', function () {
});
it('stacks higher lines above lower ones in separate renders', function () {
surface.call(iD.svgLines(projection), graph, [graph.entity('lo')], none);
surface.call(iD.svgLines(projection), graph, [graph.entity('hi')], none);
surface.call(iD.svgLines(projection, context), graph, [graph.entity('lo')], none);
surface.call(iD.svgLines(projection, context), graph, [graph.entity('hi')], none);
var selection = surface.selectAll('g.line-stroke > path.line');
expect(selection.nodes()[0].__data__.id).to.eql('lo');
@@ -115,8 +115,8 @@ describe('iD.svgLines', function () {
});
it('stacks higher lines above lower in separate renders (reverse)', function () {
surface.call(iD.svgLines(projection), graph, [graph.entity('hi')], none);
surface.call(iD.svgLines(projection), graph, [graph.entity('lo')], none);
surface.call(iD.svgLines(projection, context), graph, [graph.entity('hi')], none);
surface.call(iD.svgLines(projection, context), graph, [graph.entity('lo')], none);
var selection = surface.selectAll('g.line-stroke > path.line');
expect(selection.nodes()[0].__data__.id).to.eql('lo');