From 27c0edb2c10409ee73681d18c5b59c48ca003117 Mon Sep 17 00:00:00 2001 From: Tom MacWright Date: Wed, 6 Mar 2013 21:08:50 -0500 Subject: [PATCH] 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. --- css/map.css | 11 +++------ js/id/svg.js | 15 +++++++++++ js/id/svg/lines.js | 59 +++----------------------------------------- js/id/svg/surface.js | 13 +++++++++- 4 files changed, 35 insertions(+), 63 deletions(-) diff --git a/css/map.css b/css/map.css index 756cd11fa..e4dc2fcb0 100644 --- a/css/map.css +++ b/css/map.css @@ -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; diff --git a/js/id/svg.js b/js/id/svg.js index 12ffc5c31..c48b9e50d 100644 --- a/js/id/svg.js +++ b/js/id/svg.js @@ -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 diff --git a/js/id/svg/lines.js b/js/id/svg/lines.js index 0e91f2ce2..6ba4fb4f1 100644 --- a/js/id/svg/lines.js +++ b/js/id/svg/lines.js @@ -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)); }; }; diff --git a/js/id/svg/surface.js b/js/id/svg/surface.js index a11f8fbae..469b9e0d5 100644 --- a/js/id/svg/surface.js +++ b/js/id/svg/surface.js @@ -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']);