Cartesian product legend

Is it possible to have legend with

      red   green   blue   orange
05     
10
15
20

with sized colored images in each cell and row/column labels?


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]

legend = Legend(f[2,1],
[MarkerElement(marker=:circle, markersize=size, color=color, strokecolor=:transparent)
 for size in markersizes for color in colors])


f

ERROR: LoadError: MethodError: no method matching layoutable(::Type{Legend}, ::Figure, ::Array{MarkerElement,1})

2 Likes

I guess the answer is that that is not implemented, but you could as a workaround create
an inset plot without tick marks and labels, and put your axis labels and dots to mimic that.

You can kind of recreate some of the legend code. Make a gridlayout, put labels in it, add boxes in which you plot legend elements. The empty Attributes() is usually populated using the legend theme, but if you pass all attributes yourself you don’t need it.

using CairoMakie

f = Figure()

Axis(f[1, 1])

gl = f[1, 2] = GridLayout(tellheight = false)
for (i, label) in pairs(["a", "b", "c"])
    gl[1, i+1] = Label(f, label)
end

for (i, label) in pairs(["x", "y", "z"])
    gl[i+1, 1] = Label(f, label)
end

for i in 2:4, j in 2:4
    
    b = gl[i, j] = Box(f,
        color = :transparent,
        width = 30,
        height = 30,
        strokecolor = :transparent)

    MakieLayout.legendelement_plots!(
        f.scene,
        MarkerElement(
            color = rand(RGBf0),
            markersize = rand(10:20),
            marker = :circle,
            strokewidth = 0,
            strokecolor = :black,
            markerpoints = [Point2f0(0.5, 0.5)]
        ),
        b.layoutobservables.computedbbox,
        Attributes()
    )
end

f

2 Likes

Thanks, that helped.

using CairoMakie

f = Figure()

Axis(f[1, 1])


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

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

gl = f[2,1] = GridLayout(tellwidth = false)


gl[1,2:6] = Label(f, "Color",)
for (i, label) in pairs(string.(colors))
    gl[2, i+2] = Label(f, label)
end

gl[2:6,1] = Label(f, "Size")
for (i, label) in pairs(string.(markersizes))
    gl[i+2, 2] = Label(f, label,)
end

for (ic, c) in enumerate(colors), (im, m) in enumerate(markersizes)

    b = gl[im+2, ic+2] = Box(f,
        color = :transparent,
        width = 30,
        height = 30,
        strokecolor = :transparent)

    MakieLayout.legendelement_plots!(
        f.scene,
        MarkerElement(
            color = c,
            markersize = m,
            marker = :circle,
            strokewidth = 0,
            strokecolor = :transparent,
            markerpoints = [Point2f0(0.5, 0.5)]
        ),
        b.layoutobservables.computedbbox,
        Attributes()
    )
end

f

3 Likes