Legend

Creating A Legend From Elements

You can create a basic Legend by passing a vector of legend entries and a vector of labels, plus an optional title as the third argument.

The elements in the vector of legend entries can either be plot objects or LegendElements like LineElement, MarkerElement and PolyElement. Or they can be vectors of such objects that will be layered together as one.

Legend element attributes

The standard plot objects like Scatter or Lines have predefined conversions to MarkerElements and LineElements that copy the relevant plot attributes to the legend element. If an attribute has a vector-like value, it falls back to the scalar default of the legend. The legend defaults themselves are by default inherited from the main theme. For example, polystrokewidth of the legend falls back to patchstrokewidth of the main theme. In the following example, you can see that the legend for sca2 copies the :rect marker but not the vector-valued color.

using CairoMakie

f = Figure()

Axis(f[1, 1])

xs = 0:0.5:10
ys = sin.(xs)
lin = lines!(xs, ys, color = :blue)
sca = scatter!(xs, ys, color = :red)
sca2 = scatter!(xs, ys .+ 0.5, color = 1:length(xs), marker = :rect)

Legend(f[1, 2],
    [lin, sca, [lin, sca], sca2],
    ["a line", "some dots", "both together", "rect markers"])

f

Creating A Legend From An Axis

You can also create a Legend by passing it an axis object, like Axis, LScene or Scene. All plots that have a label attribute set will be put into the legend, in the order that they appear in the axis, and you can optionally pass a title as the third argument.

using CairoMakie

f = Figure()

ax = f[1, 1] = Axis(f)

lines!(0..15, sin, label = "sin", color = :blue)
lines!(0..15, cos, label = "cos", color = :red)
lines!(0..15, x -> -cos(x), label = "-cos", color = :green)

f[1, 2] = Legend(f, ax, "Trig Functions", framevisible = false)

f

With the keywords merge and unique you can control how plot objects with the same labels are treated. If merge is true, all plot objects with the same label will be layered on top of each other into one legend entry. If unique is true, all plot objects with the same plot type and label will be reduced to one occurrence.

using CairoMakie

f = Figure()

traces = cumsum(randn(10, 5), dims = 1)

for (i, (merge, unique)) in enumerate(
        Iterators.product([false, true], [false true]))

    axis = Axis(f[fldmod1(i, 2)...],
        title = "merge = $merge, unique = $unique")

    for trace in eachcol(traces)
        lines!(trace, label = "single", color = (:black, 0.2))
    end

    mu = vec(sum(traces, dims = 2) ./ 5)
    lines!(mu, label = "mean")
    scatter!(mu, label = "mean")

    axislegend(axis, merge = merge, unique = unique)

end

f

Multi-Bank Legend

You can control the number of banks with the nbanks attribute. Banks are columns when in vertical mode, and rows when in horizontal mode.

using CairoMakie

f = Figure()

Axis(f[1, 1])

xs = 0:0.1:10
lins = [lines!(xs, sin.(xs .+ 3v), color = RGBf(v, 0, 1-v)) for v in 0:0.1:1]

Legend(f[1, 2], lins, string.(1:length(lins)), nbanks = 3)

f

Legend Inside An Axis

The axislegend function is a quick way to add a legend to an Axis. You can pass a selected axis plus arguments which are forwarded to the Legend constructor, or the current axis is used by default. If you pass only a string, it's used as the title with the current axis.

The position can be set via a shortcut symbol, first halign (l, r, c) then valign (b, t, c), such as :lt for left, top and :cb for center bottom.

using CairoMakie

f = Figure()

ax = Axis(f[1, 1])

sc1 = scatter!(randn(10, 2), color = :red, label = "Red Dots")
sc2 = scatter!(randn(10, 2), color = :blue, label = "Blue Dots")
scatter!(randn(10, 2), color = :orange, label = "Orange Dots")
scatter!(randn(10, 2), color = :cyan, label = "Cyan Dots")

axislegend()

axislegend("Titled Legend", position = :lb)

axislegend(ax, [sc1, sc2], ["One", "Two"], "Selected Dots", position = :rb,
    orientation = :horizontal)

f

Alternatively, you can simply add a Legend to the same layout slot that an axis lives in. As long as the axis is bigger than the legend you can set the legend's tellheight and tellwidth to false and position it using the align variables. You can use the margin keyword to keep the legend from touching the axis spines.

using CairoMakie

haligns = [:left, :right, :center]
valigns = [:top, :bottom, :center]

f = Figure()

Axis(f[1, 1])

xs = 0:0.1:10
lins = [lines!(xs, sin.(xs .* i), color = color)
    for (i, color) in zip(1:3, [:red, :blue, :green])]

