Jollywatt / typst-fletcher

Typst package for drawing diagrams with arrows, built on top of CeTZ.
MIT License
270 stars 6 forks source link

Provide a `hide` function with bounds for animations #15

Closed OrangeX4 closed 4 months ago

OrangeX4 commented 4 months ago

In cetz version 0.2.1, a bounds parameter was added to the hide function, as seen in https://github.com/johannes-wolf/cetz/pull/499. This enhancement allows us to hide elements without affecting bounds calculations, ensuring that the final outcome remains consistent with the built-in hide function in Typst. Here's an example:

#import "@preview/cetz:0.2.1"

#set page(height: auto)

#rect(stroke: red, inset: 2em)[
  #cetz.canvas({
    import cetz.draw: *

    rect((0,0), (1,1))
    rect((1,1), (2,2))
    rect((2,2), (3,3))

    hide(bounds: true, {
      rect((0,0), (5,5))
    })
  })
]

image

Therefore, it is also convenient to use Touying to achieve wonderful animations (preserving spaces):

#import "@preview/touying:0.2.1": *
#import "@preview/cetz:0.2.1"

#let cetz-canvas = touying-reducer.with(reduce: cetz.canvas, cover: cetz.draw.hide.with(bounds: true))

#let (init, slide) = utils.methods(s)
#show: init

// cetz animation
#slide[
  Cetz in Touying:

  #cetz-canvas({
    import cetz.draw: *

    rect((0,0), (1,1))
    rect((1,1), (2,2))
    rect((2,2), (3,3))

    (pause,)

    rect((0,0), (5,5))
  })
]

image

As fletcher lacks a hide function similar to cetz, the final animation may be suboptimal and unable to preserve spaces:

#import "@preview/touying:0.2.1": *
#import "@preview/fletcher:0.4.1" as fletcher: node, edge

#let fletcher-diagram = touying-reducer.with(reduce: (arr, ..args) => fletcher.diagram(..args, ..arr))

#let (init, slide) = utils.methods(s)
#show: init

// fletcher animation
#slide[
  Fletcher in Touying:

  #fletcher-diagram(
    node-stroke: .1em,
    node-fill: gradient.radial(blue.lighten(80%), blue, center: (30%, 20%), radius: 80%),
    spacing: 4em,
    edge((-1,0), "r", "-|>", `open(path)`, label-pos: 0, label-side: center),
    node((0,0), `reading`, radius: 2em),
    pause,
    edge((0,0), (0,0), `read()`, "--|>", bend: 130deg),
    edge(`read()`, "-|>"),
    node((1,0), `eof`, radius: 2em),
    edge(`close()`, "-|>"),
    node((2,0), `closed`, radius: 2em, extrude: (-2.5, 0)),
    edge((0,0), (2,0), `close()`, "-|>", bend: -40deg),
  )
]

image

If fletcher could also provide a hide function, we could achieve a better animation feature.

Jollywatt commented 4 months ago

This is done in ea781e7ef1ce0b3ba9d5200ab8d10d2c25e7c8cb. :)

Because fletcher nodes and edges aren’t plain cetz arrays, but their own special thing, I needed to add a fletcher.hide(bounds: bool) function (which wraps the output in cetz.draw.hide(bounds: bool).

It now works with the following reducer:

#let fletcher-diagram = touying-reducer.with(reduce: fletcher.diagram, cover: fletcher.hide)
OrangeX4 commented 4 months ago

Thanks for such a quick implementation!