Rework legend element logic #4235
jkrumbiegel
started this conversation in
Ideas
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
This issue serves to record my current thinking on the issue of legend elements, @fatteneder you were also asking if something had been written down already, so here's a start.
Intro
When creating a
Legend
, there are different ways to specify the legend elements for a single entry:legendelements()
called on itMarkerElement
,LineElement
,PolyElement
or a vector of thoseFor
legendelements()
some overloads for specific plot types exist (Lines
,LineSegments
,Scatter
,Poly
,Violin
,BoxPlot
,CrossBar
,Density
,Band
). If a plot type has no overload, the algorithm traverses all child plots and stacks theirlegendelements
. This way, for example some custom recipe that uses aBand
withLines
on top would by default have a somewhat reasonable legend marker instead of erroring.When a legend element is created from a plot, certain visual attributes like
color
,markersize
andmarker
for aMarkerElement
are copied directly from the plot element.Problems
Some problems have appeared with the current approach:
Scatter
plot is fed toLegend
, themarkersize
in the legend will always be exactly that of the plot. This is the most common request for overrides , because scatter markers in the plot are usually smaller than would be appropriate for the legend marker.Series
where the child parts of this plot are presented viaget_plots
overload as single plots to theLegend
, but this approach only works because there are actually multiple plots insideSeries
which usually isn't the case with array-colored plots.Design goals
The new system should cover these points ideally
Scatter
legendLegend
-wide override mechanism, to choose via Theme whether allMarkerElement
s should have manually picked marker sizes or pick them from the plots they belong to. At least I can imagine it's annoying overriding the same setting many times.label
keyword rather than just aString
Design ideas
One way to address both override mechanism and multi-entries is to enhance the functionality of the
label
keyword. (Maybe it would have to be renamed tolegend
if it does more in the future).This is an idea for a multi-entry label keyword. The way to make each entry actually visually distinct is to pass override values for specific attributes that the legend element normally copies from the plot. In this case it would be the color, which can't be copied if it is array-valued as a single
MarkerElement
cannot have multiple colors.Note that this syntax is tied to this PR #2622 because it would allow to copy colormap and colorrange from an array-colored plot and then pick one of the colors via a scalar.
Overriding a value for a single entry would work just the same, for example to increase the
markersize
to make it legible:The problem with this idea is that it clashes with the composition fallback mechanism.
If an override keyword like
color
ormarkersize
refers to an attribute of the plot, then the user would have to know the attributes used in the internal components of the recipe they make a legend entry of. For example, a recipe might havecustom_markersize
as an attribute but internally theScatter
plot would usemarkersize
. But the user would not know that unless they were reading the source code.If however the keyword refers to an attribute of the legend element itself, like for the
MarkerElement
invoked byScatter
, this would clash with cases where multiple similar Elements are layered on top of each other. The user would not be able to say which of twoLineElement
s for example should have an increased line width.These concerns might seem a bit hypothetical as usually legend elements don't get super complex and a layering of two or more
MarkerElement
s would probably not be readable anyway, but I'd still prefer if the design didn't leave this ugly tail of corner cases but instead would error more and force the users to make clear decisions in cases of ambiguity.One more problem with the variant of specifying the attribute as it is used in the plot object, is that some aspects of the legend element will not map to the plot object at all. For example, the shape of the line used in a
LineElement
is not copied from aLines
plot (as there is no such attribute) so it would not be overrideable if only plot object keywords could be specified.Therefore, I tend to prefer the second option, where keywords related to
MarkerElement
,LineElement
andPolyElement
(and maybe some future additions to that list) are used. I think I already tried to make the set of attribute names for these three types disjoint (linecolor
andmarkercolor
instead of two times justcolor
when looking atMarkerElement
vsLineElement
for example), but if the names are not disjoint sets then the syntax must allow to clarify which type of element is meant when overriding. Justcolor
would be ambiguous if all three types had this.For plot objects that should automatically generate multiple legend entries, instead of overloading
get_plots
it might make more sense to add something likeget_label
(orget_legend
in case of a rename) which could return a vector of label strings plus settings as shown above if multiple entries are desired.Beta Was this translation helpful? Give feedback.
All reactions