Skip to content

Commit 5da3791

Browse files
authored
Merge pull request #1883 from plotly/mapbox-doubleclick
Mapbox reset view back to initial
2 parents 9948af4 + a80934e commit 5da3791

File tree

6 files changed

+188
-34
lines changed

6 files changed

+188
-34
lines changed

src/components/modebar/buttons.js

+26
Original file line numberDiff line numberDiff line change
@@ -574,3 +574,29 @@ function setSpikelineVisibility(gd) {
574574

575575
return aobj;
576576
}
577+
578+
modeBarButtons.resetViewMapbox = {
579+
name: 'resetViewMapbox',
580+
title: 'Reset view',
581+
attr: 'reset',
582+
icon: Icons.home,
583+
click: function(gd) {
584+
var fullLayout = gd._fullLayout;
585+
var subplotIds = Plots.getSubplotIds(fullLayout, 'mapbox');
586+
var aObj = {};
587+
588+
for(var i = 0; i < subplotIds.length; i++) {
589+
var id = subplotIds[i];
590+
var subplotObj = fullLayout[id]._subplot;
591+
var viewInitial = subplotObj.viewInitial;
592+
var viewKeys = Object.keys(viewInitial);
593+
594+
for(var j = 0; j < viewKeys.length; j++) {
595+
var key = viewKeys[j];
596+
aObj[id + '.' + key] = viewInitial[key];
597+
}
598+
}
599+
600+
Plotly.relayout(gd, aObj);
601+
}
602+
};

src/components/modebar/manage.js

+3
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,9 @@ function getButtonGroups(gd, buttonsToRemove, buttonsToAdd) {
148148
else if(hasPie) {
149149
addGroup(['hoverClosestPie']);
150150
}
151+
else if(hasMapbox) {
152+
addGroup(['resetViewMapbox', 'toggleHover']);
153+
}
151154

152155
return appendButtonsToGroups(groups, buttonsToAdd);
153156
}

src/plots/mapbox/index.js

+10
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
var mapboxgl = require('mapbox-gl');
1313

14+
var Lib = require('../../lib');
1415
var Plots = require('../plots');
1516
var xmlnsNamespaces = require('../../constants/xmlns_namespaces');
1617

@@ -75,6 +76,15 @@ exports.plot = function plotMapbox(gd) {
7576
fullLayout[id]._subplot = mapbox;
7677
}
7778

79+
if(!mapbox.viewInitial) {
80+
mapbox.viewInitial = {
81+
center: Lib.extendFlat({}, opts.center),
82+
zoom: opts.zoom,
83+
bearing: opts.bearing,
84+
pitch: opts.pitch
85+
};
86+
}
87+
7888
mapbox.plot(subplotCalcData, fullLayout, gd._promises);
7989
}
8090
};

src/plots/mapbox/mapbox.js

+21-3
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ var constants = require('./constants');
1919
var layoutAttributes = require('./layout_attributes');
2020
var createMapboxLayer = require('./layers');
2121

22-
2322
function Mapbox(opts) {
2423
this.id = opts.id;
2524
this.gd = opts.gd;
@@ -111,6 +110,7 @@ proto.createMap = function(calcData, fullLayout, resolve, reject) {
111110
interactive: !self.isStatic,
112111
preserveDrawingBuffer: self.isStatic,
113112

113+
doubleClickZoom: false,
114114
boxZoom: false
115115
});
116116

@@ -186,6 +186,24 @@ proto.createMap = function(calcData, fullLayout, resolve, reject) {
186186

187187
map.on('dragstart', unhover);
188188
map.on('zoomstart', unhover);
189+
190+
map.on('dblclick', function() {
191+
var viewInitial = self.viewInitial;
192+
193+
map.setCenter(convertCenter(viewInitial.center));
194+
map.setZoom(viewInitial.zoom);
195+
map.setBearing(viewInitial.bearing);
196+
map.setPitch(viewInitial.pitch);
197+
198+
var viewNow = self.getView();
199+
200+
opts._input.center = opts.center = viewNow.center;
201+
opts._input.zoom = opts.zoom = viewNow.zoom;
202+
opts._input.bearing = opts.bearing = viewNow.bearing;
203+
opts._input.pitch = opts.pitch = viewNow.pitch;
204+
205+
gd.emit('plotly_doubleclick', null);
206+
});
189207
};
190208

