Skip to main content

Motion Playground

Animate two scenes with keyframes, easing, translation, rotation, scaling, and sequential playback. A fixed random seed keeps the rendered preview repeatable.

Animated purple square moving across a black pixel display

Complete app

app.star
load("animation.star", "animation")
load("random.star", "random")
load("render.star", "render")

def main():
random.seed(7)
colors = ["#22d3ee", "#a78bfa", "#fb7185"]
color = colors[random.number(0, len(colors) - 1)]

travel = animation.Transformation(
child = render.Box(width = 8, height = 8, color = color),
duration = 36,
width = 64,
height = 32,
origin = animation.Origin(0.5, 0.5),
direction = "alternate",
keyframes = [
animation.Keyframe(
percentage = 0.0,
transforms = [
animation.Translate(3, 12),
animation.Rotate(0),
animation.Scale(0.75, 0.75),
],
),
animation.Keyframe(
percentage = 0.5,
transforms = [
animation.Translate(28, 5),
animation.Rotate(180),
animation.Scale(1.5, 1.5),
],
curve = "ease_in_out",
),
animation.Keyframe(
percentage = 1.0,
transforms = [
animation.Translate(53, 12),
animation.Rotate(360),
animation.Scale(0.75, 0.75),
],
curve = "ease_out",
),
],
)

pulse = animation.Transformation(
child = render.Circle(diameter = 10, color = "#fbbf24"),
duration = 24,
width = 64,
height = 32,
origin = animation.Origin(0.5, 0.5),
direction = "alternate",
keyframes = [
animation.Keyframe(
percentage = 0.0,
transforms = [
animation.Translate(27, 11),
animation.Scale(0.5, 0.5),
],
),
animation.Keyframe(
percentage = 1.0,
transforms = [
animation.Translate(27, 11),
animation.Scale(2, 2),
],
curve = "ease_in_out",
),
],
)

return render.Root(
delay = 50,
child = render.Sequence(children = [travel, pulse]),
)

Download this app.star.

How it works

  1. Each Keyframe describes the transform state at one point in the timeline.
  2. Origin(0.5, 0.5) makes scaling and rotation happen around the child's center.
  3. direction = "alternate" plays each transformation forward and backward.
  4. Sequence finishes the moving square before starting the pulsing circle.
  5. Root.delay sets a 50 ms frame delay for the animated result.

Was this helpful?