Placing Things
You rarely need coordinates: say where things go, and Pymations works out the numbers.
Every change below happens at once. Put .animate in front to play it as a movement: play(label.animate.next_to(dot, UP)).
Next to something
from pymations import *
circle = Circle(color=BLUE)
above = Text("above").next_to(circle, UP)
right = Text("right").next_to(circle, RIGHT, buff=0.5)
play(Create(circle), Write(above), Write(right))
a.next_to(b, direction) puts a beside b, touching edge to edge, with a small gap (buff, 0.25 unless you give one). b can be a point, such as axes.c2p(1, 2). Diagonals (UR, DL...) put it at a corner.
aligned_edge=LEFT lines up the left edges as well: b.next_to(a, DOWN, aligned_edge=LEFT) makes a neat list.
In rows and grids
from pymations import *
row = VGroup(*[Square(side_length=1) for _ in range(5)]).arrange(RIGHT, buff=0.3)
grid = VGroup(*[Dot() for _ in range(12)]).arrange_in_grid(rows=3, buff=0.5).next_to(row, DOWN, buff=1)
play(Create(row), FadeIn(grid))
group.arrange(RIGHT)puts the members in a row, left to right;arrange(DOWN)in a column. The group stays centred where it was.group.arrange_in_grid(rows=3)(orcols=) fills a grid, row by row.
At the edges
| Change | Where it goes |
|---|---|
m.to_edge(UP) | Against the top of the picture (also DOWN, LEFT, RIGHT) |
m.to_corner(UL) | Into a corner (UL, UR, DL, DR) |
m.center() | The middle of the picture |
They leave a margin of half a unit; buff= changes it.
Moving
| Change | What it does |
|---|---|
m.shift(RIGHT * 2) | Moves by an amount |
m.move_to([1, 2, 0]) | Moves its middle to a point, or onto another object: m.move_to(other) |
m.align_to(other, LEFT) | Lines up one edge with other's, moving only that way |
m.set_x(3), m.set_y(-1) | Sets one coordinate of its middle |
Size and turning
| Change | What it does |
|---|---|
m.scale(2) | Twice as big (about its middle). Line widths stay the same |
m.scale_to_fit_width(4), m.scale_to_fit_height(2) | Scales until it is that wide or tall |
m.set(width=4) | The same as scale_to_fit_width(4) |
m.match_width(other) | As wide as other |
m.stretch(2, 0) | Stretches along x (0) or y (1) only |
m.rotate(PI / 4) | Turns it (an eighth of a turn) about its middle |
m.flip() | Mirrors it left to right |
In front and behind
Things added later are drawn on top. m.set_z_index(1) keeps m above everything with a lower number, whatever order they came in.
Where things are
m.get_center(), m.get_top(), m.get_bottom(), m.get_left(), m.get_right(), m.get_corner(UR), and for a line get_start() and get_end(), are points you can use straight away, and do sums with:
from pymations import *
box = Square()
dot = Dot(box.get_corner(UR) + UP * 0.5, color=YELLOW)
arrow = Arrow(dot.get_center(), box.get_top())
play(Create(box), FadeIn(dot), GrowArrow(arrow))
Reading a position back
Positions are worked out in the preview, so Python does not have their numbers until it asks. Most of the time you never need them. If you do (to print one, or to use it in an if), put await in front:
from pymations import *
box = Square().shift(RIGHT * 2)
x, y, z = await box.get_center()
print("The box is at", x, y)
In a scene, write async def construct(self): so that await can be used inside it. Widths and heights read back the same way: w = await box.width.