Open Andrew15-5 opened 6 months ago
This isn't easily possible without extra support from the Typst compiler. You could try and break up content but it would be tricky to rotate each piece correctly while keeping styling correct and would break very easily.
While it's not possible to split content at the moment, it is possible to split strings. Here's a minimal working example:
#import "@preview/cetz:0.2.2"
#context cetz.canvas({
import cetz.draw: *
let windows(arr, size) = {
array.range(arr.len() - size + 1).map(i => {
arr.slice(i, count: size)
})
}
let text-along-path(text, path, start-percentage: 0%, end-percentage: 100%) = {
let letters = text.clusters().map(cluster => [#cluster])
let widths = letters.map(letter => {
let width = measure(letter).width
if width == 0pt {
// Measuring a single space returns a width of 0pt.
// This is a hack to get the width of a space.
measure([X X]).width - measure([XX]).width
} else {
width
}
})
let total_width = widths.sum()
let total_percentage = end-percentage - start-percentage
let distance_covered = 0
let anchors = ()
let anchors = for w in widths {
let relative_width = w / total_width
let percentage = start-percentage + total_percentage * distance_covered
distance_covered += relative_width
(percentage,)
}
anchors.push(end-percentage)
for ((percentage_1, percentage_2), letter) in windows(anchors, 2).zip(letters) {
let midpoint = (percentage_1 + percentage_2) / 2
get-ctx(ctx => {
let (ctx, percentage_1, percentage_2) = cetz.coordinate.resolve(
ctx,
(name: path, anchor: percentage_1),
(name: path, anchor: percentage_2),
)
let angle = cetz.vector.angle2(percentage_1, percentage_2)
content(
(name: path, anchor: midpoint),
anchor: "south",
angle: angle,
letter
)
})
}
}
bezier(name: "line", (0, 0), (2, 0), (1, 1), stroke: 0.2mm + blue)
let text = "Hello, World!"
text-along-path(text, "line", start-percentage: 10%, end-percentage: 90%)
})
It should also be possible to determine start and end percentage based on the measured total width and the total length of the path, but I haven't implemented this yet.
The killer feature of tikz is being able to shape text to the path, so if the path is a wave, then the text will also be wavy. With Typst 0.10.0 this text also should be able to be filled with colorful gradient to achieve an absolute masterpiece!
This will greatly increase creativity/beautifulness of some custom papers like brochures, booklets, invitation/congratulation cards etc.
https://tikz.dev/tikz-decorations https://tex.stackexchange.com/a/640598 https://tex.stackexchange.com/a/22316 https://latexdraw.com/how-to-write-a-text-along-path-using-tikz-speedometer-case/