for (j, ha, va) in zip(1:3, haligns, valigns)
    Legend(
        f[1, 1], lins, ["Line $i" for i in 1:3],
        "$ha & $va",
        tellheight = false,
        tellwidth = false,
        margin = (10, 10, 10, 10),
        halign = ha, valign = va, orientation = :horizontal
    )
end

f

Creating Legend Entries Manually

Sometimes you might want to construct legend entries from scratch to have maximum control. So far you can use LineElements, MarkerElements or PolyElements. The attributes for these elements are the following (the [] parts can be left out when constructing these elements directly, but have to be fully written out for the attributes that the legend holds):

# LineElement
[line]points, [line]color, linestyle, linewidth

# MarkerElement
[marker]points, marker, markersize, [marker]color,
[marker]strokewidth, [marker]strokecolor

# PolyElement
[poly]points, [poly]color, [poly]strokewidth, [poly]strokecolor

The attributes linepoints, markerpoints and polypoints decide where in the legend entry patch rectangle the plot objects are placed. These values should be normalized to a 1 by 1 rectangle, and the final shape depends on the patchsize of the legend. For example, if you want wider line and poly markers, you could set the patchsize of the legend to (50, 30).

using CairoMakie

f = Figure()

Axis(f[1, 1])

elem_1 = [LineElement(color = :red, linestyle = nothing),
          MarkerElement(color = :blue, marker = 'x', markersize = 15,
          strokecolor = :black)]

elem_2 = [PolyElement(color = :red, strokecolor = :blue, strokewidth = 1),
          LineElement(color = :black, linestyle = :dash)]

elem_3 = LineElement(color = :green, linestyle = nothing,
        points = Point2f[(0, 0), (0, 1), (1, 0), (1, 1)])

elem_4 = MarkerElement(color = :blue, marker = 'π', markersize = 15,
        points = Point2f[(0.2, 0.2), (0.5, 0.8), (0.8, 0.2)])

elem_5 = PolyElement(color = :green, strokecolor = :black, strokewidth = 2,
        points = Point2f[(0, 0), (1, 0), (0, 1)])

Legend(f[1, 2],
    [elem_1, elem_2, elem_3, elem_4, elem_5],
    ["Line & Marker", "Poly & Line", "Line", "Marker", "Poly"],
    patchsize = (35, 35), rowgap = 10)

f

Horizontal Legend

In case you want the legend entries to be listed horizontally, set the orientation attribute to :horizontal. In this case the nbanks attribute refers to the number of rows instead of columns. To keep an adjacent axis from potentially shrinking to the width of the horizontal legend, set tellwidth = false and tellheight = true if you place the legend below or above the axis.

using CairoMakie

f = Figure()

Axis(f[1, 1])

xs = 0:0.5:10
ys = sin.(xs)
lin = lines!(xs, ys, color = :blue)
sca = scatter!(xs, ys, color = :red, markersize = 15)

Legend(f[1, 2], [lin, sca, lin], ["a line", "some dots", "line again"])

Legend(f[2, 1], [lin, sca, lin], ["a line", "some dots", "line again"],
    orientation = :horizontal, tellwidth = false, tellheight = true)

f

Multi-Group Legends

Sometimes a legend consists of multiple groups, for example in a plot where both marker size and color are varied and those properties need to be visualized separately, but still together in one legend. Each group's content is given as an array of elements and an array of labels, each within one collective array. You can shift the position of the titles relative to each group with the titleposition attribute, either :left or :top.

using CairoMakie

f = Figure()

Axis(f[1, 1])

markersizes = [5, 10, 15, 20]
colors = [:red, :green, :blue, :orange]

for ms in markersizes, color in colors
    scatter!(randn(5, 2), markersize = ms, color = color)
end

group_size = [MarkerElement(marker = :circle, color = :black,
    strokecolor = :transparent,
    markersize = ms) for ms in markersizes]

group_color = [PolyElement(color = color, strokecolor = :transparent)
    for color in colors]

legends = [Legend(f,
    [group_size, group_color],
    [string.(markersizes), string.(colors)],
    ["Size", "Color"]) for _ in 1:6]

f[1, 2:4] = legends[1:3]
f[2:4, 2] = legends[4:6]

for l in legends[4:6]
    l.orientation = :horizontal
    l.tellheight = true
    l.tellwidth = false
end

legends[2].titleposition = :left
legends[5].titleposition = :left

legends[3].nbanks = 2
legends[5].nbanks = 2
legends[6].nbanks = 2

f

Attributes

alignmode

Defaults to Inside()

The align mode of the legend in its parent GridLayout.

backgroundcolor

Defaults to :white

The background color of the legend.

bgcolor

Defaults to nothing

The background color of the legend. DEPRECATED - use backgroundcolor instead.

