# Animações de valor

> AlphaAnimation, PositionAnimation e LoopAnimation — interpolar um número e aplicá-lo.

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

# Animações de valor

Os três animadores **interpolam um número ao longo do tempo**. Eles **não** desenham nada: no
`onUpdate` você lê `getValue()` e aplica onde quiser (alpha, posição, cor…). Como o render é sob
demanda, chame `Component.repaint()` no callback.

## Comparação
| Classe | Faixa | Curva | Repete? | Use para |
|---|---|---|---|---|
| `AlphaAnimation` | **[0,1]** | ease-in-out cúbico | não (tem `onComplete`) | fade, opacidade, destaque |
| `PositionAnimation` | **livre** | linear | não (tem `onComplete`) | mover em pixels, deslizar |
| `LoopAnimation` | [0,1] | linear ou eased | **sim, infinito** | pulso, glow, loading |

## Exemplo completo (copiar, colar e rodar)
```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

/** Tela principal executável. Aponte o launcher (classname) e rode: gradlew :lwjgl3:run */
public class MainWindow extends Window
{
   @Override
   public void onShow() throws Exception
   {
      super.onShow();
      setLayout(new VerticalLayout());

      // AlphaAnimation — fade-in de um rótulo (0→1 em 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 — desliza um painel entrando pela direita (em pixels, livre)
      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 — pulso contínuo de opacidade (ciclo de 1s, suavizado, infinito)
      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();
   }
}
```
> Os trechos abaixo mostram **só o miolo** (o que vai dentro de `onShow()`). Para rodar, coloque-os no esqueleto `MainWindow` acima.

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

## PositionAnimation — deslizar um painel (em pixels)
```java
int y0 = painel.y, w = painel.width, h = painel.height;
PositionAnimation slide = new PositionAnimation(Screen.width, 0, 0.4f);  // entra da direita
slide.onUpdate(() -> { painel.setBounds((int) slide.getValue(), y0, w, h); Component.repaint(); })
     .start();
```
Não é limitado a [0,1] e é **linear** — ideal para coordenadas.

## LoopAnimation — pulso contínuo
```java
LoopAnimation pulse = new LoopAnimation(1.0f, 60f, true);   // ciclo de 1s, 60 FPS, suavizado
pulse.onUpdate(() -> { float v = 0.4f + 0.6f * pulse.getValue(); ponto.alpha(v); Component.repaint(); })
     .start();
// pulse.stop();   // pare quando sair da tela
```
Construtores: `LoopAnimation(duration)` (linear, 60 FPS) ou `(duration, fps, easeInOut)`. **Não** tem
`onComplete` (roda para sempre até `stop()`).

## Controle comum
`start()` · `stop()` (dispara `onComplete` no Alpha/Position) · `cancel()` (não dispara) ·
`isRunning()` · `getValue()`.

## Boas práticas
- **Sempre `Component.repaint()` no `onUpdate`** — o render é sob demanda.
- **Pare loops** (`stop()`) ao sair da tela (em `onRemove()`), senão o `Timer` segue rodando.
- Guarde a animação numa variável/campo para poder `stop()`/`cancel()` depois.

## Erros comuns
- Usar `PositionAnimation` esperando faixa [0,1] — ela é livre; quem clampa é `AlphaAnimation`.
- Esquecer o `repaint()` e "a animação não aparece".
- Chamar `setAlpha(...)` (do Javadoc antigo) — o método real é **`alpha(float)`**.

## Veja também
- [Transições de tela](/docs/ui/animations/screen-transitions) · [Toque e feedback](/docs/ui/animations/press-and-feedback)
