Files
iD/modules/services/plane_photo.js
Mattia Pezzotti d1e5c2910c add date slider for street level photos, and more (#10394)
full list of enhancements:

* year slider to filter photos by freshness
* toggle active streetlevel layers with shortcut `shift+P`
* hfov, pitch and direction is now held between sequences and images as asked in #10392
* fix for #10361 (only panoramax)
* added tests and jsdoc
* add ticks for existing photos on slider
* general bug fixes
* rudimentary support for toDate in date slider (only when iD is started with a "to" date in the hash parameter: show a second slider to visualize and set the "to" date)

---------

Co-authored-by: Martin Raifer <martin@raifer.tech>
2025-03-18 21:09:37 +01:00

109 lines
2.5 KiB
JavaScript

import { dispatch as d3_dispatch } from 'd3-dispatch';
import { zoom as d3_zoom, zoomIdentity as d3_zoomIdentity } from 'd3-zoom';
import { utilSetTransform, utilRebind } from '../util';
const dispatch = d3_dispatch('viewerChanged');
let _photo;
let _imageWrapper;
let _planeWrapper;
let _imgZoom = d3_zoom()
.extent([[0, 0], [320, 240]])
.translateExtent([[0, 0], [320, 240]])
.scaleExtent([1, 15]);
function zoomPan (d3_event) {
let t = d3_event.transform;
_imageWrapper.call(utilSetTransform, t.x, t.y, t.k);
}
function loadImage (selection, path) {
return new Promise((resolve) => {
selection.attr('src', path);
selection.on('load', () => {
resolve(selection);
});
});
}
export default {
init: async function(context, selection) {
this.event = utilRebind(this, dispatch, 'on');
_planeWrapper = selection;
_planeWrapper.call(_imgZoom.on('zoom', zoomPan));
_imageWrapper = _planeWrapper
.append('div')
.attr('class', 'photo-frame plane-frame')
.classed('hide', true);
_photo = _imageWrapper
.append('img')
.attr('class', 'plane-photo');
context.ui().photoviewer.on('resize.plane', function(dimensions) {
_imgZoom
.extent([[0, 0], dimensions])
.translateExtent([[0, 0], dimensions]);
});
await Promise.resolve();
return this;
},
/**
* Shows the photo frame if hidden
* @param {*} context the HTML wrap of the frame
*/
showPhotoFrame: function (context) {
const isHidden = context.selectAll('.photo-frame.plane-frame.hide').size();
if (isHidden) {
context
.selectAll('.photo-frame:not(.plane-frame)')
.classed('hide', true);
context
.selectAll('.photo-frame.plane-frame')
.classed('hide', false);
}
return this;
},
/**
* Hides the photo frame if shown
* @param {*} context the HTML wrap of the frame
*/
hidePhotoFrame: function (context) {
context
.select('photo-frame.plane-frame')
.classed('hide', false);
return this;
},
/**
* Renders an image inside the frame
* @param {*} data the image data, it should contain an image_path attribute, a link to the actual image.
*/
selectPhoto: function (data) {
dispatch.call('viewerChanged');
loadImage(_photo, '');
loadImage(_photo, data.image_path)
.then(() => {
_planeWrapper.call(_imgZoom.transform, d3_zoomIdentity);
});
return this;
},
getYaw: function() {
return 0;
}
};