From 5e64f6b95d7f576c112e3bb1c4b5fde6f75a28c7 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Mon, 15 Jul 2013 14:02:23 -0700 Subject: [PATCH] Support multiple overlay layers --- js/id/renderer/background.js | 64 ++++++++++++++++++++++++++++-------- js/id/renderer/gpx_layer.js | 3 +- js/id/renderer/tile_layer.js | 8 +---- 3 files changed, 52 insertions(+), 23 deletions(-) diff --git a/js/id/renderer/background.js b/js/id/renderer/background.js index 1e3fd9871..8385ee0a7 100644 --- a/js/id/renderer/background.js +++ b/js/id/renderer/background.js @@ -4,9 +4,7 @@ iD.Background = function(context) { .projection(context.projection), gpxLayer = iD.GpxLayer(context, dispatch) .projection(context.projection), - overlayLayer = iD.TileLayer('overlay') - .projection(context.projection), - layers = [baseLayer, gpxLayer, overlayLayer]; + overlayLayers = []; var backgroundSources = iD.data.imagery.map(function(source) { if (source.sourcetag === 'Bing') { @@ -24,10 +22,35 @@ iD.Background = function(context) { }); } - function background(supersurface) { - layers.forEach(function(layer) { - supersurface.call(layer); + function background(selection) { + var base = selection.selectAll('.background-layer') + .data([0]); + + base.enter().insert('div', '.layer-data') + .attr('class', 'layer-layer background-layer'); + + base.call(baseLayer); + + var gpx = selection.selectAll('.gpx-layer') + .data([0]); + + gpx.enter().insert('div', '.layer-data') + .attr('class', 'layer-layer gpx-layer'); + + gpx.call(gpxLayer); + + var overlays = selection.selectAll('.overlay-layer') + .data(overlayLayers, function(d) { return d.source().data.name }); + + overlays.enter().insert('div', '.layer-data') + .attr('class', 'layer-layer overlay-layer'); + + overlays.each(function(layer) { + d3.select(this).call(layer); }); + + overlays.exit() + .remove(); } background.sources = function(extent) { @@ -38,7 +61,10 @@ iD.Background = function(context) { }; background.dimensions = function(_) { - layers.forEach(function(layer) { + baseLayer.dimensions(_); + gpxLayer.dimensions(_); + + overlayLayers.forEach(function(layer) { layer.dimensions(_); }); }; @@ -82,17 +108,27 @@ iD.Background = function(context) { }; background.showsLayer = function(d) { - var overlay = overlayLayer.source(); - return d.data.name === baseLayer.source().data.name || - (overlay.data && overlay.data.name === d.data.name); + return d === baseLayer.source() || overlayLayers.some(function(l) { return l.source() === d; }); }; background.toggleOverlayLayer = function(d) { - if (overlayLayer.source() === d) { - overlayLayer.source(d3.functor('')); - } else { - overlayLayer.source(d); + var layer; + + for (var i = 0; i < overlayLayers.length; i++) { + layer = overlayLayers[i]; + if (layer.source() === d) { + overlayLayers.splice(i, 1); + dispatch.change(); + return; + } } + + layer = iD.TileLayer('overlay') + .source(d) + .projection(context.projection) + .dimensions(baseLayer.dimensions()); + + overlayLayers.push(layer); dispatch.change(); }; diff --git a/js/id/renderer/gpx_layer.js b/js/id/renderer/gpx_layer.js index 4bfc63013..0463f19d2 100644 --- a/js/id/renderer/gpx_layer.js +++ b/js/id/renderer/gpx_layer.js @@ -9,8 +9,7 @@ iD.GpxLayer = function(context, dispatch) { .data([render]); svg.enter() - .append('svg') - .attr('class', 'layer-layer gpx-layer'); + .append('svg'); svg.style('display', enable ? 'block' : 'none'); diff --git a/js/id/renderer/tile_layer.js b/js/id/renderer/tile_layer.js index e441a246b..ed0918a10 100644 --- a/js/id/renderer/tile_layer.js +++ b/js/id/renderer/tile_layer.js @@ -52,12 +52,6 @@ iD.TileLayer = function(backgroundType) { // Update tiles based on current state of `projection`. function background(selection) { - var layer = selection.selectAll('.' + backgroundType + '-layer') - .data([background]); - - layer.enter().append('div') - .attr('class', 'layer-layer ' + backgroundType + '-layer', true); - tile.scale(projection.scale() * 2 * Math.PI) .translate(projection.translate()); @@ -67,7 +61,7 @@ iD.TileLayer = function(backgroundType) { z = Math.max(Math.log(projection.scale() * 2 * Math.PI) / Math.log(2) - 8, 0); - render(layer); + render(selection); } // Derive the tiles onscreen, remove those offscreen and position them.