Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
172 changes: 109 additions & 63 deletions src/components/modebar/buttons.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -267,7 +267,7 @@ function handleCartesian(gd, ev) {
modeBarButtons.zoom3d = {
name: 'zoom3d',
title: 'Zoom',
attr: 'dragmode',
attr: 'scene.dragmode',
val: 'zoom',
icon: Icons.zoombox,
click: handleDrag3d
Expand All@@ -276,7 +276,7 @@ modeBarButtons.zoom3d = {
modeBarButtons.pan3d = {
name: 'pan3d',
title: 'Pan',
attr: 'dragmode',
attr: 'scene.dragmode',
val: 'pan',
icon: Icons.pan,
click: handleDrag3d
Expand All@@ -285,7 +285,7 @@ modeBarButtons.pan3d = {
modeBarButtons.orbitRotation = {
name: 'orbitRotation',
title: 'orbital rotation',
attr: 'dragmode',
attr: 'scene.dragmode',
val: 'orbit',
icon: Icons['3d_rotate'],
click: handleDrag3d
Expand All@@ -294,7 +294,7 @@ modeBarButtons.orbitRotation = {
modeBarButtons.tableRotation = {
name: 'tableRotation',
title: 'turntable rotation',
attr: 'dragmode',
attr: 'scene.dragmode',
val: 'turntable',
icon: Icons['z-axis'],
click: handleDrag3d
Expand All@@ -304,14 +304,16 @@ function handleDrag3d(gd, ev) {
var button = ev.currentTarget,
attr = button.getAttribute('data-attr'),
val = button.getAttribute('data-val') || true,
fullLayout = gd._fullLayout,
sceneIds = Plotly.Plots.getSubplotIds(fullLayout, 'gl3d'),
layoutUpdate = {};

layoutUpdate[attr] = val;
var parts = attr.split('.');

for(var i = 0; i < sceneIds.length; i++) {
layoutUpdate[sceneIds[i] + '.' + parts[1]] = val;
}

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

Expand All@@ -334,29 +336,19 @@ modeBarButtons.resetCameraLastSave3d = {
function handleCamera3d(gd, ev) {
var button = ev.currentTarget,
attr = button.getAttribute('data-attr'),
layout = gd.layout,
fullLayout = gd._fullLayout,
sceneIds = Plotly.Plots.getSubplotIds(fullLayout, 'gl3d');

for(var i = 0; i < sceneIds.length; i++) {
var sceneId = sceneIds[i],
sceneLayout = layout[sceneId],
fullSceneLayout = fullLayout[sceneId],
scene = fullSceneLayout._scene;

if(!sceneLayout || attr==='resetDefault') scene.setCameraToDefault();
if(attr==='resetDefault') scene.setCameraToDefault();
else if(attr === 'resetLastSave') {

var cameraPos = sceneLayout.camera;
if(cameraPos) scene.setCamera(cameraPos);
else scene.setCameraToDefault();
scene.setCamera(fullSceneLayout.camera);
}
}

/*
* TODO have a sceneLastTouched in _fullLayout to only
* update the camera of the scene last touched by the user
*/
}

modeBarButtons.hoverClosest3d = {
Expand All@@ -367,50 +359,58 @@ modeBarButtons.hoverClosest3d = {
toggle: true,
icon: Icons.tooltip_basic,
gravity: 'ne',
click: function(gd, ev) {
var button = ev.currentTarget,
val = JSON.parse(button.getAttribute('data-val')) || false,
fullLayout = gd._fullLayout,
sceneIds = Plotly.Plots.getSubplotIds(fullLayout, 'gl3d');

var axes = ['xaxis', 'yaxis', 'zaxis'],
spikeAttrs = ['showspikes', 'spikesides', 'spikethickness', 'spikecolor'];

// initialize 'current spike' object to be stored in the DOM
var currentSpikes = {},
axisSpikes = {},
layoutUpdate = {};

if(val) {
layoutUpdate = val;
button.setAttribute('data-val', JSON.stringify(null));
}
else {
layoutUpdate = {'allaxes.showspikes': false};

for(var i = 0; i < sceneIds.length; i++) {
var sceneId = sceneIds[i],
sceneLayout = fullLayout[sceneId],
sceneSpikes = currentSpikes[sceneId] = {};

// copy all the current spike attrs
for(var j = 0; j < 3; j++) {
var axis = axes[j];
axisSpikes = sceneSpikes[axis] = {};

for(var k = 0; k < spikeAttrs.length; k++) {
var spikeAttr = spikeAttrs[k];
axisSpikes[spikeAttr] = sceneLayout[axis][spikeAttr];
}
click: handleHover3d
};

function handleHover3d(gd, ev) {
var button = ev.currentTarget,
val = button._previousVal || false,
layout = gd.layout,
fullLayout = gd._fullLayout,
sceneIds = Plotly.Plots.getSubplotIds(fullLayout, 'gl3d');

var axes = ['xaxis', 'yaxis', 'zaxis'],
spikeAttrs = ['showspikes', 'spikesides', 'spikethickness', 'spikecolor'];

// initialize 'current spike' object to be stored in the DOM
var currentSpikes = {},
axisSpikes = {},
layoutUpdate = {};

if(val) {
layoutUpdate = Lib.extendDeep(layout, val);
button._previousVal = null;
}
else {
layoutUpdate = {
'allaxes.showspikes': false
};

for(var i = 0; i < sceneIds.length; i++) {
var sceneId = sceneIds[i],
sceneLayout = fullLayout[sceneId],
sceneSpikes = currentSpikes[sceneId] = {};

sceneSpikes.hovermode = sceneLayout.hovermode;
layoutUpdate[sceneId + '.hovermode'] = false;

// copy all the current spike attrs
for(var j = 0; j < 3; j++) {
var axis = axes[j];
axisSpikes = sceneSpikes[axis] = {};

for(var k = 0; k < spikeAttrs.length; k++) {
var spikeAttr = spikeAttrs[k];
axisSpikes[spikeAttr] = sceneLayout[axis][spikeAttr];
}
}

button.setAttribute('data-val', JSON.stringify(currentSpikes));
}

Plotly.relayout(gd, layoutUpdate);
button._previousVal = Lib.extendDeep({}, currentSpikes);
}
};

Plotly.relayout(gd, layoutUpdate);
}

modeBarButtons.zoomInGeo = {
name: 'zoomInGeo',
Expand DownExpand Up@@ -447,7 +447,7 @@ modeBarButtons.hoverClosestGeo = {
toggle: true,
icon: Icons.tooltip_basic,
gravity: 'ne',
click: handleGeo
click: toggleHover
};

function handleGeo(gd, ev) {
Expand All@@ -468,7 +468,6 @@ function handleGeo(gd, ev) {
geo.render();
}
else if(attr === 'reset') geo.zoomReset();
else if(attr === 'hovermode') geo.showHover = !geo.showHover;
}
}

Expand All@@ -494,7 +493,54 @@ modeBarButtons.hoverClosestPie = {
};

function toggleHover(gd) {
var newHover = gd._fullLayout.hovermode ? false : 'closest';
var fullLayout = gd._fullLayout;

var onHoverVal;
if(fullLayout._hasCartesian) {
onHoverVal = fullLayout._isHoriz ? 'y' : 'x';
}
else onHoverVal = 'closest';

var newHover = gd._fullLayout.hovermode ? false : onHoverVal;

Plotly.relayout(gd, 'hovermode', newHover);
}

// buttons when more then one plot types are present

modeBarButtons.toggleHover = {
name: 'toggleHover',
title: 'Toggle show closest data on hover',
attr: 'hovermode',
val: null,
toggle: true,
icon: Icons.tooltip_basic,
gravity: 'ne',
click: function(gd, ev) {
toggleHover(gd);

// the 3d hovermode update must come
// last so that layout.hovermode update does not
// override scene?.hovermode?.layout.
handleHover3d(gd, ev);
}
};

modeBarButtons.resetViews = {
name: 'resetViews',
title: 'Reset views',
icon: Icons.home,
click: function(gd, ev) {
var button = ev.currentTarget;

button.setAttribute('data-attr', 'zoom');
button.setAttribute('data-val', 'reset');
handleCartesian(gd, ev);

button.setAttribute('data-attr', 'resetLastSave');
handleCamera3d(gd, ev);

// N.B handleCamera3d also triggers a replot for
// geo subplots.
}
};
10 changes: 7 additions & 3 deletions src/components/modebar/index.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -9,9 +9,9 @@

'use strict';

var Plotly = require('../../plotly');
var d3 = require('d3');

var Lib = require('../../lib');
var Icons = require('../../../build/ploticon');


Expand DownExpand Up@@ -204,7 +204,11 @@ proto.updateActiveButton = function(buttonClicked) {
}
}
else {
button3.classed('active', fullLayout[dataAttr]===thisval);
var val = (dataAttr === null) ?
dataAttr :
Lib.nestedProperty(fullLayout, dataAttr).get();

button3.classed('active', val === thisval);
}

});
Expand DownExpand Up@@ -260,7 +264,7 @@ proto.removeAllButtons = function() {
};

proto.destroy = function() {
Plotly.Lib.removeElement(this.container.querySelector('.modebar'));
Lib.removeElement(this.container.querySelector('.modebar'));
};

function createModeBar(gd, buttons) {
Expand Down
Loading