# Cómo mover un componente animando su posición

> Deslizar un componente de un punto a otro con PositionAnimation (interpolación lineal en píxeles).

Source: https://crossfly.dev/es/docs/cookbook/anim/mover-componente — CrossFly documentation. Full docs as one file: https://crossfly.dev/llms-full.txt

# Cómo mover un componente animando su posición

**Propósito.** Animar la **posición en píxeles** de un componente (ej.: deslizar una card de la derecha al centro). `PositionAnimation` interpola linealmente y **no** está limitada a [0,1] — ideal para coordenadas.

## APIs usadas
- `new PositionAnimation(float start, float end, float duration [, float fps])` — interpola `start → end` **linealmente**, **sin clamp**; `duration` en segundos; `fps` opcional (por defecto 60).
- `PositionAnimation.onUpdate(Runnable)` / `onComplete(Runnable)` / `getValue()` / `start()` / `stop()` / `cancel()` — misma familia que `AlphaAnimation`.
- `Component.setX(int)` / `Component.setY(int)` — reposicionan el componente (retornan `Component`). Alternativa: `setBounds(int x, int y, int w, int h)` cuando también cambie el tamaño.
- `Component.getY()` / `getWidth()` / `getHeight()` — para preservar los ejes que no se están animando.
- `Component.repaint()` — estático; obligatorio en el `onUpdate` (render bajo demanda).

## Ejemplo completo (copiar, pegar y ejecutar)
```java
package com.exemplo;

import dev.crossfly.ui.*;
import dev.crossfly.ui.layout.*;
import dev.crossfly.ui.animation.*;

/** Pantalla principal ejecutable: desliza un card de la derecha al centro al abrir. */
public class MainWindow extends Window
{
   @Override
   public void onShow() throws Exception
   {
      super.onShow();
      setLayout(new VerticalLayout());

      Card card = new Card();
      add(card);

      int fromX = Screen.width;          // comienza fuera de la pantalla, a la derecha
      int toX   = (Screen.width - card.width) / 2;   // centra horizontalmente

      PositionAnimation slide = new PositionAnimation(fromX, toX, 0.4f);   // 400 ms
      slide.onUpdate(() ->
         {
            card.x = (int) slide.getValue();     // mueve solo el eje X; Y permanece (x es campo público)
            Component.repaint();                 // sin esto el cuadro no se redibuja
         })
         .onComplete(() -> Component.repaint())
         .start();
   }
}
```

> El fragmento de abajo muestra **solo el núcleo**. Para ejecutarlo, colócalo en el esqueleto `MainWindow` de arriba.

## Fragmento mínimo
```java
// verificado en la fuente: PositionAnimation lineal sin clamp; Component.setX(int)/setY(int); repaint() estático
Card card = new Card();
add(card);

int fromX = Screen.width;          // comienza fuera de la pantalla, a la derecha
int toX   = (Screen.width - card.getWidth()) / 2;   // centra horizontalmente

PositionAnimation slide = new PositionAnimation(fromX, toX, 0.4f);   // 400 ms
slide.onUpdate(() ->
   {
      card.setX((int) slide.getValue());   // mueve solo el eje X; Y permanece
      Component.repaint();                 // sin esto el cuadro no se redibuja
   })
   .onComplete(() -> Component.repaint())
   .start();
```

Detalles:

- Si necesitas mover en X **y** Y al mismo tiempo, usa **dos** `PositionAnimation` (una por eje) o aplica `setBounds(x, y, w, h)` en el `onUpdate` calculando ambos.
- `setX`/`setY` alteran la posición **absoluta** en el padre; en pantallas con layout automático, prefiere animar componentes cuyo bounds controlas directamente (evita pelear con el `Layout`).
- A diferencia de `AlphaAnimation`, aquí **no** hay easing: el movimiento es constante. Para un movimiento suave, encadena un easing en tu propia función o combínalo con `AlphaAnimation` para el efecto de opacidad.

## Profundiza
- [Animaciones de valor](/docs/ui/animations/value-animations)
- Receta hermana: [Fade de un componente](/docs/cookbook/anim/fade) · [Pulso en loop](/docs/cookbook/anim/pulso-loop)
- Relacionado: [Abrir y cerrar una pantalla](/docs/cookbook/nav/abrir-tela)
