Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions draftlogs/7656_add.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- Add `colorlegend`, `sizelegend`, and `symbollegend` components for attribute-based legends [[#7656](https://github.com/plotly/plotly.js/pull/7656)]
171 changes: 171 additions & 0 deletions src/components/colorlegend/attributes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
'use strict';

var fontAttrs = require('../../plots/font_attributes');
var colorAttrs = require('../color/attributes');


module.exports = {
// not really a 'subplot' attribute container,
// but this is the flag we use to denote attributes that
// support colorlegend, colorlegend2, colorlegend3, ... counters
_isSubplotObj: true,

visible: {
valType: 'boolean',
dflt: true,
editType: 'legend',
description: 'Determines whether this color legend is visible.'
},

title: {
text: {
valType: 'string',
dflt: '',
editType: 'legend',
description: 'Sets the title of the color legend.'
},
font: fontAttrs({
editType: 'legend',
description: 'Sets the font for the color legend title.'
}),
side: {
valType: 'enumerated',
values: ['top', 'left', 'right'],
dflt: 'top',
editType: 'legend',
description: 'Determines the location of the legend title.'
},
editType: 'legend'
},

// Positioning (same pattern as legend)
x: {
valType: 'number',
dflt: 1.02,
editType: 'legend',
description: 'Sets the x position with respect to `xref`.'
},
xref: {
valType: 'enumerated',
values: ['container', 'paper'],
dflt: 'paper',
editType: 'legend',
description: 'Sets the container `x` refers to.'
},
xanchor: {
valType: 'enumerated',
values: ['auto', 'left', 'center', 'right'],
dflt: 'left',
editType: 'legend',
description: 'Sets the horizontal anchor.'
},
y: {
valType: 'number',
dflt: 1,
editType: 'legend',
description: 'Sets the y position with respect to `yref`.'
},
yref: {
valType: 'enumerated',
values: ['container', 'paper'],
dflt: 'paper',
editType: 'legend',
description: 'Sets the container `y` refers to.'
},
yanchor: {
valType: 'enumerated',
values: ['auto', 'top', 'middle', 'bottom'],
dflt: 'auto',
editType: 'legend',
description: 'Sets the vertical anchor.'
},

// Styling
bgcolor: {
valType: 'color',
editType: 'legend',
description: 'Sets the background color.'
},
bordercolor: {
valType: 'color',
dflt: colorAttrs.defaultLine,
editType: 'legend',
description: 'Sets the border color.'
},
borderwidth: {
valType: 'number',
min: 0,
dflt: 0,
editType: 'legend',
description: 'Sets the border width.'
},
font: fontAttrs({
editType: 'legend',
description: 'Sets the font for legend item text.'
}),

// Orientation
orientation: {
valType: 'enumerated',
values: ['v', 'h'],
dflt: 'v',
editType: 'legend',
description: 'Sets the orientation of the legend items.'
},

// Item sizing
itemsizing: {
valType: 'enumerated',
values: ['trace', 'constant'],
dflt: 'constant',
editType: 'legend',
description: [
'Determines if legend items symbols scale with their corresponding data values',
'or remain constant.'
].join(' ')
},
itemwidth: {
valType: 'number',
min: 30,
dflt: 30,
editType: 'legend',
description: 'Sets the width of the legend item symbols.'
},

// Behavior
itemclick: {
valType: 'enumerated',
values: ['toggle', 'toggleothers', false],
dflt: 'toggle',
editType: 'legend',
description: 'Determines the behavior on legend item click.'
},
itemdoubleclick: {
valType: 'enumerated',
values: ['toggle', 'toggleothers', false],
dflt: 'toggleothers',
editType: 'legend',
description: 'Determines the behavior on legend item double-click.'
},

// Continuous data binning
binning: {
valType: 'enumerated',
values: ['auto', 'discrete'],
dflt: 'auto',
editType: 'calc',
description: [
'For numeric color data, *auto* creates bins while',
'*discrete* treats each unique value as a category.'
].join(' ')
},
nbins: {
valType: 'integer',
min: 1,
dflt: 5,
editType: 'calc',
description: 'Sets the number of bins for continuous data when binning is *auto*.'
},

editType: 'legend'
};
7 changes: 7 additions & 0 deletions src/components/colorlegend/constants.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
'use strict';

module.exports = {
itemGap: 5,
textGap: 8,
padding: 10
};
94 changes: 94 additions & 0 deletions src/components/colorlegend/defaults.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
'use strict';

var Lib = require('../../lib');
var Template = require('../../plot_api/plot_template');
var attributes = require('./attributes');

module.exports = function colorlegendDefaults(layoutIn, layoutOut, fullData) {
var colorlegendIds = findColorlegendIds(fullData);

layoutOut._colorlegends = [];

for(var i = 0; i < colorlegendIds.length; i++) {
var id = colorlegendIds[i];
var containerIn = layoutIn[id] || {};
var containerOut = Template.newContainer(layoutOut, id);

handleColorlegendDefaults(containerIn, containerOut, layoutOut, id);

if(containerOut.visible) {
containerOut._id = id;
layoutOut._colorlegends.push(id);
}
}
};

function findColorlegendIds(fullData) {
var ids = [];

for(var i = 0; i < fullData.length; i++) {
var trace = fullData[i];
if(!trace.visible) continue;

var marker = trace.marker;
if(marker && marker.colorlegend) {
var id = marker.colorlegend;
if(ids.indexOf(id) === -1) {
ids.push(id);
}
}
}

return ids;
}

function handleColorlegendDefaults(containerIn, containerOut, layoutOut, id) {
function coerce(attr, dflt) {
return Lib.coerce(containerIn, containerOut, attributes, attr, dflt);
}

var visible = coerce('visible');
if(!visible) return;

// Title
coerce('title.text');
Lib.coerceFont(coerce, 'title.font', layoutOut.font);
coerce('title.side');

// Orientation first - affects positioning defaults
var orientation = coerce('orientation');

// Positioning - defaults depend on orientation
var isHorizontal = orientation === 'h';
if(isHorizontal) {
// Horizontal: top-right, outside the chart
coerce('x', 1.02);
coerce('xanchor', 'left');
coerce('y', 1);
coerce('yanchor', 'top');
} else {
// Vertical: right side of chart (default from attributes)
coerce('x');
coerce('xanchor');
coerce('y');
coerce('yanchor');
}
coerce('xref');
coerce('yref');

// Styling
coerce('bgcolor', layoutOut.paper_bgcolor);
coerce('bordercolor');
coerce('borderwidth');
Lib.coerceFont(coerce, 'font', layoutOut.font);
coerce('itemsizing');
coerce('itemwidth');

// Behavior
coerce('itemclick');
coerce('itemdoubleclick');

// Binning
coerce('binning');
coerce('nbins');
}
Loading