colgap

Defaults to 16

The gap between the label of one legend entry and the patch of the next.

framecolor

Defaults to :black

The color of the legend border.

framevisible

Defaults to true

Controls if the legend border is visible.

framewidth

Defaults to 1.0

The line width of the legend border.

gridshalign

Defaults to :center

The horizontal alignment of entry groups in their parent GridLayout.

gridsvalign

Defaults to :center

The vertical alignment of entry groups in their parent GridLayout.

groupgap

Defaults to 16

The gap between each group and the next.

halign

Defaults to :center

The horizontal alignment of the legend in its suggested bounding box.

height

Defaults to Auto()

The height setting of the legend.

label

Defaults to "undefined"

The default entry label.

labelcolor

Defaults to @inherit :textcolor :black

The color of the entry labels.

labelfont

Defaults to :regular

The font family of the entry labels.

labelhalign

Defaults to :left

The horizontal alignment of the entry labels.

labeljustification

Defaults to automatic

The justification of the label text. Default is automatic, which will set the justification to labelhalign.

labelsize

Defaults to @inherit :fontsize 16.0f0

The font size of the entry labels.

labelvalign

Defaults to :center

The vertical alignment of the entry labels.

linecolor

Defaults to theme(scene, :linecolor)

The default line color used for LineElements

linepoints

Defaults to [Point2f(0, 0.5), Point2f(1, 0.5)]

The default points used for LineElements in normalized coordinates relative to each label patch.

linestyle

Defaults to :solid

The default line style used for LineElements

linewidth

Defaults to theme(scene, :linewidth)

The default line width used for LineElements.

margin

Defaults to (0.0f0, 0.0f0, 0.0f0, 0.0f0)

The additional space between the legend and its suggested boundingbox.

marker

Defaults to theme(scene, :marker)

The default marker for MarkerElements

markercolor

Defaults to theme(scene, :markercolor)

The default marker color for MarkerElements

markerpoints

Defaults to [Point2f(0.5, 0.5)]

The default marker points used for MarkerElements in normalized coordinates relative to each label patch.

markersize

Defaults to theme(scene, :markersize)

The default marker size used for MarkerElements.

markerstrokecolor

Defaults to theme(scene, :markerstrokecolor)

The default marker stroke color used for MarkerElements.

markerstrokewidth

Defaults to theme(scene, :markerstrokewidth)

The default marker stroke width used for MarkerElements.

nbanks

Defaults to 1

The number of banks in which the legend entries are grouped. Columns if the legend is vertically oriented, otherwise rows.

orientation

Defaults to :vertical

The orientation of the legend (:horizontal or :vertical).

padding

Defaults to (10.0f0, 10.0f0, 8.0f0, 8.0f0)

The additional space between the legend content and the border.

patchcolor

Defaults to :transparent

The color of the patches containing the legend markers.

patchlabelgap

Defaults to 5

The gap between the patch and the label of each legend entry.

patchsize

Defaults to (20.0f0, 20.0f0)

The size of the rectangles containing the legend markers.

patchstrokecolor

Defaults to :transparent

The color of the border of the patches containing the legend markers.

patchstrokewidth

Defaults to 1.0

The line width of the border of the patches containing the legend markers.

polycolor

Defaults to theme(scene, :patchcolor)

The default poly color used for PolyElements.

polypoints

Defaults to [Point2f(0, 0), Point2f(1, 0), Point2f(1, 1), Point2f(0, 1)]

The default poly points used for PolyElements in normalized coordinates relative to each label patch.

polystrokecolor

Defaults to theme(scene, :patchstrokecolor)

The default poly stroke color used for PolyElements.

polystrokewidth

Defaults to theme(scene, :patchstrokewidth)

The default poly stroke width used for PolyElements.

rowgap

Defaults to 3

The gap between the entry rows.

tellheight

Defaults to automatic

Controls if the parent layout can adjust to this element's height

tellwidth

Defaults to automatic

Controls if the parent layout can adjust to this element's width

titlecolor

Defaults to @inherit :textcolor :black

The color of the legend titles

titlefont

Defaults to :bold

The font family of the legend group titles.

titlegap

Defaults to 8

The gap between each group title and its group.

titlehalign

Defaults to :center

The horizontal alignment of the legend group titles.

titleposition

Defaults to :top

The group title positions relative to their groups. Can be :top or :left.

titlesize

Defaults to @inherit :fontsize 16.0f0

The font size of the legend group titles.

titlevalign

Defaults to :center

The vertical alignment of the legend group titles.

titlevisible

Defaults to true

Controls if the legend titles are visible.

valign

Defaults to :center

The vertical alignment of the legend in its suggested bounding box.

width

Defaults to Auto()

The width setting of the legend.