Fix svg layer selections, fix and add tests..

This commit is contained in:
Bryan Housel
2016-09-09 14:19:13 -04:00
parent afb88f2ae6
commit 273407da3d
12 changed files with 145 additions and 59 deletions
+3 -2
View File
@@ -1,6 +1,7 @@
import * as d3 from 'd3';
import { d3geoTile } from '../lib/d3.geo.tile';
import { prefixCSSProperty, functor } from '../util/index';
import { prefixCSSProperty } from '../util/index';
import { BackgroundSource } from './background_source.js';
export function TileLayer(context) {
var tileSize = 256,
@@ -10,7 +11,7 @@ export function TileLayer(context) {
tileOrigin,
z,
transformProp = prefixCSSProperty('Transform'),
source = functor('');
source = BackgroundSource.None();
// blacklist overlay tiles around Null Island..
+10 -8
View File
@@ -24,23 +24,25 @@ export function Layers(projection, context) {
svg = selection.selectAll('.surface')
.data([0]);
svg.enter()
svg = svg.enter()
.append('svg')
.attr('class', 'surface')
.merge(svg);
svg
.append('defs');
var groups = svg.selectAll('.data-layer')
.data(layers);
groups.enter()
.append('g')
.attr('class', function(d) { return 'data-layer data-layer-' + d.id; });
groups
.each(function(d) { d3.select(this).call(d.layer); });
groups.exit()
.remove();
groups.enter()
.append('g')
.attr('class', function(d) { return 'data-layer data-layer-' + d.id; })
.merge(groups)
.each(function(d) { d3.select(this).call(d.layer); });
}
drawLayers.all = function() {
+12 -7
View File
@@ -64,13 +64,16 @@ export function Midpoints(projection, context) {
if (midpoints[d.id])
return true;
for (var i = 0; i < d.parents.length; i++)
if (filter(d.parents[i]))
for (var i = 0; i < d.parents.length; i++) {
if (filter(d.parents[i])) {
return true;
}
}
return false;
}
var layer = selection.selectAll('.layer-hit');
var groups = layer
@@ -78,6 +81,9 @@ export function Midpoints(projection, context) {
.filter(midpointFilter)
.data(_.values(midpoints), function(d) { return d.id; });
groups.exit()
.remove();
var enter = groups.enter()
.insert('g', ':first-child')
.attr('class', 'midpoint');
@@ -90,11 +96,12 @@ export function Midpoints(projection, context) {
.attr('points', '-3,4 5,0 -3,-4')
.attr('class', 'fill');
groups
groups = groups
.merge(enter)
.attr('transform', function(d) {
var translate = PointTransform(projection),
a = context.entity(d.edge[0]),
b = context.entity(d.edge[1]),
a = graph.entity(d.edge[0]),
b = graph.entity(d.edge[1]),
angleVal = Math.round(angle(a, b, projection) * (180 / Math.PI));
return translate(d) + ' rotate(' + angleVal + ')';
})
@@ -106,7 +113,5 @@ export function Midpoints(projection, context) {
groups.select('polygon.shadow');
groups.select('polygon.fill');
groups.exit()
.remove();
};
}
+1 -1
View File
@@ -60,7 +60,7 @@ export function Points(projection, context) {
groups.select('.icon')
.attr('xlink:href', function(entity) {
var preset = context.presets().match(entity, graph);
return preset.icon ? '#' + preset.icon + '-12' : '';
return (preset && preset.icon) ? '#' + preset.icon + '-12' : '';
});
};
}
+2
View File
@@ -104,8 +104,10 @@
<script src='spec/svg/areas.js'></script>
<script src='spec/svg/icon.js'></script>
<script src='spec/svg/layers.js'></script>
<script src='spec/svg/lines.js'></script>
<script src='spec/svg/midpoints.js'></script>
<script src='spec/svg/osm.js'></script>
<script src='spec/svg/points.js'></script>
<script src='spec/svg/svg.js'></script>
<script src='spec/svg/tag_classes.js'></script>
+24 -18
View File
@@ -1,13 +1,19 @@
describe('iD.svg.Areas', function () {
var surface,
projection = d3.geoProjection(function(x, y) { return [x, y]; })
var context, surface,
projection = d3.geoProjection(function(x, y) { return [x, -y]; })
.translate([0, 0])
.scale(180 / Math.PI)
.clipExtent([[0, 0], [Infinity, Infinity]]),
all = function() { return true; },
none = function() { return false; };
beforeEach(function () {
surface = d3.select(document.createElementNS('http://www.w3.org/2000/svg', 'svg'))
.call(iD.svg.Layers(projection, iD.Context(window)));
context = iD.Context(window);
d3.select(document.createElement('div'))
.attr('id', 'map')
.call(context.map());
surface = context.surface();
iD.setAreaKeys({
building: {},
landuse: {},
@@ -24,7 +30,7 @@ describe('iD.svg.Areas', function () {
iD.Way({id: 'w', tags: {building: 'yes'}, nodes: ['a', 'b', 'c', 'a']})
]);
surface.call(iD.svg.Areas(projection), graph, [graph.entity('w')], none);
surface.call(iD.svg.Areas(projection, context), graph, [graph.entity('w')], none);
expect(surface.select('path.way')).to.be.classed('way');
expect(surface.select('path.area')).to.be.classed('area');
@@ -39,7 +45,7 @@ describe('iD.svg.Areas', function () {
iD.Way({id: 'w', tags: {building: 'yes'}, nodes: ['a', 'b', 'c', 'a']})
]);
surface.call(iD.svg.Areas(projection), graph, [graph.entity('w')], none);
surface.call(iD.svg.Areas(projection, context), graph, [graph.entity('w')], none);
expect(surface.select('.area')).to.be.classed('tag-building');
expect(surface.select('.area')).to.be.classed('tag-building-yes');
@@ -55,10 +61,10 @@ describe('iD.svg.Areas', function () {
iD.Way({id: 'x', tags: {area: 'yes'}, nodes: ['a', 'b', 'd', 'a']})
]);
surface.call(iD.svg.Areas(projection), graph, [graph.entity('x')], all);
surface.call(iD.svg.Areas(projection, context), graph, [graph.entity('x')], all);
graph = graph.remove(graph.entity('x')).remove(graph.entity('d'));
surface.call(iD.svg.Areas(projection), graph, [graph.entity('w')], all);
surface.call(iD.svg.Areas(projection, context), graph, [graph.entity('w')], all);
expect(surface.select('.area').size()).to.equal(1);
});
@@ -77,30 +83,30 @@ describe('iD.svg.Areas', function () {
]);
it('stacks smaller areas above larger ones in a single render', function () {
surface.call(iD.svg.Areas(projection), graph, [graph.entity('s'), graph.entity('l')], none);
surface.call(iD.svg.Areas(projection, context), graph, [graph.entity('s'), graph.entity('l')], none);
expect(surface.select('.area:nth-child(1)')).to.be.classed('tag-landuse-park');
expect(surface.select('.area:nth-child(2)')).to.be.classed('tag-building-yes');
});
it('stacks smaller areas above larger ones in a single render (reverse)', function () {
surface.call(iD.svg.Areas(projection), graph, [graph.entity('l'), graph.entity('s')], none);
surface.call(iD.svg.Areas(projection, context), graph, [graph.entity('l'), graph.entity('s')], none);
expect(surface.select('.area:nth-child(1)')).to.be.classed('tag-landuse-park');
expect(surface.select('.area:nth-child(2)')).to.be.classed('tag-building-yes');
});
it('stacks smaller areas above larger ones in separate renders', function () {
surface.call(iD.svg.Areas(projection), graph, [graph.entity('s')], none);
surface.call(iD.svg.Areas(projection), graph, [graph.entity('l')], none);
surface.call(iD.svg.Areas(projection, context), graph, [graph.entity('s')], none);
surface.call(iD.svg.Areas(projection, context), graph, [graph.entity('l')], none);
expect(surface.select('.area:nth-child(1)')).to.be.classed('tag-landuse-park');
expect(surface.select('.area:nth-child(2)')).to.be.classed('tag-building-yes');
});
it('stacks smaller areas above larger ones in separate renders (reverse)', function () {
surface.call(iD.svg.Areas(projection), graph, [graph.entity('l')], none);
surface.call(iD.svg.Areas(projection), graph, [graph.entity('s')], none);
surface.call(iD.svg.Areas(projection, context), graph, [graph.entity('l')], none);
surface.call(iD.svg.Areas(projection, context), graph, [graph.entity('s')], none);
expect(surface.select('.area:nth-child(1)')).to.be.classed('tag-landuse-park');
expect(surface.select('.area:nth-child(2)')).to.be.classed('tag-building-yes');
@@ -116,7 +122,7 @@ describe('iD.svg.Areas', function () {
graph = iD.Graph([a, b, c, w, r]),
areas = [w, r];
surface.call(iD.svg.Areas(projection), graph, areas, none);
surface.call(iD.svg.Areas(projection, context), graph, areas, none);
expect(surface.select('.fill')).to.be.classed('relation');
});
@@ -130,7 +136,7 @@ describe('iD.svg.Areas', function () {
graph = iD.Graph([a, b, c, w, r]),
areas = [w, r];
surface.call(iD.svg.Areas(projection), graph, areas, none);
surface.call(iD.svg.Areas(projection, context), graph, areas, none);
expect(surface.selectAll('.stroke').size()).to.equal(0);
});
@@ -143,7 +149,7 @@ describe('iD.svg.Areas', function () {
r = iD.Relation({members: [{id: w.id, type: 'way'}], tags: {type: 'multipolygon'}}),
graph = iD.Graph([a, b, c, w, r]);
surface.call(iD.svg.Areas(projection), graph, [w, r], none);
surface.call(iD.svg.Areas(projection, context), graph, [w, r], none);
expect(surface.selectAll('.way.fill').size()).to.equal(0);
expect(surface.selectAll('.relation.fill').size()).to.equal(1);
@@ -158,7 +164,7 @@ describe('iD.svg.Areas', function () {
r = iD.Relation({members: [{id: w.id, type: 'way'}], tags: {type: 'multipolygon'}}),
graph = iD.Graph([a, b, c, w, r]);
surface.call(iD.svg.Areas(projection), graph, [w, r], none);
surface.call(iD.svg.Areas(projection, context), graph, [w, r], none);
expect(surface.selectAll('.stroke').size()).to.equal(0);
});
+30
View File
@@ -0,0 +1,30 @@
describe('iD.svg.Layers', function () {
var context, container,
projection = d3.geoProjection(function(x, y) { return [x, -y]; })
.translate([0, 0])
.scale(180 / Math.PI)
.clipExtent([[0, 0], [Infinity, Infinity]]);
beforeEach(function () {
context = iD.Context(window);
container = d3.select(document.createElement('div'));
});
it('creates a surface', function () {
container.call(iD.svg.Layers(projection, context));
expect(container.selectAll('svg')).to.be.classed('surface');
});
it('creates default data layers', function () {
container.call(iD.svg.Layers(projection, context));
var nodes = container.selectAll('svg .data-layer').nodes();
expect(nodes.length).to.eql(5);
expect(d3.select(nodes[0])).to.be.classed('data-layer-osm');
expect(d3.select(nodes[1])).to.be.classed('data-layer-gpx');
expect(d3.select(nodes[2])).to.be.classed('data-layer-mapillary-images');
expect(d3.select(nodes[3])).to.be.classed('data-layer-mapillary-signs');
expect(d3.select(nodes[4])).to.be.classed('data-layer-debug');
});
});
+10 -4
View File
@@ -1,15 +1,21 @@
describe('iD.svg.Lines', function () {
var surface,
projection = d3.geoProjection(function(x, y) { return [x, y]; })
var context, surface,
projection = d3.geoProjection(function(x, y) { return [x, -y]; })
.translate([0, 0])
.scale(180 / Math.PI)
.clipExtent([[0, 0], [Infinity, Infinity]]),
all = function() { return true; },
none = function() { return false; };
beforeEach(function () {
surface = d3.select(document.createElementNS('http://www.w3.org/2000/svg', 'svg'))
.call(iD.svg.Layers(projection, iD.Context(window)));
context = iD.Context(window);
d3.select(document.createElement('div'))
.attr('id', 'map')
.call(context.map());
surface = context.surface();
});
it('adds way and line classes', function () {
var a = iD.Node({loc: [0, 0]}),
b = iD.Node({loc: [1, 1]}),
+13 -8
View File
@@ -1,15 +1,20 @@
describe('iD.svg.Midpoints', function () {
var surface,
projection = Object,
filter = function() { return true; },
context;
var context, surface,
projection = d3.geoProjection(function(x, y) { return [x, -y]; })
.translate([0, 0])
.scale(180 / Math.PI)
.clipExtent([[0, 0], [Infinity, Infinity]]),
filter = function() { return true; };
beforeEach(function () {
context = iD.Context(window);
surface = d3.select(document.createElementNS('http://www.w3.org/2000/svg', 'svg'))
.call(iD.svg.Layers(projection, context));
d3.select(document.createElement('div'))
.attr('id', 'map')
.call(context.map());
surface = context.surface();
});
it('creates midpoint on segment completely within the extent', function () {
var a = iD.Node({loc: [0, 0]}),
b = iD.Node({loc: [50, 0]}),
@@ -21,7 +26,7 @@ describe('iD.svg.Midpoints', function () {
context.entity = function(id) { return graph.entity(id); };
surface.call(iD.svg.Midpoints(projection, context), graph, [line], filter, extent);
expect(surface.select('.midpoint').datum().loc).to.eql([25, 0]);
expect(surface.selectAll('.midpoint').datum().loc).to.eql([25, 0]);
});
it('doesn\'t create midpoint on segment with pixel length less than 40', function () {
@@ -61,7 +66,7 @@ describe('iD.svg.Midpoints', function () {
context.entity = function(id) { return graph.entity(id); };
surface.call(iD.svg.Midpoints(projection, context), graph, [line], filter, extent);
expect(surface.select('.midpoint').datum().loc).to.eql([100, 0]);
expect(surface.selectAll('.midpoint').datum().loc).to.eql([100, 0]);
});
it('doesn\'t create midpoint on extent edge for segment with pixel length less than 20', function () {
+19
View File
@@ -0,0 +1,19 @@
describe('iD.svg.Osm', function () {
var container;
beforeEach(function () {
container = d3.select(document.createElementNS('http://www.w3.org/2000/svg', 'svg'));
});
it('creates default osm layers', function () {
container.call(iD.svg.Osm());
var nodes = container.selectAll('.layer-osm').nodes();
expect(nodes.length).to.eql(5);
expect(d3.select(nodes[0])).to.be.classed('layer-areas');
expect(d3.select(nodes[1])).to.be.classed('layer-lines');
expect(d3.select(nodes[2])).to.be.classed('layer-hit');
expect(d3.select(nodes[3])).to.be.classed('layer-halo');
expect(d3.select(nodes[4])).to.be.classed('layer-label');
});
});
+11 -6
View File
@@ -1,14 +1,19 @@
describe('iD.svg.Points', function () {
var surface,
projection = Object,
context;
var context, surface,
projection = d3.geoProjection(function(x, y) { return [x, -y]; })
.translate([0, 0])
.scale(180 / Math.PI)
.clipExtent([[0, 0], [Infinity, Infinity]]);
beforeEach(function () {
context = iD.Context(window).presets(iD.data.presets);
surface = d3.select(document.createElementNS('http://www.w3.org/2000/svg', 'svg'))
.call(iD.svg.Layers(projection, context));
context = iD.Context(window);
d3.select(document.createElement('div'))
.attr('id', 'map')
.call(context.map());
surface = context.surface();
});
it('adds tag classes', function () {
var point = iD.Node({tags: {amenity: 'cafe'}, loc: [0, 0]}),
graph = iD.Graph([point]);
+10 -5
View File
@@ -1,14 +1,19 @@
describe('iD.svg.Vertices', function () {
var surface,
projection = Object,
context;
var context, surface,
projection = d3.geoProjection(function(x, y) { return [x, -y]; })
.translate([0, 0])
.scale(180 / Math.PI)
.clipExtent([[0, 0], [Infinity, Infinity]]);
beforeEach(function () {
context = iD.Context(window);
surface = d3.select(document.createElementNS('http://www.w3.org/2000/svg', 'svg'))
.call(iD.svg.Layers(projection, context));
d3.select(document.createElement('div'))
.attr('id', 'map')
.call(context.map());
surface = context.surface();
});
it('adds the .shared class to vertices that are members of two or more ways', function () {
var node = iD.Node({loc: [0, 0]}),
way1 = iD.Way({nodes: [node.id], tags: {highway: 'residential'}}),