Add photo overlay filter options for hiding flat and pano photos (close #5433)

This commit is contained in:
Quincy Morgan
2019-03-14 14:24:21 -04:00
parent bb9e8d6d86
commit c65a4d038e
10 changed files with 225 additions and 14 deletions
+11 -3
View File
@@ -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
+15 -3
View File
@@ -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": {
+7 -1
View File
@@ -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) {
+1
View File
@@ -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';
+57
View File
@@ -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');
}
+5
View File
@@ -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]];
+43
View File
@@ -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; });
+9 -2
View File
@@ -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; });
+9 -2
View File
@@ -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
View File
@@ -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)
);