In How to Reproduce an Image in Typst? - #7 by Andrew, I had to set stroke
to black
for grid, plot, scatter, and rect, because default is not black. Is there a magic way to set everything to black or some global-like setting that will do the same? I don’t want to trash the definition of things with such trivial styling that I want to be default anyway. Gotta keep it short and pretty.
Hi, the plot types like plot, scatter (although currently not rect because this is sortof extra − this can be discussed though) inherit their default stroke from lq.style
. However, this one can currently only be set
within style cycles, see Using style cycles − Lilaq. This is because of the lack of user-definable types in Typst. In the future, you will be able to write set lq.style(stroke: black)
.
The grid is separate and will always need to be set individually. You can read this tutorial for ideas on separating styling from content: Styling and themes − Lilaq.
Scatter doesn’t inherit it. Also, it’s not only within style cycles.
Code
#import "@preview/lilaq:0.2.0" as lq
#let f(x) = calc.tan(20deg) * x + 34
#show: lq.set-tick(stroke: 0pt)
#show: lq.set-grid(stroke: black)
#set lq.style(stroke: black, fill: white)
#let lq-rect = lq.rect.with(stroke: black, fill: white)
#let y-max = 400
#let x-max = 640
#lq.diagram(
width: 15cm,
height: 15cm * y-max / x-max,
ylim: (0, y-max),
xlim: (0, x-max),
yaxis: (ticks: range(y-max + 1, step: 80), subticks: 1),
xaxis: (ticks: range(x-max + 1, step: 80), subticks: 1),
grid: (stroke-sub: 0.5pt),
let xs = lq.linspace(0, 590),
lq.plot(xs, xs.map(f), stroke: 0.5pt, mark: none),
let xs = (100, 200, 300, 400),
lq.scatter(xs, xs.map(f), size: 6mm),
lq.scatter((320,), (138,), size: 3mm),
lq-rect(400, 320, width: 160, height: 80),
)
Scatter doesn’t inherit it.
Oh yeah right, it’s because scatter has no lines/shapes. Marks and their fill/stroke are controlled by lq.mark
in that context. This behaviour is the result of a very long process − there are a few tradeoffs.
Also, it’s not only within style cycles.
Well, yes but style is just an alias for std.circle
so circles will be affected then for other things outside the diagram if you don’t scope it. But yes, it technically works, I forgot about that.
I don’t understand how to use this mark thing to set stroke
/color
for scatter. I think it’s broken or something. And how would you style an ellipse?
It is indeed broken for lq.scatter
and I just fixed it on main. The ellipse cannot be styled globally as of now. It belongs to the set of primitive drawing functions and they don’t obey the style cycle (yet).
We can however change this behaviour. I feel like ellipse, rect etc should still not take part in the style cycle but they could respond to changes in lq.style
.
Hmm, I still can’t style it with the global set rule, but with cycle
it does work.
Code
#import "@local/lilaq:0.3.0" as lq
// #import "@preview/lilaq:0.2.0" as lq
#let f(x) = calc.tan(20deg) * x + 34
#set lq.style(stroke: black, fill: white) // Now it's not needed with cycle.
#set lq.mark(stroke: black, fill: white) // Doesn't work.
#show: lq.set-tick(stroke: 0pt)
#show: lq.set-grid(stroke: black)
#show: lq.set-diagram(cycle: (
it => {
set lq.mark(stroke: black, fill: white)
it
},
))
#let lq-rect = lq.rect.with(stroke: black, fill: white)
#let y-max = 400
#let x-max = 640
#lq.diagram(
width: 15cm,
height: 15cm * y-max / x-max,
ylim: (0, y-max),
xlim: (0, x-max),
yaxis: (ticks: range(y-max + 1, step: 80), subticks: 1),
xaxis: (ticks: range(x-max + 1, step: 80), subticks: 1),
grid: (stroke-sub: 0.5pt),
let xs = lq.linspace(0, 590),
lq.plot(xs, xs.map(f), stroke: 0.5pt, mark: none),
let xs = (100, 200, 300, 400),
lq.scatter(xs, xs.map(f), size: 6mm),
lq.scatter((320,), (138,), size: 3mm),
lq-rect(400, 320, width: 160, height: 80),
)
For some reason, adding empty cycle closure sets plot line color to black. Is this a backup style? Though if I use set lq.style(stroke: green)
, then it does still change the plot line color. So… is this a bug that lq.style
works globally, but lq.mark
doesn’t?
Solution (for now)
#import "@local/lilaq:0.3.0" as lq // @preview/lilaq:0.3.1/0.4.0
// #import "@preview/lilaq:0.2.0" as lq
#let f(x) = calc.tan(20deg) * x + 34
#let lq-rect = lq.rect.with(stroke: black, fill: white) // Separately, but might work with lq.style in future.
#set lq.style(stroke: black) // With cycle defaults to black, but can be set to other color.
#show: lq.set-grid(stroke: black)
#show: lq.set-diagram(cycle: (
it => {
set lq.mark(stroke: black, fill: white) // For scatter. In future can be used globally.
it
},
))
#let y-max = 400
#let x-max = 640
#lq.diagram(
width: 15cm,
height: 15cm * y-max / x-max,
ylim: (0, y-max),
xlim: (0, x-max),
yaxis: (tick-distance: 80, subticks: 1),
xaxis: (tick-distance: 80, subticks: 1),
grid: (stroke-sub: 0.5pt),
let xs = lq.linspace(0, 590),
lq.plot(xs, xs.map(f), stroke: 0.5pt, mark: none),
let xs = (100, 200, 300, 400),
lq.scatter(xs, xs.map(f), size: 6mm),
lq.scatter((320,), (138,), size: 3mm),
lq-rect(400, 320, width: 160, height: 80),
)
yes, that was what I was referring to earlier − they don’t really work globally because they are just aliases for built-in types and I cheated a little to make it work. I was a little suprised that lq.style
actually works but it makes sense because I don’t touch that one.
This is also why it default to black. The default ellipse stroke is black, I think.
So… Should the docs say that you shouldn’t use global mark/style set rule? For mark, it just doesn’t work, so to avoid confusion both shouldn’t be used globally.
I want them to be used globally eventually. It’s just a limitation of the current implementation (due to the sad fact that user-defined types still don’t exist).