diff --git a/css/app.css b/css/app.css index 521fcdf54..c1a3ef34c 100644 --- a/css/app.css +++ b/css/app.css @@ -660,43 +660,7 @@ button.save.has-count .count::before { bottom: 0; } -.mapillary-wrap { - position: absolute; - bottom: 30px; - width: 330px; - height: 250px; - padding: 5px; - background-color: #fff; -} -.mapillary-wrap.hidden { - visibility: hidden; -} - -.mapillary-wrap.temp button { - display: none; -} - -.mapillary-wrap .uil-ripple-css { - top: -22px; - left: -16px; -} -.mapillary-wrap button.thumb-hide { - border-radius: 0; - padding: 5px; - position: absolute; - right: 0; - top: 0; - z-index: 500; -} - -.mly-wrapper { - visibility: hidden; -} - -.mly-wrapper.active { - visibility: visible; -} .feature-list-pane .inspector-body { @@ -3292,3 +3256,44 @@ img.tile-removing { background: rgba(0, 0, 0, 0) url(img/iD-sprite.svg) no-repeat -300px -460px; margin: auto; } + +/* Mapillary +------------------------------------------------------- */ +.mapillary-wrap { + position: absolute; + bottom: 30px; + width: 330px; + height: 250px; + padding: 5px; + background-color: #fff; +} + +.mapillary-wrap.hidden { + visibility: hidden; +} + +.mapillary-wrap .uil-ripple-css { + top: -9px; + left: -15px; +} + +.mapillary-wrap .uil-ripple-css div { + top: 38px; +} + +.mapillary-wrap button.thumb-hide { + border-radius: 0; + padding: 5px; + position: absolute; + right: 0; + top: 0; + z-index: 500; +} + +.mly-wrapper { + visibility: hidden; +} + +.mly-wrapper.active { + visibility: visible; +} diff --git a/js/id/services/mapillary.js b/js/id/services/mapillary.js index 4183c339a..fe005b7cd 100644 --- a/js/id/services/mapillary.js +++ b/js/id/services/mapillary.js @@ -1,11 +1,10 @@ iD.services.mapillary = function() { var mapillary = {}, - dispatch = d3.dispatch('loadedImages', 'loadedSigns', 'loadedViewer'), + dispatch = d3.dispatch('loadedImages', 'loadedSigns'), apibase = 'https://a.mapillary.com/v2/', viewercss = 'https://npmcdn.com/mapillary-js@1.3.0/dist/mapillary-js.min.css', viewerjs = 'https://npmcdn.com/mapillary-js@1.3.0/dist/mapillary-js.min.js', clientId = 'NzNRM2otQkR2SHJzaXJmNmdQWVQ0dzo1ZWYyMmYwNjdmNDdlNmVi', - defaultKey = 'ytfE1_iD_N-jmHfTHkj1Ug', maxResults = 1000, tileZoom = 14; @@ -33,9 +32,7 @@ iD.services.mapillary = function() { }); } - function loadViewer(imageKey) { - imageKey = imageKey || defaultKey; - + function loadViewer() { // mapillary-wrap var wrap = d3.select('#content').selectAll('.mapillary-wrap') .data([0]); @@ -71,18 +68,25 @@ iD.services.mapillary = function() { .enter() .append('script') .attr('id', 'mapillary-viewerjs') - .attr('src', viewerjs) - .on('load', function() { - if (Mapillary) { - iD.services.mapillary.viewer = new Mapillary.Viewer('mly', clientId, imageKey, { - baseImageSize: 320, - imagePlane: false, - cover: false, - debug: false - }); - dispatch.loadedViewer(iD.services.mapillary.viewer); - } - }); + .attr('src', viewerjs); + } + + function initViewer(imageKey) { + if (Mapillary && imageKey) { + var opts = { + baseImageSize: 320, + cover: false, + cache: true, + debug: false, + imagePlane: true, + loading: true, + sequence: true + }; + + var viewer = new Mapillary.Viewer('mly', clientId, imageKey, opts); + viewer.on('loadingchanged', mapillary.viewerLoading); + iD.services.mapillary.viewer = viewer; + } } function abortRequest(i) { @@ -265,6 +269,7 @@ iD.services.mapillary = function() { }; mapillary.showViewer = function() { + loadViewer(); d3.select('#content') .selectAll('.mapillary-wrap') .classed('hidden', false) @@ -284,30 +289,54 @@ iD.services.mapillary = function() { d3.selectAll('.layer-mapillary-images .viewfield-group, .layer-mapillary-signs .icon-sign') .classed('selected', false); + iD.services.mapillary.image = null; + return mapillary; }; - mapillary.getImage = function() { + mapillary.viewerLoading = function(loading) { + var cover = d3.select('#content') + .selectAll('.mly-wrapper .Cover'); + + cover.classed('CoverDone', !loading); + + var button = cover.selectAll('.CoverButton') + .data(loading ? [0] : []); + + button.enter() + .append('div') + .attr('class', 'CoverButton') + .append('div') + .attr('class', 'uil-ripple-css') + .append('div'); + + button.exit() + .remove(); + }; + + mapillary.setViewerImage = function(imageKey) { + loadViewer(); + if (!iD.services.mapillary.viewer) { + initViewer(imageKey); + } else { + iD.services.mapillary.viewer.moveToKey(imageKey); + } + + return mapillary; + }; + + mapillary.getSelectedImage = function() { if (!iD.services.mapillary) return null; return iD.services.mapillary.image; }; - mapillary.setImage = function(image, fromViewer) { + mapillary.setSelectedImage = function(imageKey) { if (!iD.services.mapillary) return null; - if (iD.services.mapillary.image && iD.services.mapillary.image.key === image.key) return; - iD.services.mapillary.image = image; + iD.services.mapillary.image = imageKey; d3.selectAll('.layer-mapillary-images .viewfield-group, .layer-mapillary-signs .icon-sign') - .classed('selected', function(d) { return d.key === image.key; }); - - if (!fromViewer) { - if (iD.services.mapillary.viewer) { - iD.services.mapillary.viewer.moveToKey(image.key); - } else { - loadViewer(image.key); - } - } + .classed('selected', function(d) { return d.key === imageKey; }); }; mapillary.reset = function() { diff --git a/js/id/svg/mapillary_images.js b/js/id/svg/mapillary_images.js index 8bf13470d..edb382ab8 100644 --- a/js/id/svg/mapillary_images.js +++ b/js/id/svg/mapillary_images.js @@ -2,8 +2,8 @@ iD.svg.MapillaryImages = function(projection, context, dispatch) { var debouncedRedraw = _.debounce(function () { dispatch.change(); }, 1000), minZoom = 12, layer = d3.select(null), - pendingImg, - _mapillary; + _clicks = [], + _mapillary, _viewer; function init() { @@ -14,14 +14,21 @@ iD.svg.MapillaryImages = function(projection, context, dispatch) { function getMapillary() { if (iD.services.mapillary && !_mapillary) { - _mapillary = iD.services.mapillary() - .on('loadedImages', debouncedRedraw) - .on('loadedViewer', function(viewer) { - viewer.on('nodechanged', nodeChanged); - }); + _mapillary = iD.services.mapillary(); + _mapillary.on('loadedImages', debouncedRedraw); } else if (!iD.services.mapillary && _mapillary) { _mapillary = null; } + + if (iD.services.mapillary && !_viewer) { + _viewer = iD.services.mapillary.viewer; + if (_viewer) { + _viewer.on('nodechanged', nodeChanged); + } + } else if (!iD.services.mapillary && _viewer) { + _viewer = null; + } + return _mapillary; } @@ -65,34 +72,28 @@ iD.svg.MapillaryImages = function(projection, context, dispatch) { } function click(d) { - // if (pendingImg) return; // block clicks if waiting for previous marker - var mapillary = getMapillary(); - if (mapillary) { - // pendingImg = d.key; - context.map().centerEase(d.loc); - mapillary.setImage(d); - } + if (!mapillary) return; + + context.map().centerEase(d.loc); + mapillary.setSelectedImage(d.key); + mapillary.setViewerImage(d.key); + mapillary.showViewer(); + _clicks.push(d.key); } function nodeChanged(d) { var mapillary = getMapillary(); if (!mapillary) return; - var image = mapillary.getImage(); - if (!image) return; // user has never clicked a marker.. - - // if (pendingImg) { // waiting for a marker the user clicked on - // if (d.key !== pendingImg) return; - // pendingImg = null; // unblock clicks - // } else { - // // user didn't click a marker, this change came from the viewer. + var index = _clicks.indexOf(d.key); + if (index > -1) { + _clicks.splice(index, 1); + } else { // change initiated from the viewer controls.. var loc = d.apiNavImIm ? [d.apiNavImIm.lon, d.apiNavImIm.lat] : [d.latLon.lon, d.latLon.lat]; context.map().centerEase(loc); - mapillary.setImage(d, true); - // } - - mapillary.showViewer(); + mapillary.setSelectedImage(d.key); + } } function transform(d) { @@ -104,7 +105,7 @@ iD.svg.MapillaryImages = function(projection, context, dispatch) { function update() { var mapillary = getMapillary(), data = (mapillary ? mapillary.images(projection, layer.dimensions()) : []), - image = mapillary ? mapillary.getImage() : null; + imageKey = mapillary ? mapillary.getSelectedImage() : null; var markers = layer.selectAll('.viewfield-group') .data(data, function(d) { return d.key; }); @@ -113,7 +114,7 @@ iD.svg.MapillaryImages = function(projection, context, dispatch) { var enter = markers.enter() .append('g') .attr('class', 'viewfield-group') - .classed('selected', function(d) { return image && d.key === image.key; }) + .classed('selected', function(d) { return d.key === imageKey; }) .on('click', click); enter.append('path') diff --git a/js/id/svg/mapillary_signs.js b/js/id/svg/mapillary_signs.js index 92a2f949d..3fcd3e0b1 100644 --- a/js/id/svg/mapillary_signs.js +++ b/js/id/svg/mapillary_signs.js @@ -43,14 +43,16 @@ iD.svg.MapillarySigns = function(projection, context, dispatch) { var mapillary = getMapillary(); if (mapillary) { context.map().centerEase(d.loc); - mapillary.setImage(d); + mapillary.setSelectedImage(d.key); + mapillary.setViewerImage(d.key); + mapillary.showViewer(); } } function update() { var mapillary = getMapillary(), data = (mapillary ? mapillary.signs(projection, layer.dimensions()) : []), - image = mapillary ? mapillary.getImage() : null; + imageKey = mapillary ? mapillary.getSelectedImage() : null; var signs = layer.selectAll('.icon-sign') .data(data, function(d) { return d.key; }); @@ -61,7 +63,7 @@ iD.svg.MapillarySigns = function(projection, context, dispatch) { .attr('class', 'icon-sign') .attr('width', '32px') // for Firefox .attr('height', '32px') // for Firefox - .classed('selected', function(d) { return image && d.key === image.key; }) + .classed('selected', function(d) { return d.key === imageKey; }) .on('click', click); enter diff --git a/test/spec/services/mapillary.js b/test/spec/services/mapillary.js index b2a9dc79b..7294b26ee 100644 --- a/test/spec/services/mapillary.js +++ b/test/spec/services/mapillary.js @@ -360,10 +360,17 @@ describe('iD.services.mapillary', function() { }); }); - describe('#getImage', function() { + describe('#setSelectedImage', function() { + it('sets selected image', function() { + mapillary.setSelectedImage('foo'); + expect(iD.services.mapillary.image).to.eql('foo'); + }); + }); + + describe('#getSelectedImage', function() { it('gets selected image', function() { iD.services.mapillary.image = 'bar'; - expect(mapillary.getImage()).to.eql('bar'); + expect(mapillary.getSelectedImage()).to.eql('bar'); }); });