Rotation

Ply offers two rotation systems. Visual rotation renders the element and its children to an offscreen buffer then draws it back rotated, layout is unaffected. Shape rotation rotates the element's own geometry at the vertex level and adjusts its bounding box, children and text are unaffected.

🔗Visual rotation

Rotate an element and everything inside it, purely visual:

The layout stays axis-aligned, surrounding elements don't see the rotation.

🔗Pivot

By default, rotation is around the center (0.5, 0.5). Change it with .pivot():

.rotate_visual(|r| r
  .degrees(30.0)
  .pivot(0.0, 0.0)
)

Pivot coordinates are normalized: (0, 0) = top-left, (1, 1) = bottom-right.

🔗Flipping

Mirror horizontally or vertically:

.rotate_visual(|r| r.flip_x())

.rotate_visual(|r| r.flip_y())

.rotate_visual(|r| r.degrees(45.0).flip_x())

🔗Combining with shaders

Visual rotation shares the same offscreen render target as .shader(). When you use both, there's no extra GPU cost:

ui.element()
  .shader(&FOIL, |s| s.uniform("u_time", get_time() as f32))
  .rotate_visual(|r| r.degrees(5.0))
  .children(|ui| {
    ui.text("Shiny + tilted", |t| t.font_size(16).color(0xFFFFFF));
  });

🔗Reference

MethodWhat it doesDefault
.degrees(f32)Rotation angle in degrees0
.radians(f32)Rotation angle in radians0
.pivot(x, y)Rotation center (0.0–1.0)(0.5, 0.5)
.flip_x()Mirror horizontallyfalse
.flip_y()Mirror verticallyfalse

🔗Shape rotation

Rotates the element's own geometry (background, border, image) at the vertex level. The bounding box adjusts to fit the rotated shape (AABB):

What shape rotation does not affect:

  • Children
  • Text
  • Shaders

There is no pivot, because pivots actually only move elements and .rotate_shape() stays within the layout.

🔗Reference

MethodWhat it doesDefault
.degrees(f32)Rotation angle in degrees0
.radians(f32)Rotation angle in radians0
.flip_x()Mirror horizontallyfalse
.flip_y()Mirror verticallyfalse

🔗Next steps

Accessibility