Skip to content

Commit

Permalink
Merge pull request #459 from plotly/surface-highlight
Browse files Browse the repository at this point in the history
Make surface contour highlights on hover toggleable
  • Loading branch information
etpinard committed Apr 26, 2016
2 parents c067cc7 + 07f318a commit 4f8f055
Show file tree
Hide file tree
Showing 9 changed files with 169 additions and 35 deletions.
35 changes: 28 additions & 7 deletions src/plot_api/plot_api.js
Original file line number Diff line number Diff line change
Expand Up @@ -659,25 +659,25 @@ function cleanAxRef(container, attr) {
}
}

// Make a few changes to the data right away
// before it gets used for anything
function cleanData(data, existingData) {
// make a few changes to the data right away
// before it gets used for anything

/*
* Enforce unique IDs
*/
// Enforce unique IDs
var suids = [], // seen uids --- so we can weed out incoming repeats
uids = data.concat(Array.isArray(existingData) ? existingData : [])
.filter(function(trace) { return 'uid' in trace; })
.map(function(trace) { return trace.uid; });

for(var tracei = 0; tracei < data.length; tracei++) {
var trace = data[tracei];
var i;

// assign uids to each trace and detect collisions.
if(!('uid' in trace) || suids.indexOf(trace.uid) !== -1) {
var newUid, i;
for(i=0; i<100; i++) {
var newUid;

for(i = 0; i < 100; i++) {
newUid = Lib.randstr(uids);
if(suids.indexOf(newUid)===-1) break;
}
Expand Down Expand Up @@ -765,6 +765,27 @@ function cleanData(data, existingData) {
if(cont.colorscale === 'YIOrRd') cont.colorscale = 'YlOrRd';
}

// fix typo in surface 'highlight*' definitions
if(trace.type === 'surface' && Lib.isPlainObject(trace.contours)) {
var dims = ['x', 'y', 'z'];

for(i = 0; i < dims.length; i++) {
var opts = trace.contours[dims[i]];

if(!Lib.isPlainObject(opts)) continue;

if(opts.highlightColor) {
opts.highlightcolor = opts.highlightColor;
delete opts.highlightColor;
}

if(opts.highlightWidth) {
opts.highlightwidth = opts.highlightWidth;
delete opts.highlightWidth;
}
}
}

// prune empty containers made before the new nestedProperty
if(emptyContainer(trace, 'line')) delete trace.line;
if('marker' in trace) {
Expand Down
4 changes: 2 additions & 2 deletions src/plots/gl3d/layout/axis_attributes.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

'use strict';


var Color = require('../../../components/color');
var axesAttrs = require('../../cartesian/layout_attributes');
var extendFlat = require('../../../lib/extend').extendFlat;

Expand Down Expand Up @@ -43,7 +43,7 @@ module.exports = {
spikecolor: {
valType: 'color',
role: 'style',
dflt: 'rgb(0,0,0)',
dflt: Color.defaultLine,
description: 'Sets the color of the spikes.'
},
showbackground: {
Expand Down
1 change: 1 addition & 0 deletions src/plots/gl3d/layout/axis_defaults.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@


'use strict';

var colorMix = require('tinycolor2').mix;

var Lib = require('../../../lib');
Expand Down
56 changes: 42 additions & 14 deletions src/traces/surface/attributes.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

'use strict';

var Color = require('../../components/color');
var colorscaleAttrs = require('../../components/colorscale/attributes');
var extendFlat = require('../../lib/extend').extendFlat;

Expand All @@ -19,8 +20,12 @@ function makeContourProjAttr(axLetter) {
role: 'info',
dflt: false,
description: [
'Sets whether or not the dynamic contours are projected',
'along the', axLetter, 'axis.'
'Determines whether or not these contour lines are projected',
'on the', axLetter, 'axis walls.',
'If `highlight` is set to *true* (the default), the projected',
'lines are shown on hover.',
'If `show` is set to *true*, the projected lines are shown',
'in permanence.'
].join(' ')
};
}
Expand All @@ -32,8 +37,8 @@ function makeContourAttr(axLetter) {
role: 'info',
dflt: false,
description: [
'Sets whether or not dynamic contours are shown along the',
axLetter, 'axis'
'Determines whether or not contour lines about the', axLetter,
'dimension are drawn.'
].join(' ')
},
project: {
Expand All @@ -44,36 +49,49 @@ function makeContourAttr(axLetter) {
color: {
valType: 'color',
role: 'style',
dflt: '#000'
dflt: Color.defaultLine,
description: 'Sets the color of the contour lines.'
},
usecolormap: {
valType: 'boolean',
role: 'info',
dflt: false
dflt: false,
description: [
'An alternate to *color*.',
'Determines whether or not the contour lines are colored using',
'the trace *colorscale*.'
].join(' ')
},
width: {
valType: 'number',
role: 'style',
min: 1,
max: 16,
dflt: 2
dflt: 2,
description: 'Sets the width of the contour lines.'
},
highlight: {
valType: 'boolean',
role: 'info',
dflt: false
dflt: true,
description: [
'Determines whether or not contour lines about the', axLetter,
'dimension are highlighted on hover.'
].join(' ')
},
highlightColor: {
highlightcolor: {
valType: 'color',
role: 'style',
dflt: '#000'
dflt: Color.defaultLine,
description: 'Sets the color of the highlighted contour lines.'
},
highlightWidth: {
highlightwidth: {
valType: 'number',
role: 'style',
min: 1,
max: 16,
dflt: 2
dflt: 2,
description: 'Sets the width of the highlighted contour lines.'
}
};
}
Expand Down Expand Up @@ -102,6 +120,7 @@ module.exports = {
'used for setting a color scale independent of `z`.'
].join(' ')
},

cauto: colorscaleAttrs.zauto,
cmin: colorscaleAttrs.zmin,
cmax: colorscaleAttrs.zmax,
Expand All @@ -110,6 +129,7 @@ module.exports = {
{dflt: false}),
reversescale: colorscaleAttrs.reversescale,
showscale: colorscaleAttrs.showscale,

contours: {
x: makeContourAttr('x'),
y: makeContourAttr('y'),
Expand All @@ -118,8 +138,15 @@ module.exports = {
hidesurface: {
valType: 'boolean',
role: 'info',
dflt: false
dflt: false,
description: [
'Determines whether or not a surface is drawn.',
'For example, set `hidesurface` to *false*',
'`contours.x.show` to *true* and',
'`contours.y.show` to *true* to draw a wire frame plot.'
].join(' ')
},

lighting: {
ambient: {
valType: 'number',
Expand Down Expand Up @@ -163,7 +190,8 @@ module.exports = {
role: 'style',
min: 0,
max: 1,
dflt: 1
dflt: 1,
description: 'Sets the opacity of the surface.'
},

_nestedModules: { // nested module coupling
Expand Down
10 changes: 4 additions & 6 deletions src/traces/surface/convert.js
Original file line number Diff line number Diff line change
Expand Up @@ -280,13 +280,11 @@ proto.update = function(data) {
}

var highlightEnable = [true, true, true];
var contourEnable = [true, true, true];
var axis = ['x', 'y', 'z'];

for(i = 0; i < 3; ++i) {
var contourParams = data.contours[axis[i]];
highlightEnable[i] = contourParams.highlight;
contourEnable[i] = contourParams.show;

params.showContour[i] = contourParams.show || contourParams.highlight;
if(!params.showContour[i]) continue;
Expand All @@ -301,6 +299,7 @@ proto.update = function(data) {
this.showContour[i] = true;
params.levels[i] = contourLevels[i];
surface.highlightColor[i] = params.contourColor[i] = str2RgbaArray(contourParams.color);

if(contourParams.usecolormap) {
surface.highlightTint[i] = params.contourTint[i] = 0;
}
Expand All @@ -313,18 +312,17 @@ proto.update = function(data) {
}

if(contourParams.highlight) {
params.dynamicColor[i] = str2RgbaArray(contourParams.highlightColor);
params.dynamicWidth[i] = contourParams.highlightWidth;
params.dynamicColor[i] = str2RgbaArray(contourParams.highlightcolor);
params.dynamicWidth[i] = contourParams.highlightwidth;
}
}

params.coords = coords;

surface.update(params);

surface.highlightEnable = highlightEnable;
surface.contourEnable = contourEnable;
surface.visible = data.visible;
surface.enableDynamic = highlightEnable;

surface.snapToData = true;

Expand Down
7 changes: 5 additions & 2 deletions src/traces/surface/defaults.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,8 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout
}

if(highlight) {
coerce(contourDim + '.highlightColor');
coerce(contourDim + '.highlightWidth');
coerce(contourDim + '.highlightcolor');
coerce(contourDim + '.highlightwidth');
}
}

Expand All @@ -94,6 +94,9 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout
mapLegacy(traceIn, 'zauto', 'cauto');
}

// TODO if contours.?.usecolormap are false and hidesurface is true
// the colorbar shouldn't be shown by default

colorscaleDefaults(
traceIn, traceOut, layout, coerce, {prefix: '', cLetter: 'c'}
);
Expand Down
Binary file modified test/image/baselines/gl3d_contour-lines.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
66 changes: 66 additions & 0 deletions test/jasmine/tests/plot_api_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -689,5 +689,71 @@ describe('Test plot api', function() {
Plotly.plot(gd, data);
expect(gd.data[0].marker.colorscale).toBe('YlOrRd');
});

it('should rename \'highlightColor\' to \'highlightcolor\')', function() {
var data = [{
type: 'surface',
contours: {
x: { highlightColor: 'red' },
y: { highlightcolor: 'blue' }
}
}, {
type: 'surface'
}, {
type: 'surface',
contours: false
}, {
type: 'surface',
contours: {
stuff: {},
x: false,
y: []
}
}];

spyOn(Plots.subplotsRegistry.gl3d, 'plot');

Plotly.plot(gd, data);

expect(Plots.subplotsRegistry.gl3d.plot).toHaveBeenCalled();

var contours = gd.data[0].contours;

expect(contours.x.highlightColor).toBeUndefined();
expect(contours.x.highlightcolor).toEqual('red');
expect(contours.y.highlightcolor).toEqual('blue');
expect(contours.z).toBeUndefined();

expect(gd.data[1].contours).toBeUndefined();
expect(gd.data[2].contours).toBe(false);
expect(gd.data[3].contours).toEqual({ stuff: {}, x: false, y: [] });
});

it('should rename \'highlightWidth\' to \'highlightwidth\')', function() {
var data = [{
type: 'surface',
contours: {
z: { highlightwidth: 'red' },
y: { highlightWidth: 'blue' }
}
}, {
type: 'surface'
}];

spyOn(Plots.subplotsRegistry.gl3d, 'plot');

Plotly.plot(gd, data);

expect(Plots.subplotsRegistry.gl3d.plot).toHaveBeenCalled();

var contours = gd.data[0].contours;

expect(contours.x).toBeUndefined();
expect(contours.y.highlightwidth).toEqual('blue');
expect(contours.z.highlightWidth).toBeUndefined();
expect(contours.z.highlightwidth).toEqual('red');

expect(gd.data[1].contours).toBeUndefined();
});
});
});
Loading

0 comments on commit 4f8f055

Please sign in to comment.