How to generate a dashed stroke in two colours using fletcher?

Hi everyone,
i would like to use a dashed stroke that alternates between two colors. My specific use case is to color the border of a node in fletcher in two colors.
I have looked into the documentation for strokes (Stroke Type – Typst Documentation) and tried using a tiling, but the best i could come up with is as below:

// pattern that alternates two colors
#let pat = tiling(size: (20pt, 10pt), relative: "parent")[
  #place(square(size: 10pt, fill: primary_color))
  #place(dx: 10pt, square(size: 10pt, fill: primary_color.lighten(40%)))
]

// test: draw diagram with a node that uses the pattern as fill
#diagram({
  node((0, 0), text("test"), stroke: 5pt + pat, name: "test", shape: circle)
})

resulting in the following output:
Screenshot_2025-05-19_12-23-32

Would be thankful for any ideas how to achieve a coloring that follows the outline of the circle.

You can use gradient.conic() to get the dashed stroke. gradient.sharp() then makes the gradient discrete and gradient.repeat() defines the number of periods around the circle.

#import "@preview/fletcher:0.5.7" as fletcher: diagram, node, edge

#let pat = gradient.conic(purple, purple.lighten(40%)).sharp(2).repeat(15)

#diagram({
  node((0, 0), text("test"), stroke: pat, name: "test", shape: circle)
})

forum_4156_two-colored-stroke

If you add a code example to your post, please make sure that it compiles without error. It is good that you minimized the example to only show your actual issue, but in this case the variable primary_color and the import of fletcher were missing.

3 Likes

Thanks, that works just like i need it!

An alternative solution could be to use two strokes. Fletcher doesn’t support this with one node, but you can write your own function which adds two nodes and hides the second node’s label/fill.

#import "@preview/fletcher:0.5.7" as fletcher: diagram, node, edge

#let doublenode(pos, label, ..args, stroke: 1pt + black, secondary: black) = {
	node(pos, label, ..args, stroke: stroke)
	node(pos, hide(label), ..args, fill: none, stroke: (dash: (5pt, 5pt), paint: secondary, thickness: stroke.thickness))
}

#diagram({
	doublenode((0, 0), text("test"), name: "test", shape: circle,
		stroke: 4pt + purple, secondary: purple.darken(50%))
})

Screenshot 2025-05-19 at 14.56.51

3 Likes

Thanks, i suppose that is a reasonable workaround and has the benefit of also working with other shapes. I have now run into the problem that the gradient approach does not work for edges in a fletcher graph because the gradient is not oriented along the edge.