@flip, @flipH, @flipV
Mirror SVG path data around its start point.
@flipH mirrors it horizontally, @flipV vertically, and @flip both ways, a half turn.
Syntax
- @flip(<path data>)
- @flipH(<path data>)
- @flipV(<path data>)
Every command is transformed. Relative commands mirror their deltas; absolute commands
mirror their offset from the start point, so the first M stays where it is.
Input that is not path data is returned unchanged.
Comparing flips
h 3 v 3 h 3 v -3 goes right, down, right, then up.
@flipH changes the horizontal signs, @flipV the vertical ones, @flip both.
@grid: 2 / 60vmin _1px;
background: @svg(
viewBox: -8 -6 16 16;
--path: h 3 v 3 h 3 v -3;
path {
d: M 0 0 @pn(
--path,
@flipH(--path),
@flipV(--path),
@flip(--path)
);
fill: none;
stroke: @pn(#e6437d, #000, #000, #000);
stroke-width: .4;
}
circle { cx, cy: 0; r: .4; }
text {
x: 0;
y: 8;
text-anchor: middle;
font-size: 1.5;
font-family: sans-serif;
content: @pn(Original, Horizontal, Vertical, Both);
}
);
Keep the initial M outside the function to continue from the current point
instead of starting a new subpath.
A traditional border pattern
Combined with @invert and
@reverse, one segment can close a border.
@p(…) stores a stage; .p reuses that pick.
Composition reads right to left: @flip.invert.reverse.p is
@flip(@invert(@reverse(@p()))).
@grid: 1 / 60vmin ß .5vmin / @svg(
viewBox: 200;
path {
fill: none;
stroke: #000;
stroke-width: 3;
stroke-linecap: square;
--base: h-43 v5 h-10 v-5 h-10 v16 h-32 v10 h10 v-26 h-10;
d: M 100 5
@p(@p(@p(--base) @flip.invert.reverse.p) @flipv.invert.p)
@flip.p
}
); Mirroring curves
Control points flip with the rest of the path. The original petal is pink;
the black path draws its three mirrors by transforming that pick with .p.
@grid: 1 / 60vmin;
background: @svg(
viewBox: -20 -20 40 40;
--petal: M 0 0 c 0 -12 18 -18 18 -6 q 0 6 -18 6;
fill: none;
stroke: #000;
stroke-width: .6;
path { d: @p(--petal); stroke: #e6437d }
path { d: @flipH.p @flipV.p @flip.p }
);