Skip to content
Browse documentation and tutorials
TUTORIAL

Create a looping animation with JavaScript

Build a rotating ring of colored dots in Motion Lab, add breathing motion, and render your first seamless loop.

On this page

Build a rotating ring of cyan and gold dots, add a gentle breathing motion, and export a repeating animation.

Before you start

Allow about 15 minutes. You need an editable Motion Lab project and basic familiarity with JavaScript variables and loops. No local setup or package installation is required.

You will use Motion Lab's motion object. The examples are for its code editor.

Set up the project

  1. Open an editable project in Motion Lab.
  2. In project settings, choose a 1:1 aspect ratio.
  3. In Layers, choose Code and select the new layer to edit its source.
  4. Keep the layer visible and unlocked. Make its timeline clip cover the whole composition, starting at zero.
  5. Hide other visual layers while following this exercise.

Draw your first dot

Replace the starter source with this complete example:

Code example
motion.onFrame(() => {
  motion.draw.clear();
  motion.draw.setBackground("#090d1a");
  motion.draw.circle(0.5, 0.5, 0.02, {
    color: "#65e7ff",
    fillOnly: true,
  });
});

You should see one cyan dot at the center of a dark frame. If the preview is blank, check the layer's visibility and clip, and inspect the editor's diagnostics.

Animate a ring

Replace the entire previous example with the following code. Keep only one motion.onFrame() callback.

Code example
const dotCount = 48;
const orbitRadius = 0.28;
const breathingAmount = 0.03;
const dotRadius = 0.008;

motion.onFrame(() => {
  motion.draw.clear();
  motion.draw.setBackground("#090d1a");

  const phase = (motion.time / Math.max(0.001, motion.duration)) * Math.PI * 2;
  const radius = orbitRadius + Math.sin(phase * 2) * breathingAmount;

  for (let i = 0; i < dotCount; i += 1) {
    const angle = (i / dotCount) * Math.PI * 2 + phase;
    const x = 0.5 + Math.cos(angle) * radius;
    const y = 0.5 + Math.sin(angle) * radius;

    motion.draw.circle(x, y, dotRadius, {
      color: i % 4 === 0 ? "#ffc86b" : "#65e7ff",
      fillOnly: true,
    });
  }
});

Start playback. You should see 48 dots rotating around the center. Every fourth dot is gold. The ring expands and contracts twice during a full cycle.

Scrub backward in the timeline. The pattern should return to the same arrangement at the same time because each frame is calculated from timeline time.

Make one variation

Change dotCount from 48 to 24. You should see more space between the dots.

Try changing breathingAmount from 0.03 to 0.06 for a larger expansion. Keep orbitRadius + breathingAmount + dotRadius below 0.5 so the dots stay inside the square frame.

Use a positive whole number for the dot count. Multiples of four keep the gold accents evenly spaced.

Export your loop

Preview a complete cycle, then open Export. Enable Use Project Settings, select 30 FPS, choose an available format, and select Render Video.

Open the downloaded file in a player with repeat enabled. Watch the transition from the end back to the beginning. See Export an animation for more detail.

Troubleshooting

The ring is still. Start playback. At a paused time, the code intentionally draws a fixed frame.

The orbit looks oval. Use a 1:1 project aspect ratio and match it in the export settings.

Drawings overlap. Replace the previous example instead of appending another callback. Keep clear() at the beginning of each frame.

The loop jumps. Restore the phase and angle formulas above. Confirm that the code clip covers the whole composition.

Keep learning

Read Timeline time and loops to understand the phase calculation, or use Drawing API basics to look up the methods in this example.

Need a hand with this guide?Contact support