Refactoring and fixing layers

* Fixed opacity control
* Reorganize layer switcher
* Add GPX item to menu
* Allow user to cinch to GPX extent

Needs:

* Moderate refactoring
* Possibly a specific 'layerchange event'
* Dropping GPX on the map should be a behavior, probably, instead of in
  the layer
* Layers, if we want them, should be named rather than just have list
  indices
* A better icon for zoom to extent and for that icon to be properly
  placed
This commit is contained in:
Tom MacWright
2013-03-20 13:32:42 -04:00
parent a16b677fb3
commit 51d915c8a6
5 changed files with 174 additions and 103 deletions
+12 -5
View File
@@ -1415,6 +1415,14 @@ div.combobox {
height:18px;
}
.background-control .layer-toggle-gpx .layer-extent {
display:none;
}
.background-control .layer-toggle-gpx.selected .layer-extent {
display:inline-block;
}
/* Geocoder */
.geocode-control, .geocode-control form {
@@ -1471,9 +1479,12 @@ div.combobox {
background:#000;
}
#surface, #tile-g {
#surface, #layer-g, .layer-layer {
position:absolute;
top:0;
left: 0;
right: 0;
bottom: 0;
transform-origin:0 0;
-ms-transform-origin:0 0;
-webkit-transform-origin:0 0;
@@ -1489,10 +1500,6 @@ div.combobox {
position: static;
}
#tile-g {
opacity: 0.5;
}
/* About Section
------------------------------------------------------- */
+3
View File
@@ -184,3 +184,6 @@ en:
out: Zoom Out
imagery:
provided_by: "Imagery provided by {source}"
gpx:
local_layer: "Local GPX file"
drag_drop: "Drag and drop a .gpx file on the page"
+20 -4
View File
@@ -1,7 +1,8 @@
iD.LocalGpx = function() {
iD.LocalGpx = function(context) {
var tileSize = 256,
projection,
gj = {},
enable = true,
size = [0, 0],
transformProp = iD.util.prefixCSSProperty('Transform'),
path = d3.geo.path().projection(projection),
@@ -12,7 +13,7 @@ iD.LocalGpx = function() {
path.projection(projection);
var surf = selection.selectAll('svg')
.data([gj]);
.data(enable ? [gj] : []);
surf.exit().remove();
@@ -43,17 +44,30 @@ iD.LocalGpx = function() {
return render;
};
render.enable = function(_) {
if (!arguments.length) return enable;
enable = _;
return render;
};
render.geojson = function(_) {
if (!arguments.length) return gj;
gj = _;
return render;
};
render.size = function(_) {
if (!arguments.length) return size;
size = _;
return render;
};
render.id = 'layer-gpx';
function over() {
d3.event.stopPropagation();
d3.event.preventDefault();
d3.event.dataTransfer.dropEffect = 'copy';
console.log('here');
}
d3.select('body')
@@ -65,7 +79,9 @@ iD.LocalGpx = function() {
reader = new FileReader();
reader.onload = function(e) {
gj = toGeoJSON.gpx(toDom(e.target.result));
render.geojson(toGeoJSON.gpx(toDom(e.target.result)));
context.redraw();
context.map().pan([0, 0]);
};
reader.readAsText(f);
+4 -4
View File
@@ -13,7 +13,7 @@ iD.Map = function(context) {
minzoom = 0,
layers = [
iD.Background().projection(projection),
iD.LocalGpx().projection(projection)],
iD.LocalGpx(context).projection(projection)],
transformProp = iD.util.prefixCSSProperty('Transform'),
points = iD.svg.Points(roundedProjection, context),
vertices = iD.svg.Vertices(roundedProjection, context),
@@ -31,7 +31,7 @@ iD.Map = function(context) {
selection.call(zoom);
layergroup = selection.append('div')
.attr('id', 'layers-g');
.attr('id', 'layer-g');
var supersurface = selection.append('div')
.style('position', 'absolute');
@@ -166,13 +166,13 @@ iD.Map = function(context) {
if (!difference) {
var sel = layergroup
.selectAll('.tile-layer-group')
.selectAll('.layer-layer')
.data(layers);
sel.exit().remove();
sel.enter().append('div')
.attr('class', 'tile-layer-group');
.attr('class', 'layer-layer');
sel.each(function(layer) {
d3.select(this).call(layer);
+135 -90
View File
@@ -1,9 +1,13 @@
iD.ui.Background = function(context) {
var event = d3.dispatch('cancel', 'save'),
key = 'b',
opacities = [1, 0.5, 0];
var layers = context.backgroundSources();
opacities = [1, 0.5, 0],
directions = [
['left', [1, 0]],
['top', [0, -1]],
['right', [-1, 0]],
['bottom', [0, 1]]],
layers = context.backgroundSources();
function getSources() {
var ext = context.map().extent();
@@ -15,24 +19,6 @@ iD.ui.Background = function(context) {
function background(selection) {
var content = selection.append('div')
.attr('class', 'content fillD map-overlay hide'),
shown = false;
var tooltip = bootstrap.tooltip()
.placement('right')
.html(true)
.title(iD.ui.tooltipHtml(t('background.description'), key));
var button = selection.append('button')
.attr('tabindex', -1)
.attr('class', 'fillD')
.on('click.background-toggle', toggle)
.call(tooltip);
button.append('span')
.attr('class', 'layers icon');
function toggle() {
tooltip.hide(button);
setVisible(content.classed('hide'));
@@ -55,56 +41,23 @@ iD.ui.Background = function(context) {
}
}
context.surface().on('mousedown.background-outside', function() {
setVisible(false);
});
context.container().on('mousedown.background-outside', function() {
setVisible(false);
});
var opa = content
.append('div')
.attr('class', 'opacity-options-wrapper');
opa.append('h4')
.text(t('background.title'));
var opacityList = opa.append('ul')
.attr('class', 'opacity-options');
function setOpacity(d) {
context.map().tilesurface
context.map().layersurface.selectAll('.layer-layer')
.filter(function(d) { return d == context.map().layers[0]; })
.transition()
.style('opacity', d)
.attr('data-opacity', d);
opacityList.selectAll('li')
.classed('selected', false);
d3.select(this)
.classed('selected', true);
if (d3.event) {
d3.select(this)
.classed('selected', true);
}
}
opacityList.selectAll('div.opacity')
.data(opacities)
.enter()
.append('li')
.attr('data-original-title', function(d) {
return t('background.percent_brightness', { opacity: (d * 100) });
})
.on('click.set-opacity', setOpacity)
.html("<div class='select-box'></div>")
.call(bootstrap.tooltip()
.placement('top'))
.append('div')
.attr('class', 'opacity')
.style('opacity', String);
// Make sure there is an active selection by default
opa.select('.opacity-options li:nth-child(2)')
.classed('selected', true);
function selectLayer(d) {
content.selectAll('a.layer')
.classed('selected', function(d) {
return d.data.name === context.background().source().data.name;
@@ -135,9 +88,16 @@ iD.ui.Background = function(context) {
selectLayer(d);
}
var layerList = content
.append('ul')
.attr('class', 'toggle-list fillL');
function clickGpx(d) {
d3.event.preventDefault();
if (!_.isEmpty(context.map().layers[1].geojson())) {
context.map().layers[1]
.enable(!context.map().layers[1].enable());
d3.select(this)
.classed('selected', context.map().layers[1].enable());
context.redraw();
}
}
function update() {
var layerLinks = layerList.selectAll('a.layer')
@@ -169,26 +129,121 @@ iD.ui.Background = function(context) {
return d.data.name;
});
gpxLayerItem
.classed('selected', function() {
var gpxLayer = context.map().layers[1];
return !_.isEmpty(gpxLayer.geojson()) &&
gpxLayer.enable();
});
layerLinks.exit()
.remove();
selectLayer(context.background().source());
}
context.map().on('move.background-update', _.debounce(update, 1000));
function clickNudge(d) {
var interval = window.setInterval(nudge, 100);
update();
d3.select(this).on('mouseup', function() {
window.clearInterval(interval);
nudge();
});
function nudge() {
context.background().nudge(d[1], context.map().zoom());
context.redraw();
}
}
var content = selection.append('div')
.attr('class', 'content fillD map-overlay hide'),
tooltip = bootstrap.tooltip()
.placement('right')
.html(true)
.title(iD.ui.tooltipHtml(t('background.description'), key)),
button = selection.append('button')
.attr('tabindex', -1)
.attr('class', 'fillD')
.on('click.background-toggle', toggle)
.call(tooltip),
opa = content
.append('div')
.attr('class', 'opacity-options-wrapper'),
shown = false;
button.append('span')
.attr('class', 'layers icon');
opa.append('h4')
.text(t('background.title'));
context.surface().on('mousedown.background-outside', function() {
setVisible(false);
});
context.container().on('mousedown.background-outside', function() {
setVisible(false);
});
var opacityList = opa.append('ul')
.attr('class', 'opacity-options');
opacityList.selectAll('div.opacity')
.data(opacities)
.enter()
.append('li')
.attr('data-original-title', function(d) {
return t('background.percent_brightness', { opacity: (d * 100) });
})
.on('click.set-opacity', setOpacity)
.html("<div class='select-box'></div>")
.call(bootstrap.tooltip()
.placement('top'))
.append('div')
.attr('class', 'opacity')
.style('opacity', String);
// Make sure there is an active selection by default
opa.select('.opacity-options li:nth-child(2)')
.classed('selected', true);
var layerList = content
.append('ul')
.attr('class', 'toggle-list fillL');
var gpxLayerItem = content
.append('ul')
.attr('class', 'toggle-list fillL')
.append('li')
.append('a')
.classed('layer-toggle-gpx', true)
.call(bootstrap.tooltip()
.title(t('gpx.drag_drop'))
.placement('right'))
.on('click.set-gpx', clickGpx);
gpxLayerItem
.append('span')
.attr('class', 'icon toggle');
gpxLayerItem.append('span')
.text(t('gpx.local_layer'));
gpxLayerItem
.append('a')
.attr('class', 'icon geocode layer-extent')
.on('click', function() {
d3.event.preventDefault();
d3.event.stopPropagation();
context.map()
.extent(d3.geo.bounds(context.map().layers[1].geojson()));
});
var adjustments = content
.append('div')
.attr('class', 'adjustments pad1');
var directions = [
['left', [1, 0]],
['top', [0, -1]],
['right', [-1, 0]],
['bottom', [0, 1]]];
adjustments.append('a')
.text(t('background.fix_misalignment'))
.attr('href', '#')
@@ -197,8 +252,7 @@ iD.ui.Background = function(context) {
.on('click', function() {
var exp = d3.select(this).classed('expanded');
nudge_container.style('display', exp ? 'none' : 'block');
d3.select(this)
.classed('expanded', !exp);
d3.select(this).classed('expanded', !exp);
d3.event.preventDefault();
});
@@ -212,20 +266,7 @@ iD.ui.Background = function(context) {
.append('button')
.attr('class', function(d) { return d[0] + ' nudge'; })
.text(function(d) { return d[0]; })
.on('mousedown', function(d) {
var interval = window.setInterval(nudge, 100);
d3.select(this).on('mouseup', function() {
window.clearInterval(interval);
nudge();
});
function nudge() {
context.background().nudge(d[1], context.map().zoom());
context.redraw();
}
});
.on('mousedown', clickNudge);
nudge_container.append('button')
.text(t('background.reset'))
@@ -235,8 +276,12 @@ iD.ui.Background = function(context) {
context.redraw();
});
var keybinding = d3.keybinding('background');
context.map()
.on('move.background-update', _.debounce(update, 1000));
update();
setOpacity(0.5);
var keybinding = d3.keybinding('background');
keybinding.on(key, toggle);
d3.select(document)