mirror of
https://github.com/FoggedLens/iD.git
synced 2026-02-14 17:52:55 +00:00
278 lines
8.0 KiB
JavaScript
278 lines
8.0 KiB
JavaScript
iD.Background = function(context) {
|
|
var dispatch = d3.dispatch('change'),
|
|
baseLayer = iD.TileLayer()
|
|
.projection(context.projection),
|
|
gpxLayer = iD.GpxLayer(context, dispatch)
|
|
.projection(context.projection),
|
|
mapillaryLayer = iD.MapillaryLayer(context),
|
|
overlayLayers = [];
|
|
|
|
var backgroundSources;
|
|
|
|
function findSource(id) {
|
|
return _.find(backgroundSources, function(d) {
|
|
return d.id && d.id === id;
|
|
});
|
|
}
|
|
|
|
function updateImagery() {
|
|
var b = background.baseLayerSource(),
|
|
o = overlayLayers.map(function (d) { return d.source().id; }).join(','),
|
|
q = iD.util.stringQs(location.hash.substring(1));
|
|
|
|
var id = b.id;
|
|
if (id === 'custom') {
|
|
id = 'custom:' + b.template;
|
|
}
|
|
|
|
if (id) {
|
|
q.background = id;
|
|
} else {
|
|
delete q.background;
|
|
}
|
|
|
|
if (o) {
|
|
q.overlays = o;
|
|
} else {
|
|
delete q.overlays;
|
|
}
|
|
|
|
location.replace('#' + iD.util.qsString(q, true));
|
|
|
|
var imageryUsed = [b.imageryUsed()];
|
|
|
|
overlayLayers.forEach(function (d) {
|
|
var source = d.source();
|
|
if (!source.isLocatorOverlay()) {
|
|
imageryUsed.push(source.imageryUsed());
|
|
}
|
|
});
|
|
|
|
if (background.showsGpxLayer()) {
|
|
imageryUsed.push('Local GPX');
|
|
}
|
|
|
|
context.history().imageryUsed(imageryUsed);
|
|
}
|
|
|
|
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 overlays = selection.selectAll('.layer-overlay')
|
|
.data(overlayLayers, function(d) { return d.source().name(); });
|
|
|
|
overlays.enter().insert('div', '.layer-data')
|
|
.attr('class', 'layer-layer layer-overlay');
|
|
|
|
overlays.each(function(layer) {
|
|
d3.select(this).call(layer);
|
|
});
|
|
|
|
overlays.exit()
|
|
.remove();
|
|
|
|
var gpx = selection.selectAll('.layer-gpx')
|
|
.data([0]);
|
|
|
|
gpx.enter().insert('div')
|
|
.attr('class', 'layer-layer layer-gpx');
|
|
|
|
gpx.call(gpxLayer);
|
|
|
|
var mapillary = selection.selectAll('.layer-mapillary')
|
|
.data([0]);
|
|
|
|
mapillary.enter().insert('div')
|
|
.attr('class', 'layer-layer layer-mapillary');
|
|
|
|
mapillary.call(mapillaryLayer);
|
|
}
|
|
|
|
background.sources = function(extent) {
|
|
return backgroundSources.filter(function(source) {
|
|
return source.intersects(extent);
|
|
});
|
|
};
|
|
|
|
background.dimensions = function(_) {
|
|
baseLayer.dimensions(_);
|
|
gpxLayer.dimensions(_);
|
|
mapillaryLayer.dimensions(_);
|
|
|
|
overlayLayers.forEach(function(layer) {
|
|
layer.dimensions(_);
|
|
});
|
|
};
|
|
|
|
background.baseLayerSource = function(d) {
|
|
if (!arguments.length) return baseLayer.source();
|
|
|
|
baseLayer.source(d);
|
|
dispatch.change();
|
|
updateImagery();
|
|
|
|
return background;
|
|
};
|
|
|
|
background.bing = function() {
|
|
background.baseLayerSource(findSource('Bing'));
|
|
};
|
|
|
|
background.hasGpxLayer = function() {
|
|
return !_.isEmpty(gpxLayer.geojson());
|
|
};
|
|
|
|
background.showsGpxLayer = function() {
|
|
return background.hasGpxLayer() && gpxLayer.enable();
|
|
};
|
|
|
|
function toDom(x) {
|
|
return (new DOMParser()).parseFromString(x, 'text/xml');
|
|
}
|
|
|
|
background.gpxLayerFiles = function(fileList) {
|
|
var f = fileList[0],
|
|
reader = new FileReader();
|
|
|
|
reader.onload = function(e) {
|
|
gpxLayer.geojson(toGeoJSON.gpx(toDom(e.target.result)));
|
|
iD.ui.MapInMap.gpxLayer.geojson(toGeoJSON.gpx(toDom(e.target.result)));
|
|
background.zoomToGpxLayer();
|
|
dispatch.change();
|
|
};
|
|
|
|
reader.readAsText(f);
|
|
};
|
|
|
|
background.zoomToGpxLayer = function() {
|
|
if (background.hasGpxLayer()) {
|
|
var map = context.map(),
|
|
viewport = map.trimmedExtent().polygon(),
|
|
coords = _.reduce(gpxLayer.geojson().features, function(coords, feature) {
|
|
var c = feature.geometry.coordinates;
|
|
return _.union(coords, feature.geometry.type === 'Point' ? [c] : c);
|
|
}, []);
|
|
|
|
if (!iD.geo.polygonIntersectsPolygon(viewport, coords)) {
|
|
var extent = iD.geo.Extent(d3.geo.bounds(gpxLayer.geojson()));
|
|
map.centerZoom(extent.center(), map.trimmedExtentZoom(extent));
|
|
}
|
|
}
|
|
};
|
|
|
|
background.toggleGpxLayer = function() {
|
|
gpxLayer.enable(!gpxLayer.enable());
|
|
iD.ui.MapInMap.gpxLayer.enable(!iD.ui.MapInMap.gpxLayer.enable());
|
|
dispatch.change();
|
|
};
|
|
|
|
background.showsMapillaryLayer = function() {
|
|
return mapillaryLayer.enable();
|
|
};
|
|
|
|
background.toggleMapillaryLayer = function() {
|
|
mapillaryLayer.enable(!mapillaryLayer.enable());
|
|
dispatch.change();
|
|
};
|
|
|
|
background.showsLayer = function(d) {
|
|
return d === baseLayer.source() ||
|
|
(d.id === 'custom' && baseLayer.source().id === 'custom') ||
|
|
overlayLayers.some(function(l) { return l.source() === d; });
|
|
};
|
|
|
|
background.overlayLayerSources = function() {
|
|
return overlayLayers.map(function (l) { return l.source(); });
|
|
};
|
|
|
|
background.toggleOverlayLayer = function(d) {
|
|
var layer;
|
|
|
|
for (var i = 0; i < overlayLayers.length; i++) {
|
|
layer = overlayLayers[i];
|
|
if (layer.source() === d) {
|
|
overlayLayers.splice(i, 1);
|
|
dispatch.change();
|
|
updateImagery();
|
|
return;
|
|
}
|
|
}
|
|
|
|
layer = iD.TileLayer()
|
|
.source(d)
|
|
.projection(context.projection)
|
|
.dimensions(baseLayer.dimensions());
|
|
|
|
overlayLayers.push(layer);
|
|
dispatch.change();
|
|
updateImagery();
|
|
};
|
|
|
|
background.nudge = function(d, zoom) {
|
|
baseLayer.source().nudge(d, zoom);
|
|
dispatch.change();
|
|
return background;
|
|
};
|
|
|
|
background.offset = function(d) {
|
|
if (!arguments.length) return baseLayer.source().offset();
|
|
baseLayer.source().offset(d);
|
|
dispatch.change();
|
|
return background;
|
|
};
|
|
|
|
background.load = function(imagery) {
|
|
backgroundSources = imagery.map(function(source) {
|
|
if (source.type === 'bing') {
|
|
return iD.BackgroundSource.Bing(source, dispatch);
|
|
} else {
|
|
return iD.BackgroundSource(source);
|
|
}
|
|
});
|
|
|
|
backgroundSources.unshift(iD.BackgroundSource.None());
|
|
|
|
var q = iD.util.stringQs(location.hash.substring(1)),
|
|
chosen = q.background || q.layer;
|
|
|
|
if (chosen && chosen.indexOf('custom:') === 0) {
|
|
background.baseLayerSource(iD.BackgroundSource.Custom(chosen.replace(/^custom:/, '')));
|
|
} else {
|
|
background.baseLayerSource(findSource(chosen) || findSource('Bing') || backgroundSources[1]);
|
|
}
|
|
|
|
var locator = _.find(backgroundSources, function(d) {
|
|
return d.overlay && d.default;
|
|
});
|
|
|
|
if (locator) {
|
|
background.toggleOverlayLayer(locator);
|
|
}
|
|
|
|
var overlays = (q.overlays || '').split(',');
|
|
overlays.forEach(function(overlay) {
|
|
overlay = findSource(overlay);
|
|
if (overlay) background.toggleOverlayLayer(overlay);
|
|
});
|
|
|
|
var gpx = q.gpx;
|
|
if (gpx) {
|
|
d3.text(gpx, function(err, gpxTxt) {
|
|
if (!err) {
|
|
gpxLayer.geojson(toGeoJSON.gpx(toDom(gpxTxt)));
|
|
iD.ui.MapInMap.gpxLayer.geojson(toGeoJSON.gpx(toDom(gpxTxt)));
|
|
dispatch.change();
|
|
}
|
|
});
|
|
}
|
|
};
|
|
|
|
return d3.rebind(background, dispatch, 'on');
|
|
};
|