diff --git a/data/core.yaml b/data/core.yaml index e9518957b..8f29823d7 100644 --- a/data/core.yaml +++ b/data/core.yaml @@ -287,6 +287,9 @@ en: location: key: L title: Location + zoom: Zoom + unknown_location: Unknown Location + unknown_imagery_age: Unknown Imagery Age measurement: key: M title: Measurement diff --git a/dist/locales/en.json b/dist/locales/en.json index 13ca2d42f..78a101e60 100644 --- a/dist/locales/en.json +++ b/dist/locales/en.json @@ -363,7 +363,10 @@ }, "location": { "key": "L", - "title": "Location" + "title": "Location", + "zoom": "Zoom", + "unknown_location": "Unknown Location", + "unknown_imagery_age": "Unknown Imagery Age" }, "measurement": { "key": "M", diff --git a/modules/renderer/background_source.js b/modules/renderer/background_source.js index 38252f1ff..c8b2cff63 100644 --- a/modules/renderer/background_source.js +++ b/modules/renderer/background_source.js @@ -106,6 +106,11 @@ export function rendererBackgroundSource(data) { source.copyrightNotices = function() {}; + source.getVintage = function(center, zoom, callback) { + callback(null, { start: null, end: null }); + }; + + return source; } @@ -137,6 +142,7 @@ rendererBackgroundSource.Bing = function(data, dispatch) { dispatch.call('change'); }); + bing.copyrightNotices = function(zoom, extent) { zoom = Math.min(zoom, 21); return providers.filter(function(provider) { @@ -150,8 +156,31 @@ rendererBackgroundSource.Bing = function(data, dispatch) { }).join(', '); }; + + bing.getVintage = function(center, zoom, callback) { + zoom = Math.min(zoom, 21); + + var centerPoint = center[1] + ',' + center[0], + url = 'https://dev.virtualearth.net/REST/v1/Imagery/Metadata/Aerial/' + centerPoint + + '?zl=' + zoom + '&key=' + key + '&jsonp={callback}'; + + jsonpRequest(url, function(result) { + var error = (!result && 'Unknown Error') || result.errorDetails; + if (error) { + return callback(error); + } else { + return callback(null, { + start: result.resourceSets[0].resources[0].vintageStart, + end: result.resourceSets[0].resources[0].vintageEnd + }); + } + }); + }; + + bing.terms_url = 'https://blog.openstreetmap.org/2010/11/30/microsoft-imagery-details'; + return bing; }; @@ -159,18 +188,22 @@ rendererBackgroundSource.Bing = function(data, dispatch) { rendererBackgroundSource.None = function() { var source = rendererBackgroundSource({ id: 'none', template: '' }); + source.name = function() { return t('background.none'); }; + source.imageryUsed = function() { return 'None'; }; + source.area = function() { return -1; // sources in background pane are sorted by area }; + return source; }; @@ -178,17 +211,21 @@ rendererBackgroundSource.None = function() { rendererBackgroundSource.Custom = function(template) { var source = rendererBackgroundSource({ id: 'custom', template: template }); + source.name = function() { return t('background.custom'); }; + source.imageryUsed = function() { return 'Custom (' + template + ')'; }; + source.area = function() { return -2; // sources in background pane are sorted by area }; + return source; }; diff --git a/modules/ui/panels/location.js b/modules/ui/panels/location.js index 056e8ec6f..acc2bbd1b 100644 --- a/modules/ui/panels/location.js +++ b/modules/ui/panels/location.js @@ -6,7 +6,7 @@ import { services } from '../../services'; export function uiPanelLocation(context) { var lastLocation = ''; - var debouncedUpdate = _.debounce(updateLocation, 250); + var lastImagery = ''; var OSM_PRECISION = 7; @@ -43,26 +43,61 @@ export function uiPanelLocation(context) { .append('li') .text(coordStr); - // Location Name - if (services.geocoder) { - selection - .append('p') - .attr('class', 'location-name') - .text(lastLocation); + list + .append('li') + .text(t('infobox.location.zoom') + ': ' + context.map().zoom().toFixed(2)); - debouncedUpdate(selection, coord); + // Date of Imagery + selection + .append('p') + .attr('class', 'imagery-vintage') + .text(lastImagery); + + // Location Name + selection + .append('p') + .attr('class', 'location-name') + .text(lastLocation); + + debouncedLocation(selection, coord); + } + + + var debouncedLocation = _.debounce(updateLocation, 250); + function updateLocation(selection, coord) { + if (!services.geocoder) { + lastLocation = t('infobox.location.unknown_location'); + selection.selectAll('.location-name') + .text(lastLocation); + } else { + services.geocoder.reverse(coord, function(err, result) { + lastLocation = result ? result.display_name : t('infobox.location.unknown_location'); + selection.selectAll('.location-name') + .text(lastLocation); + }); } } - function updateLocation(selection, coord) { - if (!services.geocoder) return; - services.geocoder.reverse(coord, function(err, result) { - if (result) { - lastLocation = result.display_name; - selection.selectAll('.location-name') - .text(lastLocation); + var debouncedImageryVintage = _.debounce(updateImageryVintage, 250); + function updateImageryVintage(selection) { + var tiledata = d3.select('.layer-background img').datum(), + zoom = tiledata[2] || Math.floor(context.map().zoom()), + center = context.map().center(); + + context.background().baseLayerSource().getVintage(center, zoom, function(err, result) { + if (!result) { + lastImagery = t('infobox.location.unknown_imagery_age'); + } else { + if (result.start || result.end) { + lastImagery = (result.start || '?') + ' - ' + (result.end || '?'); + } else { + lastImagery = t('infobox.location.unknown_imagery_age'); + } } + + selection.selectAll('.imagery-vintage') + .text(lastImagery); }); } @@ -74,11 +109,24 @@ export function uiPanelLocation(context) { .on('mousemove.info-location', function() { selection.call(redraw); }); + + context.map() + .on('drawn.info-location', function() { + selection.call(redraw); + }) + .on('move.info-location', function() { + selection.call(debouncedImageryVintage); + }); + }; panel.off = function() { context.surface() .on('mousemove.info-location', null); + + context.map() + .on('drawn.info-location', null) + .on('move.info-location', null); }; panel.id = 'location';