Skip to content

Commit

Permalink
plot: Support adding custom legend items
Browse files Browse the repository at this point in the history
fixes #9
  • Loading branch information
johannes-wolf committed Jun 23, 2024
1 parent 72960ea commit 56e7d49
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 7 deletions.
13 changes: 12 additions & 1 deletion src/plot.typ
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#import "/src/plot/bar.typ": add-bar
#import "/src/plot/errorbar.typ": add-errorbar
#import "/src/plot/mark.typ"
#import plot-legend: add-legend

#let default-colors = (blue, red, green, yellow, black)

Expand Down Expand Up @@ -261,6 +262,8 @@
// Create axes for data & annotations
let axis-dict = (:)
for d in data + annotations {
if "axes" not in d { continue }

for (i, name) in d.axes.enumerate() {
if not name in axis-dict {
axis-dict.insert(name, axes.axis(
Expand Down Expand Up @@ -304,6 +307,8 @@

// Prepare styles
for i in range(data.len()) {
if "style" not in data.at(i) { continue }

let style-base = plot-style
if type(style-base) == function {
style-base = (style-base)(i)
Expand Down Expand Up @@ -346,6 +351,8 @@

// Prepare
for i in range(data.len()) {
if "axes" not in data.at(i) { continue }

let (x, y) = data.at(i).axes.map(name => axis-dict.at(name))
let plot-ctx = make-ctx(x, y, size)

Expand All @@ -370,6 +377,8 @@
// Fill
if fill-below {
for d in data {
if "axes" not in d { continue }

let (x, y) = d.axes.map(name => axis-dict.at(name))
let plot-ctx = make-ctx(x, y, size)

Expand Down Expand Up @@ -420,6 +429,8 @@

// Stroke + Mark data
for d in data {
if "axes" not in d { continue }

let (x, y) = d.axes.map(name => axis-dict.at(name))
let plot-ctx = make-ctx(x, y, size)

Expand Down Expand Up @@ -487,7 +498,7 @@
mark: item.at("mark", default: none),
mark-size: item.at("mark-size", default: none),
mark-style: item.at("mark-style", default: none),
..item.style)
..item.at("style", default: (:)))
}
}, ..legend-style)
}
Expand Down
27 changes: 27 additions & 0 deletions src/plot/legend.typ
Original file line number Diff line number Diff line change
Expand Up @@ -203,3 +203,30 @@
"items.north-east", fill: style.fill, stroke: style.stroke, radius: style.radius)
})
})

/// Function for manually adding a legend item from within
/// a plot environment
///
/// - label (content): Legend label
/// - preview (auto,function): Legend preview function of the format `() => elements`.
/// The preview canvas bounds are between (0,0) and (1,1).
/// If set to `auto`, a straight line is drawn.
///
/// ```example
/// add-legend([Custom item], preview _ => {
/// draw.rect((0,0), (1,1)) // Draw a rect as preview
/// })
/// ```
#let add-legend(label, preview: auto) = {
assert(preview == auto or type(preview) == function,
message: "Expected auto or function, got " + repr(type(preview)))

return ((
type: "legend-item",
label: label,
style: (:),
axes: ("x", "y"),
) + if preview != auto {
(plot-legend-preview: _ => { preview() })
},)
}
Binary file modified tests/plot/legend/ref/1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
23 changes: 17 additions & 6 deletions tests/plot/legend/test.typ
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
#set page(width: auto, height: auto)
#import "/src/lib.typ": *
#import "/src/cetz.typ": *
#import "/tests/helper.typ": *
#import cetz: draw
#import cetz-plot: plot

#let dom = (domain: (0, 2 * calc.pi))
#let fn(x, offset: 0) = {calc.sin(x) + offset}

#for pos in ("north", "south", "west", "east",
"north-east", "north-west",
"south-east", "south-west",) {
pos = "legend." + pos
test-case({
import draw: *

Expand All @@ -26,7 +25,6 @@
#for pos in ("inner-north", "inner-south", "inner-west", "inner-east",
"inner-north-east", "inner-north-west",
"inner-south-east", "inner-south-west",) {
pos = "legend." + pos
test-case({
import draw: *

Expand Down Expand Up @@ -117,7 +115,7 @@
import draw: *

set-style(legend: (item: (preview: (width: .4), spacing: .7),
orientation: ltr, default-position: "legend.north"))
orientation: ltr, default-position: "north"))

plot.plot(size: (4, 2),
x-tick-step: none,
Expand All @@ -136,7 +134,7 @@
padding: .1,
stroke: black,
fill: white,
orientation: ltr, default-position: "legend.north"))
orientation: ltr, default-position: "north"))

plot.plot(size: (4, 2),
x-tick-step: none,
Expand Down Expand Up @@ -164,3 +162,16 @@
plot.add(samples: 10, ..dom, fn.with(offset: .2), mark: "|", style: (stroke: none), label: $ f_3(x) $)
})
})

#test-case({
plot.plot(size: (4,2), x-tick-step: none, y-tick-step: none, {
plot.add(domain: (0,1), x => x)
plot.add-legend([Custom 1])
plot.add-legend([Custom 2], preview: () => {
import draw: *
set-style(stroke: blue)
line((0,0), (1,1))
line((0,1), (1,0))
})
})
})

0 comments on commit 56e7d49

Please sign in to comment.