Conversation
…multiple legends
|
@alexshoe Can you document the full API for the new properties in this PR description? Basically just the info that's in the plot schema. |
|
@alexshoe Can you remove the image test? You can make a Codepen and link it in the PR description for testing purposes, but this feature doesn't require adding an image test to the test suite. |
| if(numClicks === 1 && legendObj.titleclick) { | ||
| const clickVal = Events.triggerHandler(gd, 'plotly_legendtitleclick', evtData); | ||
| if(clickVal === false) return; | ||
|
|
||
| legendObj._titleClickTimeout = setTimeout(function() { | ||
| if(gd._fullLayout) handleTitleClick(gd, legendObj, legendObj.titleclick); | ||
| }, doubleClickDelay); | ||
| } else if(numClicks === 2) { | ||
| if(legendObj._titleClickTimeout) clearTimeout(legendObj._titleClickTimeout); | ||
| gd._legendMouseDownTime = 0; | ||
|
|
||
| const dblClickVal = Events.triggerHandler(gd, 'plotly_legendtitledoubleclick', evtData); | ||
| if(dblClickVal !== false && legendObj.titledoubleclick) handleTitleClick(gd, legendObj, legendObj.titledoubleclick); | ||
| } | ||
| }); |
There was a problem hiding this comment.
@alexshoe Could some of the logic in the clickOrDoubleClick() function possibly be reused here? Seems like a fair amount of code duplication, although I'm sure there are some subtle differences.
| function positionTitleToggle(scrollBox, legendObj, legendId) { | ||
| const titleToggle = scrollBox.select('.' + legendId + 'titletoggle'); | ||
| if(!titleToggle.size()) return; | ||
|
|
||
| const side = legendObj.title.side || 'top'; | ||
| const bw = legendObj.borderwidth; | ||
| var x = bw; | ||
| const width = legendObj._titleWidth + 2 * constants.titlePad; | ||
| const height = legendObj._titleHeight + 2 * constants.titlePad; | ||
|
|
||
|
|
||
| if(side === 'top center') { | ||
| x = bw + 0.5 * (legendObj._width - 2 * bw - width); | ||
| } else if(side === 'top right') { | ||
| x = legendObj._width - bw - width; | ||
| } | ||
|
|
||
| titleToggle.attr({ x: x, y: bw, width: width, height: height }); | ||
| } |
There was a problem hiding this comment.
Hmm, likewise this function seems like it's duplicating a lot of the title placement logic. I don't think we should be referencing parameters like legendObj.title.side here at all. My feeling is that the titleToggle logic should be more parallel to the traceToggle placement logic.
| } | ||
| }; | ||
|
|
||
| exports.handleTitleClick = function handleTitleClick(gd, legendObj, mode) { |
There was a problem hiding this comment.
Also similar comment here to above -- check whether you can share some of this logic with the handleClick function to avoid TOO much code duplication
|
@robertcollar-kobold Pie charts do sometimes need unique logic compared to other trace types when it comes to legends, since pie chart legends contain one entry per data point rather than one entry per trace. That said, @alexshoe I can't see any reason why the Here's an example of a pie chart with multiple legends: Plot def: Details{
"data": [
{
"type": "pie",
"labels": ["a", "b", "c"],
"values": [3,5,4],
"showlegend": true,
"domain": {"row": 0, "column": 0},
},
{
"type": "pie",
"labels": ["d", "e", "f"],
"values": [1,3,7],
"legend": "legend2",
"showlegend": true,
"domain": {"row": 0, "column": 1},
},
],
"layout": {
"grid": {"rows": 1, "columns": 2},
"legend": {
"title": {"text": "Mylegend"},
"visible": true,
},
"legend2": {
"title": {"text": "Mylegend2"},
"visible": true,
"y": 0.15,
"itemclick": false,
},
}
}Image:
|
|
@alexshoe @robertcollar-kobold One question I just thought of, whose answer is not immediately obvious to me (but maybe it is to you): Should clicking the legend title toggle the visibility of all traces listed in the legend (i.e. those with Here's a mock to make it clearer. Each legend has one trace for which
Detailsvar plotDef = {
"data": [
{
"x": [1,2,3],
"y": [2,4,3],
"showlegend": false,
},
{
"x": [1,2,3],
"y": [3,5,4],
"showlegend": true,
},
{
"x": [2,4,6],
"y": [2,1,5],
"legend": "legend2",
"showlegend": true,
},
{
"x": [2,4,6],
"y": [3,2,6],
"yaxis": "yaxis2",
"legend": "legend2",
"showlegend": false,
},
],
"layout": {
"shapes": [
{
"type": "rect",
"x0": 1,
"x1": 2.5,
"y0": 4,
"y1": 5.5,
"line": {"color": "#FF0000"},
"showlegend": true,
},
{
"type": "rect",
"x0": 5,
"x1": 6,
"y0": 1,
"y1": 2,
"line": {"color": "#FF00FF"},
"legend": "legend2",
"showlegend": false,
},
],
"legend": {
"title": {"text": "Mylegend"},
"visible": true,
},
"legend2": {
"title": {"text": "Mylegend2"},
"visible": true,
"y": 0.25,
},
"yaxis2": {
"overlaying": "yaxis",
}
}
}; |
@emilykl I'll have to think about this a bit, but my first thought is that there must already be precedent with Okay update: I thought about it, and I would want a trace associated with, though not visible in, a legend to have its visibility be toggled when clicking on the legend title. I believe that's already the precedent today with For our use case, we might have multiple such multi-trace legend items under one legend, and clicking on the legend title should toggle the visibility of all associated traces, not just the ones for which |
@robertcollar-kobold Cool, yes, this makes sense to me and I think it's the most logically consistent behavior. |
|
@alexshoe Thanks for the updates, I'll take another pass tomorrow |


Description:
Adds the ability to click/double-click on legend titles to toggle legend visibility, making it easier to manage complex charts with multiple legends.
Example:
See this codepen for an interactive demo of this feature
New API:
legend.titleclick'toggle'|'toggleothers'|false'toggle'when there are multiple legends,falseotherwiselegend.titledoubleclick'toggle'|'toggleothers'|false'toggleothers'when there are multiple legends,falseotherwiseWhat each value for
titleclickandtitledoubleclickdoes:'toggle'toggles the visibility of all items in the clicked legend'toggleothers'toggles the visibility of all other legendsfalsedisables legend title double-click interactionsBug Fixes:
itemclickanditemdoubleclicksettings rather than inheriting them from the defaultlegend