mirror of
https://github.com/FoggedLens/iD.git
synced 2026-03-13 14:46:01 +00:00
Move gpx layer from background to surface
This commit is contained in:
@@ -1,9 +1,7 @@
|
||||
iD.Background = function(context) {
|
||||
var dispatch = d3.dispatch('change'),
|
||||
baseLayer = iD.TileLayer()
|
||||
.projection(context.projection),
|
||||
gpxLayer = iD.svg.Gpx(context, dispatch)
|
||||
.projection(context.projection),
|
||||
baseLayer = iD.TileLayer().projection(context.projection),
|
||||
gpxLayer = iD.svg.Gpx(context.projection, context),
|
||||
mapillaryImageLayer,
|
||||
mapillarySignLayer,
|
||||
overlayLayers = [];
|
||||
@@ -78,13 +76,20 @@ iD.Background = function(context) {
|
||||
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 gpx = selection.selectAll('.layer-gpx')
|
||||
// .data([0]);
|
||||
|
||||
// gpx.enter().insert('div')
|
||||
// .attr('class', 'layer-layer layer-gpx');
|
||||
|
||||
// gpx.call(gpxLayer);
|
||||
|
||||
selection.selectAll('#surface')
|
||||
.call(gpxLayer);
|
||||
|
||||
|
||||
|
||||
|
||||
var mapillary = iD.services.mapillary,
|
||||
@@ -133,7 +138,6 @@ iD.Background = function(context) {
|
||||
|
||||
background.dimensions = function(_) {
|
||||
baseLayer.dimensions(_);
|
||||
gpxLayer.dimensions(_);
|
||||
if (mapillaryImageLayer) mapillaryImageLayer.dimensions(_);
|
||||
if (mapillarySignLayer) mapillarySignLayer.dimensions(_);
|
||||
|
||||
@@ -156,51 +160,20 @@ iD.Background = function(context) {
|
||||
background.baseLayerSource(findSource('Bing'));
|
||||
};
|
||||
|
||||
background.gpxLayer = function() {
|
||||
return gpxLayer;
|
||||
};
|
||||
|
||||
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, true)) {
|
||||
var extent = iD.geo.Extent(d3.geo.bounds(gpxLayer.geojson()));
|
||||
map.centerZoom(extent.center(), map.trimmedExtentZoom(extent));
|
||||
}
|
||||
}
|
||||
return background.hasGpxLayer() && gpxLayer.enabled();
|
||||
};
|
||||
|
||||
background.toggleGpxLayer = function() {
|
||||
gpxLayer.enable(!gpxLayer.enable());
|
||||
iD.ui.MapInMap.gpxLayer.enable(!iD.ui.MapInMap.gpxLayer.enable());
|
||||
gpxLayer.enabled(!gpxLayer.enabled());
|
||||
dispatch.change();
|
||||
};
|
||||
|
||||
@@ -317,15 +290,8 @@ iD.Background = function(context) {
|
||||
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();
|
||||
}
|
||||
});
|
||||
if (q.gpx) {
|
||||
gpxLayer.url(q.gpx);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -145,7 +145,7 @@ iD.Map = function(context) {
|
||||
|
||||
function editOff() {
|
||||
context.features().resetStats();
|
||||
surface.selectAll('.layer *').remove();
|
||||
surface.selectAll('.layer-osm *').remove();
|
||||
dispatch.drawn({full: true});
|
||||
}
|
||||
|
||||
|
||||
219
js/id/svg/gpx.js
219
js/id/svg/gpx.js
@@ -1,101 +1,160 @@
|
||||
iD.svg.Gpx = function(context) {
|
||||
var projection,
|
||||
gj = {},
|
||||
enable = true,
|
||||
svg;
|
||||
iD.svg.Gpx = function(projection, context) {
|
||||
var showLabels = true,
|
||||
layer;
|
||||
|
||||
function render(selection) {
|
||||
svg = selection.selectAll('svg')
|
||||
.data([render]);
|
||||
|
||||
svg.enter()
|
||||
.append('svg');
|
||||
function init() {
|
||||
if (iD.svg.Gpx.initialized) return; // run once
|
||||
|
||||
svg.style('display', enable ? 'block' : 'none');
|
||||
iD.svg.Gpx.geojson = {};
|
||||
iD.svg.Gpx.enabled = true;
|
||||
|
||||
var paths = svg
|
||||
function over() {
|
||||
d3.event.stopPropagation();
|
||||
d3.event.preventDefault();
|
||||
d3.event.dataTransfer.dropEffect = 'copy';
|
||||
}
|
||||
|
||||
d3.select('body')
|
||||
.attr('dropzone', 'copy')
|
||||
.on('drop.localgpx', function() {
|
||||
d3.event.stopPropagation();
|
||||
d3.event.preventDefault();
|
||||
if (!iD.detect().filedrop) return;
|
||||
gpx.files(d3.event.dataTransfer.files);
|
||||
})
|
||||
.on('dragenter.localgpx', over)
|
||||
.on('dragexit.localgpx', over)
|
||||
.on('dragover.localgpx', over);
|
||||
|
||||
iD.svg.Gpx.initialized = true;
|
||||
}
|
||||
|
||||
|
||||
function gpx(surface) {
|
||||
var geojson = iD.svg.Gpx.geojson,
|
||||
enabled = iD.svg.Gpx.enabled;
|
||||
|
||||
layer = surface.selectAll('.layer-gpx')
|
||||
.data(enabled ? [0] : []);
|
||||
|
||||
layer.enter()
|
||||
.append('g')
|
||||
.attr('class', 'layer layer-gpx');
|
||||
|
||||
layer.exit()
|
||||
.remove();
|
||||
|
||||
|
||||
var paths = layer
|
||||
.selectAll('path')
|
||||
.data([gj]);
|
||||
.data([geojson]);
|
||||
|
||||
paths
|
||||
.enter()
|
||||
paths.enter()
|
||||
.append('path')
|
||||
.attr('class', 'gpx');
|
||||
|
||||
paths.exit()
|
||||
.remove();
|
||||
|
||||
var path = d3.geo.path()
|
||||
.projection(projection);
|
||||
|
||||
paths
|
||||
.attr('d', path);
|
||||
|
||||
if (typeof gj.features !== 'undefined') {
|
||||
svg
|
||||
.selectAll('text')
|
||||
.remove();
|
||||
|
||||
svg
|
||||
.selectAll('path')
|
||||
.data(gj.features)
|
||||
.enter()
|
||||
.append('text')
|
||||
.attr('class', 'gpx')
|
||||
.text(function(d) {
|
||||
return d.properties.desc || d.properties.name;
|
||||
})
|
||||
.attr('x', function(d) {
|
||||
var centroid = path.centroid(d);
|
||||
return centroid[0] + 5;
|
||||
})
|
||||
.attr('y', function(d) {
|
||||
var centroid = path.centroid(d);
|
||||
return centroid[1];
|
||||
});
|
||||
var labels = layer.selectAll('text')
|
||||
.data(showLabels && geojson.features ? geojson.features : []);
|
||||
|
||||
labels.enter()
|
||||
.append('text')
|
||||
.attr('class', 'gpx')
|
||||
.text(function(d) {
|
||||
return d.properties.desc || d.properties.name;
|
||||
});
|
||||
|
||||
labels.exit()
|
||||
.remove();
|
||||
|
||||
labels
|
||||
.attr('x', function(d) {
|
||||
var centroid = path.centroid(d);
|
||||
return centroid[0] + 7;
|
||||
})
|
||||
.attr('y', function(d) {
|
||||
var centroid = path.centroid(d);
|
||||
return centroid[1];
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
function toDom(x) {
|
||||
return (new DOMParser()).parseFromString(x, 'text/xml');
|
||||
}
|
||||
|
||||
|
||||
gpx.showLabels = function(_) {
|
||||
if (!arguments.length) return showLabels;
|
||||
showLabels = _;
|
||||
return gpx;
|
||||
};
|
||||
|
||||
gpx.enabled = function(_) {
|
||||
if (!arguments.length) return iD.svg.Gpx.enabled;
|
||||
iD.svg.Gpx.enabled = _;
|
||||
return gpx;
|
||||
};
|
||||
|
||||
gpx.geojson = function(gj) {
|
||||
if (!arguments.length) return iD.svg.Gpx.geojson;
|
||||
if (_.isEmpty(gj) || _.isEmpty(gj.features)) return gpx;
|
||||
iD.svg.Gpx.geojson = gj;
|
||||
return gpx;
|
||||
};
|
||||
|
||||
gpx.url = function(url) {
|
||||
d3.text(url, function(err, data) {
|
||||
if (!err) {
|
||||
gpx.geojson(toGeoJSON.gpx(toDom(data)));
|
||||
// dispatch.change();
|
||||
}
|
||||
});
|
||||
return gpx;
|
||||
};
|
||||
|
||||
gpx.files = function(fileList) {
|
||||
var f = fileList[0],
|
||||
reader = new FileReader();
|
||||
|
||||
reader.onload = function(e) {
|
||||
gpx.geojson(toGeoJSON.gpx(toDom(e.target.result))).fitZoom();
|
||||
// dispatch.change();
|
||||
};
|
||||
|
||||
reader.readAsText(f);
|
||||
return gpx;
|
||||
};
|
||||
|
||||
gpx.fitZoom = function() {
|
||||
var geojson = iD.svg.Gpx.geojson;
|
||||
if (_.isEmpty(geojson) || _.isEmpty(geojson.features)) return gpx;
|
||||
|
||||
var map = context.map(),
|
||||
viewport = map.trimmedExtent().polygon(),
|
||||
coords = _.reduce(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, true)) {
|
||||
var extent = iD.geo.Extent(d3.geo.bounds(geojson));
|
||||
map.centerZoom(extent.center(), map.trimmedExtentZoom(extent));
|
||||
}
|
||||
}
|
||||
|
||||
render.projection = function(_) {
|
||||
if (!arguments.length) return projection;
|
||||
projection = _;
|
||||
return render;
|
||||
return gpx;
|
||||
};
|
||||
|
||||
render.enable = function(_) {
|
||||
if (!arguments.length) return enable;
|
||||
enable = _;
|
||||
return render;
|
||||
};
|
||||
|
||||
render.geojson = function(_) {
|
||||
if (!arguments.length) return gj;
|
||||
gj = _;
|
||||
return render;
|
||||
};
|
||||
|
||||
render.dimensions = function(_) {
|
||||
if (!arguments.length) return svg.dimensions();
|
||||
svg.dimensions(_);
|
||||
return render;
|
||||
};
|
||||
|
||||
render.id = 'layer-gpx';
|
||||
|
||||
function over() {
|
||||
d3.event.stopPropagation();
|
||||
d3.event.preventDefault();
|
||||
d3.event.dataTransfer.dropEffect = 'copy';
|
||||
}
|
||||
|
||||
d3.select('body')
|
||||
.attr('dropzone', 'copy')
|
||||
.on('drop.localgpx', function() {
|
||||
d3.event.stopPropagation();
|
||||
d3.event.preventDefault();
|
||||
if (!iD.detect().filedrop) return;
|
||||
context.background().gpxLayerFiles(d3.event.dataTransfer.files);
|
||||
})
|
||||
.on('dragenter.localgpx', over)
|
||||
.on('dragexit.localgpx', over)
|
||||
.on('dragover.localgpx', over);
|
||||
|
||||
return render;
|
||||
init();
|
||||
return gpx;
|
||||
};
|
||||
|
||||
@@ -9,6 +9,6 @@ iD.svg.Surface = function() {
|
||||
.data(['areas', 'lines', 'hit', 'halo', 'label']);
|
||||
|
||||
layers.enter().append('g')
|
||||
.attr('class', function(d) { return 'layer layer-' + d; });
|
||||
.attr('class', function(d) { return 'layer layer-osm layer-' + d; });
|
||||
};
|
||||
};
|
||||
|
||||
@@ -133,10 +133,9 @@ iD.ui.MapData = function(context) {
|
||||
|
||||
|
||||
function drawGpxItem(selection) {
|
||||
var supportsGpx = iD.detect().filedrop,
|
||||
gpxLayerItem = selection
|
||||
.selectAll('.layer-gpx')
|
||||
.data(supportsGpx ? [0] : []);
|
||||
var gpxLayerItem = selection
|
||||
.selectAll('.layer-gpx')
|
||||
.data([0]);
|
||||
|
||||
// Enter
|
||||
var enter = gpxLayerItem.enter()
|
||||
@@ -153,7 +152,7 @@ iD.ui.MapData = function(context) {
|
||||
.on('click', function() {
|
||||
d3.event.preventDefault();
|
||||
d3.event.stopPropagation();
|
||||
context.background().zoomToGpxLayer();
|
||||
context.background().gpxLayer().fitZoom();
|
||||
})
|
||||
.call(iD.svg.Icon('#icon-search'));
|
||||
|
||||
@@ -166,7 +165,7 @@ iD.ui.MapData = function(context) {
|
||||
d3.select(document.createElement('input'))
|
||||
.attr('type', 'file')
|
||||
.on('change', function() {
|
||||
context.background().gpxLayerFiles(d3.event.target.files);
|
||||
context.background().gpxLayer().files(d3.event.target.files);
|
||||
})
|
||||
.node().click();
|
||||
})
|
||||
@@ -185,8 +184,8 @@ iD.ui.MapData = function(context) {
|
||||
.text(t('gpx.local_layer'));
|
||||
|
||||
// Update
|
||||
var hasGpx = supportsGpx && context.background().hasGpxLayer(),
|
||||
showsGpx = supportsGpx && context.background().showsGpxLayer();
|
||||
var hasGpx = context.background().hasGpxLayer(),
|
||||
showsGpx = context.background().showsGpxLayer();
|
||||
|
||||
gpxLayerItem
|
||||
.classed('active', showsGpx)
|
||||
|
||||
@@ -4,18 +4,15 @@ iD.ui.MapInMap = function(context) {
|
||||
function map_in_map(selection) {
|
||||
var backgroundLayer = iD.TileLayer(),
|
||||
overlayLayers = {},
|
||||
dispatch = d3.dispatch('change'),
|
||||
gpxLayer = iD.svg.Gpx(context, dispatch),
|
||||
projection = iD.geo.RawMercator(),
|
||||
gpxLayer = iD.svg.Gpx(projection, context).showLabels(false),
|
||||
zoom = d3.behavior.zoom()
|
||||
.scaleExtent([ztok(0.5), ztok(24)])
|
||||
.on('zoom', zoomPan),
|
||||
transformed = false,
|
||||
panning = false,
|
||||
zDiff = 6, // by default, minimap renders at (main zoom - 6)
|
||||
tStart, tLast, tCurr, kLast, kCurr, tiles, svg, gpx, timeoutId;
|
||||
|
||||
iD.ui.MapInMap.gpxLayer = gpxLayer;
|
||||
tStart, tLast, tCurr, kLast, kCurr, tiles, svg, timeoutId;
|
||||
|
||||
function ztok(z) { return 256 * Math.pow(2, z); }
|
||||
function ktoz(k) { return Math.log(k) / Math.LN2 - 8; }
|
||||
@@ -155,6 +152,7 @@ iD.ui.MapInMap = function(context) {
|
||||
background
|
||||
.call(backgroundLayer);
|
||||
|
||||
|
||||
// redraw overlay
|
||||
var overlaySources = context.background().overlayLayerSources();
|
||||
var activeOverlayLayers = [];
|
||||
@@ -188,20 +186,20 @@ iD.ui.MapInMap = function(context) {
|
||||
overlays.exit()
|
||||
.remove();
|
||||
|
||||
// redraw gpx overlay
|
||||
gpxLayer
|
||||
.projection(projection);
|
||||
|
||||
gpx = tiles
|
||||
var gpx = tiles
|
||||
.selectAll('.map-in-map-gpx')
|
||||
.data([0]);
|
||||
.data(gpxLayer.enabled() ? [0] : []);
|
||||
|
||||
gpx.enter()
|
||||
.append('div')
|
||||
.append('svg')
|
||||
.attr('class', 'map-in-map-gpx');
|
||||
|
||||
gpx.exit()
|
||||
.remove();
|
||||
|
||||
gpx.call(gpxLayer);
|
||||
gpx.dimensions(dMini);
|
||||
|
||||
|
||||
// redraw bounding box
|
||||
if (!panning) {
|
||||
|
||||
Reference in New Issue
Block a user