Resample oneway paths to produce markers.

This uses a technique created by @mbostock in http://bl.ocks.org/mbostock/4965670
Need to confirm that this is faster. It is definitely cleaner.
This commit is contained in:
Tom MacWright
2013-03-06 21:08:50 -05:00
parent 15c37b86b9
commit 27c0edb2c1
4 changed files with 35 additions and 63 deletions

View File

@@ -695,17 +695,14 @@ text {
opacity: 1;
}
.oneway .textpath {
pointer-events: none;
font-size: 7px;
baseline-shift: 2px;
opacity: .7;
}
.oneway .textpath.tag-waterway {
fill: #002F35;
}
marker#oneway-marker path {
fill:#000;
}
text.tag-oneway {
fill:#91CFFF;
stroke:#2C6B9B;

View File

@@ -5,6 +5,21 @@ iD.svg = {
};
},
resample: function resample(dx) {
return function() {
var line = d3.svg.line();
var path = this,
l = path.getTotalLength(),
t = [0], i = 0, dt = dx / l;
while ((i += dt) < 1) t.push(i);
t.push(1);
return line(t.map(function(t) {
var p = path.getPointAtLength(t * l);
return [p.x, p.y];
}));
};
},
PointTransform: function(projection) {
return function(entity) {
// http://jsperf.com/short-array-join

View File

@@ -1,8 +1,5 @@
iD.svg.Lines = function(projection) {
var arrowtext = '►\u3000\u3000\u3000',
alength;
var highway_stack = {
motorway: 0,
motorway_link: 1,
@@ -92,16 +89,6 @@ iD.svg.Lines = function(projection) {
return paths;
}
if (!alength) {
var container = surface.append('g')
.attr('class', 'oneway'),
arrow = container.append('text')
.attr('class', 'textpath')
.text(arrowtext);
alength = arrow.node().getComputedTextLength();
container.remove();
}
var lines = [];
for (var i = 0; i < entities.length; i++) {
@@ -127,47 +114,9 @@ iD.svg.Lines = function(projection) {
casings = drawPaths(casing, lines, filter, 'casing', lineString),
strokes = drawPaths(stroke, lines, filter, 'stroke', lineString);
// Determine the lengths of oneway paths
var lengths = {},
oneways = strokes.filter(function(d) { return d.isOneWay(); }).each(function(d) {
lengths[d.id] = Math.floor(this.getTotalLength() / alength);
}).data();
var uses = defs.selectAll('path')
.filter(filter)
.data(oneways, iD.Entity.key);
uses.enter()
.append('path');
uses
.attr('id', function(d) { return 'shadow-' + d.id; })
.attr('d', lineString);
uses.exit()
.remove();
var labels = text.selectAll('text')
.filter(filter)
.data(oneways, iD.Entity.key);
var tagClasses = iD.svg.TagClasses();
var tp = labels.enter()
.append('text')
.attr({ 'class': 'oneway', dy: 4 })
.append('textPath')
.attr('class', 'textpath')
.call(tagClasses);
labels.exit().remove();
text.selectAll('.textpath')
.filter(filter)
.attr('xlink:href', function(d) { return '#shadow-' + d.id; })
.text(function(d) {
// adding longer text than necessary, since overflow is hidden
return (new Array(Math.floor(lengths[d.id] * 1.1))).join(arrowtext);
});
strokes
.filter(function(d) { return d.isOneWay(); })
.attr('marker-mid', 'url(#oneway-marker)')
.attr('d', iD.svg.resample(60));
};
};

View File

@@ -1,6 +1,17 @@
iD.svg.Surface = function() {
return function drawSurface(selection) {
selection.append('defs');
var defs = selection.append('defs');
defs.append('marker')
.attr({
id: 'oneway-marker',
viewBox: '0 0 10 10',
refY: 2.5,
markerWidth: 2,
markerHeight: 2,
orient: 'auto'
})
.append('path')
.attr('d', 'M 0 0 L 5 2.5 L 0 5 z');
var layers = selection.selectAll('.layer')
.data(['fill', 'shadow', 'casing', 'stroke', 'text', 'hit', 'halo', 'label']);