1. Your first animation

You will add a circle to the screen and move it. That is most of what animation code ever does.

Loading live preview…

Source of learn_01_hello — edit in the playground
//! Lesson 1 — Hello: add a shape and move it.
//!
//! A scene is an `async fn`. You add shapes to the `view`, then animate
//! their properties. `.await` means "wait until this animation is done".

use oxframe::prelude::*;

#[oxframe::scene]
pub async fn hello(view: View) {
    // Add a circle on the left. `view.add` gives back a handle to animate it.
    let ball = view.add(Circle::new().size(160.0).x(-400.0).fill(color!("#68abdf")));

    // Move it to the right over 1 second.
    ball.x().to(400.0, 1.0).await;

    // When that is done, shrink it to nothing over half a second.
    ball.size().to(0.0, 0.5).await;
}

// Try:
// - change `1.0` to `3.0`: the move takes three seconds;
// - add `ball.fill().to(color!("#e13238"), 1.0).await;` before the shrink.

pub fn project() -> Project {
    Project::new("hello").scene(hello())
}

A scene is a function

An animation in oxframe is called a scene, and a scene is just a function marked with #[oxframe::scene]. It receives the view — the canvas you draw on.

The word async is there because the function runs over time: it can stop, let a few frames pass, and continue. You do not need to know more about async than that.

Adding a shape

let ball = view.add(Circle::new().size(160.0).x(-400.0).fill(color!("#68abdf")));

Circle::new() starts describing a circle; each .something(...) sets how it looks at the start — 160 pixels wide, 400 pixels left of the center, light blue. view.add(...) puts it on screen and gives you back ball, a handle you use to animate it later.

The center of the screen is (0, 0). Positive x goes right, positive y goes down.

Animating it

ball.x().to(400.0, 1.0).await;

Read it as: take the ball's x, move it to 400 over 1 second, and wait until that is done.

  • ball.x() is the ball's horizontal position. Without an argument it gives you the property; with one (like in the builder) it sets the starting value.
  • .to(400.0, 1.0) creates the animation: target value, then duration in seconds.
  • .await plays it and waits. The next line only runs once the ball has arrived.

So the scene plays its lines from top to bottom, and every .await takes time. That is the whole model.