mirror of
https://github.com/FoggedLens/iD.git
synced 2026-05-17 22:24:49 +02:00
Add photo overlay filter options for hiding flat and pano photos (close #5433)
This commit is contained in:
+11
-3
@@ -527,13 +527,21 @@ en:
|
||||
tooltip: "Drag and drop a data file onto the page, or click the button to setup"
|
||||
title: Custom Map Data
|
||||
zoom: Zoom to data
|
||||
photo_overlays: Photo Overlays
|
||||
fill_area: Fill Areas
|
||||
map_features: Map Features
|
||||
traffic_signs:
|
||||
title: Traffic Signs
|
||||
autohidden: "These features have been automatically hidden because too many would be shown on the screen. You can zoom in to edit them."
|
||||
osmhidden: "These features have been automatically hidden because the OpenStreetMap layer is hidden."
|
||||
photo_overlays:
|
||||
title: Photo Overlays
|
||||
traffic_signs:
|
||||
title: Traffic Signs
|
||||
photo_type:
|
||||
flat:
|
||||
title: "Flat Photos"
|
||||
tooltip: "Traditional photos"
|
||||
panoramic:
|
||||
title: "Panoramic Photos"
|
||||
tooltip: "360° photos"
|
||||
feature:
|
||||
points:
|
||||
description: Points
|
||||
|
||||
Vendored
+15
-3
@@ -644,14 +644,26 @@
|
||||
"zoom": "Zoom to data"
|
||||
}
|
||||
},
|
||||
"photo_overlays": "Photo Overlays",
|
||||
"fill_area": "Fill Areas",
|
||||
"map_features": "Map Features",
|
||||
"autohidden": "These features have been automatically hidden because too many would be shown on the screen. You can zoom in to edit them.",
|
||||
"osmhidden": "These features have been automatically hidden because the OpenStreetMap layer is hidden."
|
||||
},
|
||||
"photo_overlays": {
|
||||
"title": "Photo Overlays",
|
||||
"traffic_signs": {
|
||||
"title": "Traffic Signs"
|
||||
},
|
||||
"autohidden": "These features have been automatically hidden because too many would be shown on the screen. You can zoom in to edit them.",
|
||||
"osmhidden": "These features have been automatically hidden because the OpenStreetMap layer is hidden."
|
||||
"photo_type": {
|
||||
"flat": {
|
||||
"title": "Flat Photos",
|
||||
"tooltip": "Traditional photos"
|
||||
},
|
||||
"panoramic": {
|
||||
"title": "Panoramic Photos",
|
||||
"tooltip": "360° photos"
|
||||
}
|
||||
}
|
||||
},
|
||||
"feature": {
|
||||
"points": {
|
||||
|
||||
@@ -18,7 +18,7 @@ import { dataLocales, dataEn } from '../../data';
|
||||
import { geoRawMercator } from '../geo/raw_mercator';
|
||||
import { modeSelect } from '../modes/select';
|
||||
import { presetIndex } from '../presets';
|
||||
import { rendererBackground, rendererFeatures, rendererMap } from '../renderer';
|
||||
import { rendererBackground, rendererFeatures, rendererMap, rendererPhotos } from '../renderer';
|
||||
import { services } from '../services';
|
||||
import { uiInit } from '../ui/init';
|
||||
import { utilDetect } from '../util/detect';
|
||||
@@ -309,6 +309,11 @@ export function coreContext() {
|
||||
};
|
||||
|
||||
|
||||
/* Photos */
|
||||
var photos;
|
||||
context.photos = function() { return photos; };
|
||||
|
||||
|
||||
/* Presets */
|
||||
var presets;
|
||||
context.presets = function() { return presets; };
|
||||
@@ -501,6 +506,7 @@ export function coreContext() {
|
||||
connection = services.osm;
|
||||
background = rendererBackground(context);
|
||||
features = rendererFeatures(context);
|
||||
photos = rendererPhotos(context);
|
||||
presets = presetIndex(context);
|
||||
|
||||
if (services.maprules && utilStringQs(window.location.hash).maprules) {
|
||||
|
||||
@@ -2,4 +2,5 @@ export { rendererBackgroundSource } from './background_source';
|
||||
export { rendererBackground } from './background';
|
||||
export { rendererFeatures } from './features';
|
||||
export { rendererMap } from './map';
|
||||
export { rendererPhotos } from './photos';
|
||||
export { rendererTileLayer } from './tile_layer';
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
import _clone from 'lodash-es/clone';
|
||||
|
||||
import { dispatch as d3_dispatch } from 'd3-dispatch';
|
||||
|
||||
import { utilRebind } from '../util/rebind';
|
||||
|
||||
|
||||
export function rendererPhotos(context) {
|
||||
|
||||
var dispatch = d3_dispatch('change');
|
||||
|
||||
var _allPhotoTypes = ['flat', 'panoramic'];
|
||||
var _shownPhotoTypes = _clone(_allPhotoTypes);
|
||||
|
||||
function photos() {}
|
||||
|
||||
photos.allPhotoTypes = function() {
|
||||
return _allPhotoTypes;
|
||||
};
|
||||
|
||||
function showsLayer(id) {
|
||||
var layer = context.layers().layer(id);
|
||||
return layer && layer.supported() && layer.enabled();
|
||||
}
|
||||
|
||||
photos.shouldFilterByPhotoType = function() {
|
||||
return showsLayer('mapillary-images') ||
|
||||
(showsLayer('streetside') && showsLayer('openstreetcam-images'));
|
||||
};
|
||||
|
||||
photos.showsPhotoType = function(val) {
|
||||
if (!photos.shouldFilterByPhotoType()) return true;
|
||||
|
||||
return _shownPhotoTypes.indexOf(val) !== -1;
|
||||
};
|
||||
|
||||
photos.showsFlat = function() {
|
||||
return photos.showsPhotoType('flat');
|
||||
};
|
||||
|
||||
photos.showsPanoramic = function() {
|
||||
return photos.showsPhotoType('panoramic');
|
||||
};
|
||||
|
||||
photos.togglePhotoType = function(val) {
|
||||
var index = _shownPhotoTypes.indexOf(val);
|
||||
if (index !== -1) {
|
||||
_shownPhotoTypes.splice(index, 1);
|
||||
} else {
|
||||
_shownPhotoTypes.push(val);
|
||||
}
|
||||
dispatch.call('change', this);
|
||||
return photos;
|
||||
};
|
||||
|
||||
return utilRebind(photos, dispatch, 'on');
|
||||
}
|
||||
@@ -289,6 +289,11 @@ export default {
|
||||
},
|
||||
|
||||
|
||||
cachedImage: function(imageKey) {
|
||||
return _mlyCache.images.forImageKey[imageKey];
|
||||
},
|
||||
|
||||
|
||||
sequences: function(projection) {
|
||||
var viewport = projection.clipExtent();
|
||||
var min = [viewport[0][0], viewport[1][1]];
|
||||
|
||||
@@ -120,6 +120,46 @@ export function svgMapillaryImages(projection, context, dispatch) {
|
||||
return t;
|
||||
}
|
||||
|
||||
context.photos().on('change.mapillary_images', update);
|
||||
|
||||
function filterImages(images) {
|
||||
var showsPano = context.photos().showsPanoramic();
|
||||
var showsFlat = context.photos().showsFlat();
|
||||
if (!showsPano || !showsFlat) {
|
||||
images = images.filter(function(image) {
|
||||
if (image.pano) return showsPano;
|
||||
return showsFlat;
|
||||
});
|
||||
}
|
||||
return images;
|
||||
}
|
||||
|
||||
function filterSequences(sequences, service) {
|
||||
var showsPano = context.photos().showsPanoramic();
|
||||
var showsFlat = context.photos().showsFlat();
|
||||
if (!showsPano || !showsFlat) {
|
||||
sequences = sequences.filter(function(sequence) {
|
||||
if (sequence.properties.hasOwnProperty('pano')) {
|
||||
if (sequence.properties.pano) return showsPano;
|
||||
return showsFlat;
|
||||
} else {
|
||||
// if the sequence doesn't specify pano or not, search its images
|
||||
var cProps = sequence.properties.coordinateProperties;
|
||||
if (cProps && cProps.image_keys && cProps.image_keys.length > 0) {
|
||||
for (var index in cProps.image_keys) {
|
||||
var imageKey = cProps.image_keys[index];
|
||||
var image = service.cachedImage(imageKey);
|
||||
if (image && image.hasOwnProperty('pano')) {
|
||||
if (image.pano) return showsPano;
|
||||
return showsFlat;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
return sequences;
|
||||
}
|
||||
|
||||
function update() {
|
||||
var viewer = d3_select('#photoviewer');
|
||||
@@ -133,6 +173,9 @@ export function svgMapillaryImages(projection, context, dispatch) {
|
||||
var sequences = (service ? service.sequences(projection) : []);
|
||||
var images = (service && showMarkers ? service.images(projection) : []);
|
||||
|
||||
images = filterImages(images);
|
||||
sequences = filterSequences(sequences, service);
|
||||
|
||||
var traces = layer.selectAll('.sequences').selectAll('.sequence')
|
||||
.data(sequences, function(d) { return d.properties.key; });
|
||||
|
||||
|
||||
@@ -104,6 +104,8 @@ export function svgOpenstreetcamImages(projection, context, dispatch) {
|
||||
}
|
||||
|
||||
|
||||
context.photos().on('change.openstreetcam_images', update);
|
||||
|
||||
function update() {
|
||||
var viewer = d3_select('#photoviewer');
|
||||
var selected = viewer.empty() ? undefined : viewer.datum();
|
||||
@@ -113,8 +115,13 @@ export function svgOpenstreetcamImages(projection, context, dispatch) {
|
||||
var showViewfields = (z >= minViewfieldZoom);
|
||||
|
||||
var service = getService();
|
||||
var sequences = (service ? service.sequences(projection) : []);
|
||||
var images = (service && showMarkers ? service.images(projection) : []);
|
||||
var sequences = [];
|
||||
var images = [];
|
||||
|
||||
if (context.photos().showsFlat()) {
|
||||
sequences = (service ? service.sequences(projection) : []);
|
||||
images = (service && showMarkers ? service.images(projection) : []);
|
||||
}
|
||||
|
||||
var traces = layer.selectAll('.sequences').selectAll('.sequence')
|
||||
.data(sequences, function(d) { return d.properties.key; });
|
||||
|
||||
@@ -158,6 +158,8 @@ export function svgStreetside(projection, context, dispatch) {
|
||||
}
|
||||
|
||||
|
||||
context.photos().on('change.streetside', update);
|
||||
|
||||
/**
|
||||
* update().
|
||||
*/
|
||||
@@ -169,8 +171,13 @@ export function svgStreetside(projection, context, dispatch) {
|
||||
var showViewfields = (z >= minViewfieldZoom);
|
||||
var service = getService();
|
||||
|
||||
var sequences = (service ? service.sequences(projection) : []);
|
||||
var bubbles = (service && showMarkers ? service.bubbles(projection) : []);
|
||||
var sequences = [];
|
||||
var bubbles = [];
|
||||
|
||||
if (context.photos().showsPanoramic()) {
|
||||
sequences = (service ? service.sequences(projection) : []);
|
||||
bubbles = (service && showMarkers ? service.bubbles(projection) : []);
|
||||
}
|
||||
|
||||
var traces = layer.selectAll('.sequences').selectAll('.sequence')
|
||||
.data(sequences, function(d) { return d.properties.key; });
|
||||
|
||||
+68
-3
@@ -178,7 +178,7 @@ export function uiMapData(context) {
|
||||
var id = d.id;
|
||||
if (id === 'mapillary-images') id = 'mapillary';
|
||||
if (id === 'openstreetcam-images') id = 'openstreetcam';
|
||||
if (id === 'mapillary-signs') id = 'map_data.traffic_signs';
|
||||
if (id === 'mapillary-signs') id = 'photo_overlays.traffic_signs';
|
||||
return t(id.replace('-', '_') + '.title');
|
||||
});
|
||||
|
||||
@@ -191,6 +191,70 @@ export function uiMapData(context) {
|
||||
.property('checked', layerEnabled);
|
||||
}
|
||||
|
||||
function drawPhotoTypeItems(selection) {
|
||||
var data = context.photos().allPhotoTypes();
|
||||
|
||||
function typeEnabled(d) {
|
||||
return context.photos().showsPhotoType(d);
|
||||
}
|
||||
|
||||
var ul = selection
|
||||
.selectAll('.layer-list-photo-types')
|
||||
.data(context.photos().shouldFilterByPhotoType() ? [0] : []);
|
||||
|
||||
ul.exit()
|
||||
.remove();
|
||||
|
||||
ul = ul.enter()
|
||||
.append('ul')
|
||||
.attr('class', 'layer-list layer-list-photo-types')
|
||||
.merge(ul);
|
||||
|
||||
var li = ul.selectAll('.list-item-photo-types')
|
||||
.data(data);
|
||||
|
||||
li.exit()
|
||||
.remove();
|
||||
|
||||
var liEnter = li.enter()
|
||||
.append('li')
|
||||
.attr('class', function(d) {
|
||||
return 'list-item-photo-types list-item-' + d;
|
||||
});
|
||||
|
||||
var labelEnter = liEnter
|
||||
.append('label')
|
||||
.each(function(d) {
|
||||
d3_select(this)
|
||||
.call(tooltip()
|
||||
.title(t('photo_overlays.photo_type.' + d + '.tooltip'))
|
||||
.placement('top')
|
||||
);
|
||||
});
|
||||
|
||||
labelEnter
|
||||
.append('input')
|
||||
.attr('type', 'checkbox')
|
||||
.on('change', function(d) {
|
||||
context.photos().togglePhotoType(d);
|
||||
update();
|
||||
});
|
||||
|
||||
labelEnter
|
||||
.append('span')
|
||||
.text(function(d) {
|
||||
return t('photo_overlays.photo_type.' + d + '.title');
|
||||
});
|
||||
|
||||
|
||||
// Update
|
||||
li
|
||||
.merge(liEnter)
|
||||
.classed('active', typeEnabled)
|
||||
.selectAll('input')
|
||||
.property('checked', typeEnabled);
|
||||
}
|
||||
|
||||
|
||||
function drawOsmItems(selection) {
|
||||
var osmKeys = ['osm', 'notes'];
|
||||
@@ -605,7 +669,8 @@ export function uiMapData(context) {
|
||||
|
||||
function updatePhotoOverlays() {
|
||||
_photoOverlayContainer
|
||||
.call(drawPhotoItems);
|
||||
.call(drawPhotoItems)
|
||||
.call(drawPhotoTypeItems);
|
||||
}
|
||||
|
||||
function updateDataLayers() {
|
||||
@@ -759,7 +824,7 @@ export function uiMapData(context) {
|
||||
.append('div')
|
||||
.attr('class', 'map-data-photo-overlays')
|
||||
.call(uiDisclosure(context, 'photo_overlays', false)
|
||||
.title(t('map_data.photo_overlays'))
|
||||
.title(t('photo_overlays.title'))
|
||||
.content(renderPhotoOverlays)
|
||||
);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user