From 30f68c4ef9d41a5a0fc7bcaffac67d76364278c0 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Mon, 26 Aug 2013 15:18:53 -0700 Subject: [PATCH] Insert areas in sorted order Fixes #1693 --- js/id/svg/areas.js | 15 +++++++++++++-- test/spec/svg/areas.js | 38 +++++++++++++++++++++++++++++++------- 2 files changed, 44 insertions(+), 9 deletions(-) diff --git a/js/id/svg/areas.js b/js/id/svg/areas.js index 1f02a05ee..8021db114 100644 --- a/js/id/svg/areas.js +++ b/js/id/svg/areas.js @@ -61,13 +61,25 @@ iD.svg.Areas = function(projection) { fill: areas }; + var bisect = d3.bisector(function(node) { + return -node.__data__.area(graph); + }).left; + + var fills = surface.selectAll('.layer-fill path.area')[0]; + + function sortedByArea(entity) { + if (this.__data__ === 'fill') { + return fills[bisect(fills, -entity.area(graph))]; + } + } + var paths = surface.selectAll('.layer-shadow, .layer-stroke, .layer-fill') .selectAll('path.area') .filter(filter) .data(function(layer) { return data[layer]; }, iD.Entity.key); paths.enter() - .append('path') + .insert('path', sortedByArea) .each(function(entity) { var layer = this.parentNode.__data__; @@ -80,7 +92,6 @@ iD.svg.Areas = function(projection) { .call(iD.svg.TagClasses()); paths - .order() .attr('d', path); paths.exit() diff --git a/test/spec/svg/areas.js b/test/spec/svg/areas.js index cebaff9bf..cf652ef11 100644 --- a/test/spec/svg/areas.js +++ b/test/spec/svg/areas.js @@ -1,7 +1,7 @@ describe("iD.svg.Areas", function () { var surface, projection = Object, - filter = d3.functor(true); + filter = d3.functor(false); beforeEach(function () { surface = d3.select(document.createElementNS('http://www.w3.org/2000/svg', 'svg')) @@ -51,7 +51,7 @@ describe("iD.svg.Areas", function () { expect(surface.selectAll('.other')[0].length).to.equal(1); }); - it("stacks smaller areas above larger ones", function () { + describe("z-indexing", function() { var graph = iD.Graph({ 'a': iD.Node({id: 'a', loc: [-0.0002, 0.0001]}), 'b': iD.Node({id: 'b', loc: [ 0.0002, 0.0001]}), @@ -63,13 +63,37 @@ describe("iD.svg.Areas", function () { 'h': iD.Node({id: 'd', loc: [-0.0004, -0.0002]}), 's': iD.Way({id: 's', tags: {building: 'yes'}, nodes: ['a', 'b', 'c', 'd', 'a']}), 'l': iD.Way({id: 'l', tags: {landuse: 'park'}, nodes: ['e', 'f', 'g', 'h', 'e']}) - }), - areas = [graph.entity('s'), graph.entity('l')]; + }); - surface.call(iD.svg.Areas(projection), graph, areas, filter); + 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')], filter); - 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'); + 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')], filter); + + 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')], filter); + surface.call(iD.svg.Areas(projection), graph, [graph.entity('l')], filter); + + 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')], filter); + surface.call(iD.svg.Areas(projection), graph, [graph.entity('s')], filter); + + 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("renders fills for multipolygon areas", function () {