191209
proto.updateMap = function(calcData, fullLayout, resolve, reject) {
@@ -488,8 +506,8 @@ proto.project = function(v) {
488506
proto.getView = function() {
489507
var map = this.map;
490508

491-
var mapCenter = map.getCenter(),
492-
center = { lon: mapCenter.lng, lat: mapCenter.lat };
509+
var mapCenter = map.getCenter();
510+
var center = { lon: mapCenter.lng, lat: mapCenter.lat };
493511

494512
return {
495513
center: center,

test/jasmine/tests/mapbox_test.js

+45-31
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ Plotly.setPlotConfig({
2323
mapboxAccessToken: MAPBOX_ACCESS_TOKEN
2424
});
2525

26-
2726
describe('mapbox defaults', function() {
2827
'use strict';
2928

@@ -788,31 +787,19 @@ describe('@noCI, mapbox plots', function() {
788787
.then(done);
789788
}, LONG_TIMEOUT_INTERVAL);
790789

791-
it('should respond drag / scroll interactions', function(done) {
792-
var relayoutCnt = 0,
793-
updateData;
790+
it('should respond drag / scroll / double-click interactions', function(done) {
791+
var relayoutCnt = 0;
792+
var doubleClickCnt = 0;
793+
var updateData;
794794

795795
gd.on('plotly_relayout', function(eventData) {
796796
relayoutCnt++;
797797
updateData = eventData;
798798
});
799799

800-
function _drag(p0, p1, cb) {
801-
var promise = _mouseEvent('mousemove', p0, noop).then(function() {
802-
return _mouseEvent('mousedown', p0, noop);
803-
}).then(function() {
804-
return _mouseEvent('mousemove', p1, noop);
805-
}).then(function() {
806-
// repeat mousemove to simulate long dragging motion
807-
return _mouseEvent('mousemove', p1, noop);
808-
}).then(function() {
809-
return _mouseEvent('mouseup', p1, noop);
810-
}).then(function() {
811-
return _mouseEvent('mouseup', p1, noop);
812-
}).then(cb);
813-
814-
return promise;
815-
}
800+
gd.on('plotly_doubleclick', function() {
801+
doubleClickCnt++;
802+
});
816803

817804
function assertLayout(center, zoom, opts) {
818805
var mapInfo = getMapInfo(gd),
@@ -838,8 +825,13 @@ describe('@noCI, mapbox plots', function() {
838825

839826
_drag(pointPos, p1, function() {
840827
expect(relayoutCnt).toEqual(1);
841-
assertLayout([-19.651, 13.751], 1.234, { withUpdateData: true });
828+
assertLayout([-19.651, 13.751], 1.234, {withUpdateData: true});
842829

830+
return _doubleClick(p1);
831+
})
832+
.then(function() {
833+
expect(doubleClickCnt).toBe(1, 'double click cnt');
834+
assertLayout([-4.710, 19.475], 1.234);
843835
})
844836
.catch(failTest)
845837
.then(done);
@@ -855,16 +847,6 @@ describe('@noCI, mapbox plots', function() {
855847
ptData = eventData.points[0];
856848
});
857849

858-
function _click(pos, cb) {
859-
var promise = _mouseEvent('mousemove', pos, noop).then(function() {
860-
return _mouseEvent('mousedown', pos, noop);
861-
}).then(function() {
862-
return _mouseEvent('click', pos, cb);
863-
});
864-
865-
return promise;
866-
}
867-
868850
_click(blankPos, function() {
869851
expect(ptData).toBe(undefined, 'not firing on blank points');
870852
})
@@ -991,6 +973,38 @@ describe('@noCI, mapbox plots', function() {
991973
}, MOUSE_DELAY);
992974
});
993975
}
976+
977+
function _click(pos, cb) {
978+
var promise = _mouseEvent('mousemove', pos, noop).then(function() {
979+
return _mouseEvent('mousedown', pos, noop);
980+
}).then(function() {
981+
return _mouseEvent('click', pos, cb);
982+
});
983+
984+
return promise;
985+
}
986+
987+
function _doubleClick(pos) {
988+
return _mouseEvent('dblclick', pos, noop);
989+
}
990+
991+
function _drag(p0, p1, cb) {
992+
var promise = _mouseEvent('mousemove', p0, noop).then(function() {
993+
return _mouseEvent('mousedown', p0, noop);
994+
}).then(function() {
995+
return _mouseEvent('mousemove', p1, noop);
996+
}).then(function() {
997+
// repeat mousemove to simulate long dragging motion
998+
return _mouseEvent('mousemove', p1, noop);
999+
}).then(function() {
1000+
return _mouseEvent('mouseup', p1, noop);
1001+
}).then(function() {
1002+
return _mouseEvent('mouseup', p1, noop);
1003+
}).then(cb);
1004+
1005+
return promise;
1006+
}
1007+
9941008
});
9951009

9961010
describe('@noCI, mapbox toImage', function() {

test/jasmine/tests/modebar_test.js

+83
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,44 @@ describe('ModeBar', function() {
270270
checkButtons(modeBar, buttons, 1);
271271
});
272272

273+
it('creates mode bar (mapbox version)', function() {
274+
var buttons = getButtons([
275+
['toImage', 'sendDataToCloud'],
276+
['pan2d'],
277+
['resetViewMapbox', 'toggleHover']
278+
]);
279+
280+
var gd = getMockGraphInfo();
281+
gd._fullLayout._basePlotModules = [{ name: 'mapbox' }];
282+
283+
manageModeBar(gd);
284+
var modeBar = gd._fullLayout._modeBar;
285+
286+
checkButtons(modeBar, buttons, 1);
287+
});
288+
289+
it('creates mode bar (mapbox + selected version)', function() {
290+
var buttons = getButtons([
291+
['toImage', 'sendDataToCloud'],
292+
['pan2d', 'select2d', 'lasso2d'],
293+
['resetViewMapbox', 'toggleHover']
294+
]);
295+
296+
var gd = getMockGraphInfo();
297+
gd._fullLayout._basePlotModules = [{ name: 'mapbox' }];
298+
gd._fullData = [{
299+
type: 'scatter',
300+
visible: true,
301+
mode: 'markers',
302+
_module: {selectPoints: true}
303+
}];
304+
305+
manageModeBar(gd);
306+
var modeBar = gd._fullLayout._modeBar;
307+
308+
checkButtons(modeBar, buttons, 1);
309+
});
310+
273311
it('creates mode bar (gl2d version)', function() {
274312
var buttons = getButtons([
275313
['toImage', 'sendDataToCloud'],
@@ -882,5 +920,50 @@ describe('ModeBar', function() {
882920

883921
});
884922

923+
describe('@noCI mapbox handlers', function() {
924+
it('button *resetViewMapbox* should reset the mapbox view attribute to their default', function(done) {
925+
var gd = createGraphDiv();
926+
927+
function _assert(centerLon, centerLat, zoom) {
928+
var mapboxLayout = gd._fullLayout.mapbox;
929+
930+
expect(mapboxLayout.center.lon).toBe(centerLon, 'center.lon');
931+
expect(mapboxLayout.center.lat).toBe(centerLat, 'center.lat');
932+
expect(mapboxLayout.zoom).toBe(zoom, 'zoom');
933+
}
934+
935+
Plotly.plot(gd, [{
936+
type: 'scattermapbox',
937+
lon: [10, 20, 30],
938+
lat: [10, 20, 30]
939+
}], {
940+
mapbox: {
941+
center: {lon: 10, lat: 10},
942+
zoom: 8
943+
}
944+
}, {
945+
mapboxAccessToken: require('@build/credentials.json').MAPBOX_ACCESS_TOKEN
946+
})
947+
.then(function() {
948+
_assert(10, 10, 8);
949+
950+
return Plotly.relayout(gd, {
951+
'mapbox.zoom': 10,
952+
'mapbox.center.lon': 30
953+
});
954+
})
955+
.then(function() {
956+
_assert(30, 10, 10);
957+
958+
var button = selectButton(gd._fullLayout._modeBar, 'resetViewMapbox');
959+
960+
button.isActive(false);
961+
button.click(false);
962+
_assert(10, 10, 8);
963+
button.isActive(false);
964+
})
965+
.then(done);
966+
});
967+
});
885968
});
886969
});

0 commit comments

Comments
 (0)