diff --git a/css/60_photos.css b/css/60_photos.css index d1e84d79c..d7f4adff5 100644 --- a/css/60_photos.css +++ b/css/60_photos.css @@ -12,11 +12,46 @@ border-radius: 0; padding: 5px; position: absolute; - right: 0; - top: 0; - z-index: 48; + right: 5px; + top: 5px; + z-index: 50; } +#photoviewer button.resize-handle-xy { + border-radius: 0; + position: absolute; + top: 0; + right: 0; + z-index: 49; + cursor: nesw-resize; + height: 10px; + width: 10px; +} + +#photoviewer button.resize-handle-x { + border-radius: 0; + position: absolute; + top: 0; + right: 0; + bottom: 0; + z-index: 48; + cursor: ew-resize; + height: auto; + width: 5px; +} + +#photoviewer button.resize-handle-y { + border-radius: 0; + position: absolute; + top: 0; + right: 0; + z-index: 48; + cursor: ns-resize; + height: 5px; + width: 100%; +} + + .photo-wrapper, .photo-wrapper img { width: 100%; diff --git a/modules/services/mapillary.js b/modules/services/mapillary.js index baed207b8..01aefaae2 100644 --- a/modules/services/mapillary.js +++ b/modules/services/mapillary.js @@ -431,6 +431,13 @@ export default { // load mapillary signs sprite var defs = context.container().select('defs'); defs.call(svgDefs(context).addSprites, ['mapillary-sprite']); + + // Register viewer resize handler + context.ui().on('photoviewerResize', function() { + if (_mlyViewer) { + _mlyViewer.resize(); + } + }); }, diff --git a/modules/ui/init.js b/modules/ui/init.js index 7e1d134fc..e196d507f 100644 --- a/modules/ui/init.js +++ b/modules/ui/init.js @@ -2,6 +2,7 @@ import { event as d3_event, select as d3_select } from 'd3-selection'; +import { dispatch as d3_dispatch } from 'd3-dispatch'; import { d3keybinding as d3_keybinding } from '../lib/d3.keybinding.js'; @@ -13,6 +14,7 @@ import { modeBrowse } from '../modes'; import { services } from '../services'; import { svgDefs, svgIcon } from '../svg'; import { utilGetDimensions } from '../util/dimensions'; +import { utilRebind } from '../util'; import { uiAccount } from './account'; import { uiAttribution } from './attribution'; @@ -42,9 +44,46 @@ import { uiVersion } from './version'; import { uiZoom } from './zoom'; import { uiCmd } from './cmd'; +function buildResizeListener(target, eventName, dispatch, options) { + var resizeOnX = !!options.resizeOnX; + var resizeOnY = !!options.resizeOnY; + var startX; + var startY; + var startWidth; + var startHeight; + + function startResize() { + if (resizeOnX) { + target.style('width', (startWidth + d3_event.clientX - startX) + 'px'); + } + + if (resizeOnY) { + target.style('height', (startHeight + startY - d3_event.clientY) + 'px'); + } + + dispatch.call(eventName, target); + } + + function stopResize() { + d3_select(window) + .on('.' + eventName, null); + } + + return function initResize() { + startX = d3_event.clientX; + startY = d3_event.clientY; + startWidth = target.node().getBoundingClientRect().width; + startHeight = target.node().getBoundingClientRect().height; + + d3_select(window) + .on('mousemove.' + eventName, startResize, false) + .on('mouseup.' + eventName, stopResize, false); + }; +} export function uiInit(context) { var uiInitCounter = 0; + var dispatch = d3_dispatch('photoviewerResize'); function render(container) { @@ -256,6 +295,29 @@ export function uiInit(context) { .append('div') .call(svgIcon('#iD-icon-close')); + photoviewer + .append('button') + .attr('class', 'resize-handle-xy') + .on( + 'mousedown', + buildResizeListener(photoviewer, 'photoviewerResize', dispatch, { resizeOnX: true, resizeOnY: true }) + ); + + photoviewer + .append('button') + .attr('class', 'resize-handle-x') + .on( + 'mousedown', + buildResizeListener(photoviewer, 'photoviewerResize', dispatch, { resizeOnX: true }) + ); + + photoviewer + .append('button') + .attr('class', 'resize-handle-y') + .on( + 'mousedown', + buildResizeListener(photoviewer, 'photoviewerResize', dispatch, { resizeOnY: true }) + ); window.onbeforeunload = function() { return context.save(); @@ -370,5 +432,5 @@ export function uiInit(context) { ui.sidebar = uiSidebar(context); - return ui; + return utilRebind(ui, dispatch, 'on'); }