Transform Basics

Use transforms when geometry should stay local, but its rendered position, rotation, or scale should change. In pyDreamplet, the most common pattern is to append elements to a G group and transform the group.

Local Coordinates

A group creates a local coordinate system for its children. The elements inside the group can be drawn around (0, 0), then the group can be moved as a single unit.

import pydreamplet as dp

svg = dp.SVG(540, 360)

origin = dp.G(pos=(svg.w / 2, svg.h / 2))
svg.append(origin)

origin.append(dp.Circle(cx=0, cy=0, r=6, fill="#14b8a6"))
origin.append(
    dp.Line(
        x1=-120,
        y1=0,
        x2=120,
        y2=0,
        stroke="currentColor",
        stroke_width=3,
        opacity=0.45,
    )
)
origin.append(
    dp.Line(
        x1=0,
        y1=-120,
        x2=0,
        y2=120,
        stroke="currentColor",
        stroke_width=3,
        opacity=0.28,
    )
)

The group is centered on the canvas, but its children still use coordinates relative to the group origin.

Vector Placement

Many shape constructors accept pos, and G.pos is a Vector. Vector math is useful when you want to build geometry around a local origin.

circle_pos = dp.Vector(110, 0)
origin.append(dp.Circle(pos=circle_pos, r=12, fill="#14b8a6"))

Vector.direction is expressed in degrees. Updating it rotates the vector while keeping its magnitude, which makes radial placement concise.

for _ in range(4):
    circle_pos.direction += 72
    origin.append(dp.Circle(pos=circle_pos, r=12, fill="#14b8a6"))

This is the same pattern used for radial marks, circular layouts, and animated designs where each element starts from a rotated copy of the same vector.

Rotation

Set angle on a group to rotate everything inside it.

needle = dp.G(angle=-45)
origin.append(needle)

needle.append(
    dp.Rect(
        x=-12,
        y=-118,
        width=24,
        height=110,
        rx=12,
        fill="#38bdf8",
        stroke="currentColor",
        stroke_width=4,
    )
)

This keeps the shape simple. The rectangle is still defined vertically around the local origin, and the group handles the rotation.

Scale And Pivot

Scaling and rotation happen around the group pivot. The default pivot is (0, 0), which is usually what you want when the group is drawn around its own origin.

markers = dp.G(scale=dp.Vector(1.15, 1.15))
origin.append(markers)

for angle in range(0, 360, 45):
    mark = dp.G(angle=angle)
    mark.append(
        dp.Circle(cx=0, cy=-140, r=8, fill="#f83898", stroke="currentColor", stroke_width=3)
    )
    markers.append(mark)

When the pivot needs to be somewhere else, set pivot=(x, y) explicitly.

Transform Order

G exposes an order property for transform composition. The default is "trs", which applies translation, then rotation, then scale.

badge = dp.G(pos=(svg.w / 2, svg.h / 2), angle=-45, scale=dp.Vector(1.2, 1.2), order="trs")
badge.append(dp.Rect(x=-42, y=-24, width=84, height=48, rx=10, fill="#95cf20"))
badge.append(
    dp.Text(
        "trs",
        x=0,
        y=0,
        fill="currentColor",
        font_size=18,
        text_anchor="middle",
        alignment_baseline="middle",
    )
)

svg.append(badge)

Changing the order can produce a visibly different result, especially when translation, rotation, and non-uniform scale are combined.

Next

Continue with Text basics to place, align, and measure SVG text.