# Value animations

> AlphaAnimation, PositionAnimation and LoopAnimation — interpolate a number and apply it.

Source: https://crossfly.dev/docs/ui/animations/value-animations — CrossFly documentation. Full docs as one file: https://crossfly.dev/llms-full.txt

# Value animations

The three animators **interpolate a number over time**. They do **not** draw anything: in the
`onUpdate` you read `getValue()` and apply it wherever you want (alpha, position, color…). Since rendering is on
demand, call `Component.repaint()` in the callback.

## Comparison
| Class | Range | Curve | Repeats? | Use for |
|---|---|---|---|---|
| `AlphaAnimation` | **[0,1]** | cubic ease-in-out | no (has `onComplete`) | fade, opacity, highlight |
| `PositionAnimation` | **free** | linear | no (has `onComplete`) | move in pixels, slide |
| `LoopAnimation` | [0,1] | linear or eased | **yes, infinite** | pulse, glow, loading |

## Complete example (copy, paste and run)
```java
package com.exemplo;

import dev.crossfly.ui.*;
import dev.crossfly.ui.layout.*;
import dev.crossfly.ui.animation.*;   // AlphaAnimation, PositionAnimation, LoopAnimation
import dev.crossfly.util.*;           // Debug

/** Runnable main screen. Point the launcher (classname) and run: gradlew :lwjgl3:run */
public class MainWindow extends Window
{
   @Override
   public void onShow() throws Exception
   {
      super.onShow();
      setLayout(new VerticalLayout());

      // AlphaAnimation — fade-in of a label (0→1 in 0.3s)
      Label card = new Label("Olá");
      add(LAY_AUTO, card);
      AlphaAnimation fade = new AlphaAnimation(0f, 1f, 0.3f);
      fade.onUpdate(() -> { card.alpha(fade.getValue()); Component.repaint(); })
          .onComplete(() -> Debug.log("fade concluído"))
          .start();

      // PositionAnimation — slides a panel in from the right (in pixels, free)
      Label painel = new Label("Painel");
      add(LAY_AUTO, painel);
      int y0 = painel.y, w = painel.width, h = painel.height;
      PositionAnimation slide = new PositionAnimation(Screen.width, 0, 0.4f);
      slide.onUpdate(() -> { painel.setBounds((int) slide.getValue(), y0, w, h); Component.repaint(); })
           .start();

      // LoopAnimation — continuous opacity pulse (1s cycle, smoothed, infinite)
      Label ponto = new Label("●");
      add(LAY_AUTO, ponto);
      LoopAnimation pulse = new LoopAnimation(1.0f, 60f, true);
      pulse.onUpdate(() -> { ponto.alpha(0.4f + 0.6f * pulse.getValue()); Component.repaint(); })
           .start();
   }
}
```
> The snippets below show **only the core** (what goes inside `onShow()`). To run them, place them in the `MainWindow` skeleton above.

## AlphaAnimation — fade-in
```java
Label card = new Label("Olá");
AlphaAnimation fade = new AlphaAnimation(0f, 1f, 0.3f);   // 0→1 in 0.3s
fade.onUpdate(() -> { card.alpha(fade.getValue()); Component.repaint(); })
    .onComplete(() -> Debug.log("fade concluído"))
    .start();
```
Constructors: `AlphaAnimation(start, end, duration)` (60 FPS) or `(start, end, duration, fps)`.

## PositionAnimation — slide a panel (in pixels)
```java
int y0 = painel.y, w = painel.width, h = painel.height;
PositionAnimation slide = new PositionAnimation(Screen.width, 0, 0.4f);  // enters from the right
slide.onUpdate(() -> { painel.setBounds((int) slide.getValue(), y0, w, h); Component.repaint(); })
     .start();
```
It is not limited to [0,1] and is **linear** — ideal for coordinates.

## LoopAnimation — continuous pulse
```java
LoopAnimation pulse = new LoopAnimation(1.0f, 60f, true);   // 1s cycle, 60 FPS, smoothed
pulse.onUpdate(() -> { float v = 0.4f + 0.6f * pulse.getValue(); ponto.alpha(v); Component.repaint(); })
     .start();
// pulse.stop();   // stop when leaving the screen
```
Constructors: `LoopAnimation(duration)` (linear, 60 FPS) or `(duration, fps, easeInOut)`. It does **not** have
`onComplete` (runs forever until `stop()`).

## Common control
`start()` · `stop()` (fires `onComplete` on Alpha/Position) · `cancel()` (does not fire) ·
`isRunning()` · `getValue()`.

## Best practices
- **Always `Component.repaint()` in `onUpdate`** — rendering is on demand.
- **Stop loops** (`stop()`) when leaving the screen (in `onRemove()`), otherwise the `Timer` keeps running.
- Store the animation in a variable/field so you can `stop()`/`cancel()` it later.

## Common mistakes
- Using `PositionAnimation` expecting a [0,1] range — it is free; the one that clamps is `AlphaAnimation`.
- Forgetting the `repaint()` and "the animation doesn't show up".
- Calling `setAlpha(...)` (from the old Javadoc) — the real method is **`alpha(float)`**.

## See also
- [Screen transitions](/docs/ui/animations/screen-transitions) · [Press and feedback](/docs/ui/animations/press-and-feedback)
