Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 34438d7

Browse filesBrowse files
committed
Merge pull request plotly#258 from plotly/subplot-modebar
Subplot mode bars
2 parents 4221a2a + da5ea21 commit 34438d7
Copy full SHA for 34438d7

File tree

14 files changed

+953
-186
lines changed
Filter options

14 files changed

+953
-186
lines changed

‎src/components/modebar/buttons.js

Copy file name to clipboardExpand all lines: src/components/modebar/buttons.js
+109-63Lines changed: 109 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,7 @@ function handleCartesian(gd, ev) {
267267
modeBarButtons.zoom3d = {
268268
name: 'zoom3d',
269269
title: 'Zoom',
270-
attr: 'dragmode',
270+
attr: 'scene.dragmode',
271271
val: 'zoom',
272272
icon: Icons.zoombox,
273273
click: handleDrag3d
@@ -276,7 +276,7 @@ modeBarButtons.zoom3d = {
276276
modeBarButtons.pan3d = {
277277
name: 'pan3d',
278278
title: 'Pan',
279-
attr: 'dragmode',
279+
attr: 'scene.dragmode',
280280
val: 'pan',
281281
icon: Icons.pan,
282282
click: handleDrag3d
@@ -285,7 +285,7 @@ modeBarButtons.pan3d = {
285285
modeBarButtons.orbitRotation = {
286286
name: 'orbitRotation',
287287
title: 'orbital rotation',
288-
attr: 'dragmode',
288+
attr: 'scene.dragmode',
289289
val: 'orbit',
290290
icon: Icons['3d_rotate'],
291291
click: handleDrag3d
@@ -294,7 +294,7 @@ modeBarButtons.orbitRotation = {
294294
modeBarButtons.tableRotation = {
295295
name: 'tableRotation',
296296
title: 'turntable rotation',
297-
attr: 'dragmode',
297+
attr: 'scene.dragmode',
298298
val: 'turntable',
299299
icon: Icons['z-axis'],
300300
click: handleDrag3d
@@ -304,14 +304,16 @@ function handleDrag3d(gd, ev) {
304304
var button = ev.currentTarget,
305305
attr = button.getAttribute('data-attr'),
306306
val = button.getAttribute('data-val') || true,
307+
fullLayout = gd._fullLayout,
308+
sceneIds = Plotly.Plots.getSubplotIds(fullLayout, 'gl3d'),
307309
layoutUpdate = {};
308310

309-
layoutUpdate[attr] = val;
311+
var parts = attr.split('.');
312+
313+
for(var i = 0; i < sceneIds.length; i++) {
314+
layoutUpdate[sceneIds[i] + '.' + parts[1]] = val;
315+
}
310316

311-
/*
312-
* Dragmode will go through the relayout -> doplot -> scene.plot()
313-
* routine where the dragmode will be set in scene.plot()
314-
*/
315317
Plotly.relayout(gd, layoutUpdate);
316318
}
317319

@@ -334,29 +336,19 @@ modeBarButtons.resetCameraLastSave3d = {
334336
function handleCamera3d(gd, ev) {
335337
var button = ev.currentTarget,
336338
attr = button.getAttribute('data-attr'),
337-
layout = gd.layout,
338339
fullLayout = gd._fullLayout,
339340
sceneIds = Plotly.Plots.getSubplotIds(fullLayout, 'gl3d');
340341

341342
for(var i = 0; i < sceneIds.length; i++) {
342343
var sceneId = sceneIds[i],
343-
sceneLayout = layout[sceneId],
344344
fullSceneLayout = fullLayout[sceneId],
345345
scene = fullSceneLayout._scene;
346346

347-
if(!sceneLayout || attr==='resetDefault') scene.setCameraToDefault();
347+
if(attr === 'resetDefault') scene.setCameraToDefault();
348348
else if(attr === 'resetLastSave') {
349-
350-
var cameraPos = sceneLayout.camera;
351-
if(cameraPos) scene.setCamera(cameraPos);
352-
else scene.setCameraToDefault();
349+
scene.setCamera(fullSceneLayout.camera);
353350
}
354351
}
355-
356-
/*
357-
* TODO have a sceneLastTouched in _fullLayout to only
358-
* update the camera of the scene last touched by the user
359-
*/
360352
}
361353

362354
modeBarButtons.hoverClosest3d = {
@@ -367,50 +359,58 @@ modeBarButtons.hoverClosest3d = {
367359
toggle: true,
368360
icon: Icons.tooltip_basic,
369361
gravity: 'ne',
370-
click: function(gd, ev) {
371-
var button = ev.currentTarget,
372-
val = JSON.parse(button.getAttribute('data-val')) || false,
373-
fullLayout = gd._fullLayout,
374-
sceneIds = Plotly.Plots.getSubplotIds(fullLayout, 'gl3d');
375-
376-
var axes = ['xaxis', 'yaxis', 'zaxis'],
377-
spikeAttrs = ['showspikes', 'spikesides', 'spikethickness', 'spikecolor'];
378-
379-
// initialize 'current spike' object to be stored in the DOM
380-
var currentSpikes = {},
381-
axisSpikes = {},
382-
layoutUpdate = {};
383-
384-
if(val) {
385-
layoutUpdate = val;
386-
button.setAttribute('data-val', JSON.stringify(null));
387-
}
388-
else {
389-
layoutUpdate = {'allaxes.showspikes': false};
390-
391-
for(var i = 0; i < sceneIds.length; i++) {
392-
var sceneId = sceneIds[i],
393-
sceneLayout = fullLayout[sceneId],
394-
sceneSpikes = currentSpikes[sceneId] = {};
395-
396-
// copy all the current spike attrs
397-
for(var j = 0; j < 3; j++) {
398-
var axis = axes[j];
399-
axisSpikes = sceneSpikes[axis] = {};
400-
401-
for(var k = 0; k < spikeAttrs.length; k++) {
402-
var spikeAttr = spikeAttrs[k];
403-
axisSpikes[spikeAttr] = sceneLayout[axis][spikeAttr];
404-
}
362+
click: handleHover3d
363+
};
364+
365+
function handleHover3d(gd, ev) {
366+
var button = ev.currentTarget,
367+
val = button._previousVal || false,
368+
layout = gd.layout,
369+
fullLayout = gd._fullLayout,
370+
sceneIds = Plotly.Plots.getSubplotIds(fullLayout, 'gl3d');
371+
372+
var axes = ['xaxis', 'yaxis', 'zaxis'],
373+
spikeAttrs = ['showspikes', 'spikesides', 'spikethickness', 'spikecolor'];
374+
375+
// initialize 'current spike' object to be stored in the DOM
376+
var currentSpikes = {},
377+
axisSpikes = {},
378+
layoutUpdate = {};
379+
380+
if(val) {
381+
layoutUpdate = Lib.extendDeep(layout, val);
382+
button._previousVal = null;
383+
}
384+
else {
385+
layoutUpdate = {
386+
'allaxes.showspikes': false
387+
};
388+
389+
for(var i = 0; i < sceneIds.length; i++) {
390+
var sceneId = sceneIds[i],
391+
sceneLayout = fullLayout[sceneId],
392+
sceneSpikes = currentSpikes[sceneId] = {};
393+
394+
sceneSpikes.hovermode = sceneLayout.hovermode;
395+
layoutUpdate[sceneId + '.hovermode'] = false;
396+
397+
// copy all the current spike attrs
398+
for(var j = 0; j < 3; j++) {
399+
var axis = axes[j];
400+
axisSpikes = sceneSpikes[axis] = {};
401+
402+
for(var k = 0; k < spikeAttrs.length; k++) {
403+
var spikeAttr = spikeAttrs[k];
404+
axisSpikes[spikeAttr] = sceneLayout[axis][spikeAttr];
405405
}
406406
}
407-
408-
button.setAttribute('data-val', JSON.stringify(currentSpikes));
409407
}
410408

411-
Plotly.relayout(gd, layoutUpdate);
409+
button._previousVal = Lib.extendDeep({}, currentSpikes);
412410
}
413-
};
411+
412+
Plotly.relayout(gd, layoutUpdate);
413+
}
414414

415415
modeBarButtons.zoomInGeo = {
416416
name: 'zoomInGeo',
@@ -447,7 +447,7 @@ modeBarButtons.hoverClosestGeo = {
447447
toggle: true,
448448
icon: Icons.tooltip_basic,
449449
gravity: 'ne',
450-
click: handleGeo
450+
click: toggleHover
451451
};
452452

453453
function handleGeo(gd, ev) {
@@ -468,7 +468,6 @@ function handleGeo(gd, ev) {
468468
geo.render();
469469
}
470470
else if(attr === 'reset') geo.zoomReset();
471-
else if(attr === 'hovermode') geo.showHover = !geo.showHover;
472471
}
473472
}
474473

@@ -494,7 +493,54 @@ modeBarButtons.hoverClosestPie = {
494493
};
495494

496495
function toggleHover(gd) {
497-
var newHover = gd._fullLayout.hovermode ? false : 'closest';
496+
var fullLayout = gd._fullLayout;
497+
498+
var onHoverVal;
499+
if(fullLayout._hasCartesian) {
500+
onHoverVal = fullLayout._isHoriz ? 'y' : 'x';
501+
}
502+
else onHoverVal = 'closest';
503+
504+
var newHover = gd._fullLayout.hovermode ? false : onHoverVal;
498505

499506
Plotly.relayout(gd, 'hovermode', newHover);
500507
}
508+
509+
// buttons when more then one plot types are present
510+
511+
modeBarButtons.toggleHover = {
512+
name: 'toggleHover',
513+
title: 'Toggle show closest data on hover',
514+
attr: 'hovermode',
515+
val: null,
516+
toggle: true,
517+
icon: Icons.tooltip_basic,
518+
gravity: 'ne',
519+
click: function(gd, ev) {
520+
toggleHover(gd);
521+
522+
// the 3d hovermode update must come
523+
// last so that layout.hovermode update does not
524+
// override scene?.hovermode?.layout.
525+
handleHover3d(gd, ev);
526+
}
527+
};
528+
529+
modeBarButtons.resetViews = {
530+
name: 'resetViews',
531+
title: 'Reset views',
532+
icon: Icons.home,
533+
click: function(gd, ev) {
534+
var button = ev.currentTarget;
535+
536+
button.setAttribute('data-attr', 'zoom');
537+
button.setAttribute('data-val', 'reset');
538+
handleCartesian(gd, ev);
539+
540+
button.setAttribute('data-attr', 'resetLastSave');
541+
handleCamera3d(gd, ev);
542+
543+
// N.B handleCamera3d also triggers a replot for
544+
// geo subplots.
545+
}
546+
};

‎src/components/modebar/index.js

Copy file name to clipboardExpand all lines: src/components/modebar/index.js
+7-3Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@
99

1010
'use strict';
1111

12-
var Plotly = require('../../plotly');
1312
var d3 = require('d3');
1413

14+
var Lib = require('../../lib');
1515
var Icons = require('../../../build/ploticon');
1616

1717

@@ -204,7 +204,11 @@ proto.updateActiveButton = function(buttonClicked) {
204204
}
205205
}
206206
else {
207-
button3.classed('active', fullLayout[dataAttr]===thisval);
207+
var val = (dataAttr === null) ?
208+
dataAttr :
209+
Lib.nestedProperty(fullLayout, dataAttr).get();
210+
211+
button3.classed('active', val === thisval);
208212
}
209213

210214
});
@@ -260,7 +264,7 @@ proto.removeAllButtons = function() {
260264
};
261265

262266
proto.destroy = function() {
263-
Plotly.Lib.removeElement(this.container.querySelector('.modebar'));
267+
Lib.removeElement(this.container.querySelector('.modebar'));
264268
};
265269

266270
function createModeBar(gd, buttons) {

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.