Proportionally scale arbitrary canvas to a fixed width #689
-
I'm looking for a canvas-agnostic solution for scaling any canvas to a fixed width (e. g. the page width), such that the leftmost visible element borders to the left edge of the canvas and rightmost element borders to the right edge of the canvas. The canvas should vertically scale proportionally, so the aspect ratio is maintained. Or, more simply put, I want to resize my graphs like you would in any image editing software: Screencast.from.2024-08-19.17-40-14.webmCanvases can be scaled to the parent's size by using a relative unit as its The One potential solution might be to resolve the position of each element, caching the min and max x and y values, and somehow retroactively applying a transformation based on those values. But maybe there's a much more simple solution I'm missing. |
Beta Was this translation helpful? Give feedback.
Replies: 3 comments
-
Something like: #import "@preview/cetz:0.2.2"
#set page(width: 12cm, height: 10cm)
#let scale-to(body, target-width: 1) = {
(ctx => {
import cetz.draw: *
let (ctx: _, drawables, bounds) = cetz.process.many(ctx, cetz.util.resolve-body(ctx, body))
let bounds = cetz.vector.sub(bounds.high, bounds.low)
let ratio = bounds.at(1) / bounds.at(0)
return cetz.process.many(ctx, {
group({
set-viewport((0, 0, 0), (target-width, target-width * ratio, 1), bounds: bounds,)
body
})
})
},)
}
#place(rect(width: 10cm, height: 8cm))
#cetz.canvas(length: 10cm, {
import cetz.draw: *
scale-to({
circle((2,1), fill: red)
rotate(300deg)
rect((0,0), (rel: (2, 2)), fill: blue)
})
}) But as you have mentioned, finding the right scaling with unscaled content in the canvas is non-trivial. |
Beta Was this translation helpful? Give feedback.
-
You could also apply scaling to the content by modifying the |
Beta Was this translation helpful? Give feedback.
-
Alternative: Use Typst' naitve #place(rect(width: 10cm, height: 8cm))
#let c = cetz.canvas({
import cetz.draw: *
circle((1,1), fill: red)
content((5,0), [Some test text is here. \ What do you think?])
rotate(280deg)
rect((1,3), (rel: (2, 2)), fill: blue)
})
#place(context {
let (width, height) = measure(c)
scale(10cm / width * 100%, place(c))
}) The downside is, that it scales the stroke-width of your canvas. |
Beta Was this translation helpful? Give feedback.
Something like: