Animaciones en JavaFX: De Timeline a Transiciones

Aprende a crear animaciones fluidas en JavaFX con demos interactivas en vivo. Desde FadeTransition hasta animaciones combinadas con Timeline, cada ejemplo incluye una demo visual y el código Java completo.

J

JavaFX Master

4 de marzo de 2025 14 min de lectura

Animaciones en JavaFX: De Timeline a Transiciones

Las animaciones son lo que hace que una interfaz pase de ser funcional a sentirse viva. JavaFX incluye un sistema de animaciones potente con transiciones predefinidas y la flexibilidad de Timeline para crear cualquier animación personalizada.

En este artículo cada ejemplo tiene una demo interactiva para que veas la animación en acción, seguida del código JavaFX equivalente.

1. Fade (Opacidad)

La animación más básica y útil. Perfecta para mostrar/ocultar elementos con elegancia.

Fade

Código JavaFX

import javafx.animation.FadeTransition;
import javafx.util.Duration;

FadeTransition fade = new FadeTransition(Duration.millis(700), nodo);
fade.setFromValue(1.0);
fade.setToValue(0.0);
fade.play();

// Para hacer Fade In, invierte los valores:
fade.setFromValue(0.0);
fade.setToValue(1.0);

Tip: Usa fade.setAutoReverse(true) y fade.setCycleCount(Animation.INDEFINITE) para crear un efecto de "respiración" continuo.

2. Scale (Escala)

Agranda o reduce un elemento. Ideal para botones al hacer hover o para resaltar elementos seleccionados.

Scale

Código JavaFX

import javafx.animation.ScaleTransition;
import javafx.util.Duration;

ScaleTransition scale = new ScaleTransition(Duration.millis(500), nodo);
scale.setFromX(1.0);
scale.setFromY(1.0);
scale.setToX(1.5);
scale.setToY(1.5);
scale.play();

Para un efecto de botón hover, usa un listener:

boton.setOnMouseEntered(e -> {
    ScaleTransition st = new ScaleTransition(Duration.millis(200), boton);
    st.setToX(1.1);
    st.setToY(1.1);
    st.play();
});

boton.setOnMouseExited(e -> {
    ScaleTransition st = new ScaleTransition(Duration.millis(200), boton);
    st.setToX(1.0);
    st.setToY(1.0);
    st.play();
});

3. Slide (Desplazamiento)

Mueve un elemento de un punto a otro. Útil para paneles deslizantes, sidebars y notificaciones.

Slide

Código JavaFX

import javafx.animation.TranslateTransition;
import javafx.util.Duration;

TranslateTransition slide = new TranslateTransition(Duration.millis(500), nodo);
slide.setFromX(0);
slide.setToX(200); // Mover 200px a la derecha
slide.play();

// Para una sidebar que se desliza desde la izquierda:
TranslateTransition showSidebar = new TranslateTransition(Duration.millis(300), sidebar);
showSidebar.setFromX(-250); // Empieza fuera de pantalla
showSidebar.setToX(0);      // Termina en posición
showSidebar.play();

4. Rotate (Rotación)

Rota un elemento sobre su centro. Perfecto para iconos de carga, flechas expandibles y efectos decorativos.

Rotate

Código JavaFX

import javafx.animation.RotateTransition;
import javafx.util.Duration;

RotateTransition rotate = new RotateTransition(Duration.millis(700), nodo);
rotate.setFromAngle(0);
rotate.setToAngle(180);
rotate.play();

// Spinner infinito:
RotateTransition spinner = new RotateTransition(Duration.millis(1000), iconoCarga);
spinner.setFromAngle(0);
spinner.setToAngle(360);
spinner.setCycleCount(Animation.INDEFINITE);
spinner.setInterpolator(Interpolator.LINEAR);
spinner.play();

5. Color (Cambio de Color)

Cambia el color de fondo de un componente gradualmente. Útil para estados de validación, temas y feedback visual.

Color

Código JavaFX

JavaFX no tiene un ColorTransition directo, pero lo puedes crear con Timeline:

import javafx.animation.Timeline;
import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.scene.paint.Color;
import javafx.util.Duration;

ObjectProperty<Color> colorProp = new SimpleObjectProperty<>(Color.web("#0ea5e9"));

colorProp.addListener((obs, oldColor, newColor) -> {
    nodo.setStyle(String.format(
        "-fx-background-color: rgb(%d,%d,%d);",
        (int)(newColor.getRed() * 255),
        (int)(newColor.getGreen() * 255),
        (int)(newColor.getBlue() * 255)
    ));
});

Timeline colorAnim = new Timeline(
    new KeyFrame(Duration.ZERO,
        new KeyValue(colorProp, Color.web("#0ea5e9"))),
    new KeyFrame(Duration.millis(700),
        new KeyValue(colorProp, Color.web("#f43f5e")))
);
colorAnim.play();

6. Animaciones Combinadas

La magia real ocurre cuando combinas múltiples animaciones. Puedes usar ParallelTransition para ejecutar varias a la vez.

All

Código JavaFX

import javafx.animation.ParallelTransition;
import javafx.animation.FadeTransition;
import javafx.animation.ScaleTransition;
import javafx.animation.RotateTransition;
import javafx.animation.TranslateTransition;
import javafx.util.Duration;

// Crear transiciones individuales
FadeTransition fade = new FadeTransition(Duration.millis(700), nodo);
fade.setToValue(0.8);

ScaleTransition scale = new ScaleTransition(Duration.millis(700), nodo);
scale.setToX(1.25);
scale.setToY(1.25);

RotateTransition rotate = new RotateTransition(Duration.millis(700), nodo);
rotate.setToAngle(12);

TranslateTransition move = new TranslateTransition(Duration.millis(700), nodo);
move.setToX(32);

// Ejecutar todas en paralelo
ParallelTransition combo = new ParallelTransition(fade, scale, rotate, move);
combo.play();

También puedes encadenar animaciones con SequentialTransition:

import javafx.animation.SequentialTransition;

SequentialTransition secuencia = new SequentialTransition(
    fade,    // Primero fade
    scale,   // Luego escala
    rotate   // Finalmente rotación
);
secuencia.play();

7. Efectos Hover

Los efectos hover hacen que la interfaz se sienta interactiva y responsiva. Pasa el mouse sobre estos elementos:

Hover
Lift
Tilt

Pasa el mouse sobre los cuadros

Código JavaFX

// Efecto Scale on Hover
nodo.setOnMouseEntered(e -> {
    ScaleTransition st = new ScaleTransition(Duration.millis(200), nodo);
    st.setToX(1.1);
    st.setToY(1.1);
    st.play();
});

nodo.setOnMouseExited(e -> {
    ScaleTransition st = new ScaleTransition(Duration.millis(200), nodo);
    st.setToX(1.0);
    st.setToY(1.0);
    st.play();
});

// Efecto Lift (mover hacia arriba)
nodo.setOnMouseEntered(e -> {
    TranslateTransition tt = new TranslateTransition(Duration.millis(200), nodo);
    tt.setToY(-8);
    tt.play();
});

nodo.setOnMouseExited(e -> {
    TranslateTransition tt = new TranslateTransition(Duration.millis(200), nodo);
    tt.setToY(0);
    tt.play();
});

// Efecto con DropShadow
import javafx.scene.effect.DropShadow;
import javafx.scene.paint.Color;

DropShadow shadow = new DropShadow(10, Color.rgb(59, 130, 246, 0.5));
nodo.setOnMouseEntered(e -> nodo.setEffect(shadow));
nodo.setOnMouseExited(e -> nodo.setEffect(null));

8. Animaciones Infinitas

Animaciones que se repiten continuamente, útiles para indicadores de carga, notificaciones y elementos decorativos.

Pulse
Bounce
Spin

Animaciones infinitas: pulse, bounce, spin, ping

Código JavaFX

// Pulse (opacidad pulsante)
FadeTransition pulse = new FadeTransition(Duration.millis(1000), nodo);
pulse.setFromValue(1.0);
pulse.setToValue(0.5);
pulse.setAutoReverse(true);
pulse.setCycleCount(Animation.INDEFINITE);
pulse.play();

// Bounce (rebote vertical)
TranslateTransition bounce = new TranslateTransition(Duration.millis(500), nodo);
bounce.setFromY(0);
bounce.setToY(-20);
bounce.setAutoReverse(true);
bounce.setCycleCount(Animation.INDEFINITE);
bounce.setInterpolator(Interpolator.EASE_BOTH);
bounce.play();

// Spin (rotación continua)
RotateTransition spin = new RotateTransition(Duration.millis(1000), nodo);
spin.setFromAngle(0);
spin.setToAngle(360);
spin.setCycleCount(Animation.INDEFINITE);
spin.setInterpolator(Interpolator.LINEAR);
spin.play();

Interpoladores

Los interpoladores controlan la curva de velocidad de la animación. JavaFX incluye varios:

InterpoladorEfecto
Interpolator.LINEARVelocidad constante
Interpolator.EASE_INEmpieza lento, termina rápido
Interpolator.EASE_OUTEmpieza rápido, termina suave
Interpolator.EASE_BOTHSuave al inicio y final
Interpolator.SPLINE(a,b,c,d)Curva Bézier personalizada
// Animación con ease-out para un movimiento natural
TranslateTransition slide = new TranslateTransition(Duration.millis(400), nodo);
slide.setToX(200);
slide.setInterpolator(Interpolator.EASE_OUT);
slide.play();

Clase Helper: AnimationUtils

Para no repetir código, crea una clase utilitaria:

public class AnimationUtils {

    public static void fadeIn(Node nodo, double duracionMs) {
        FadeTransition ft = new FadeTransition(Duration.millis(duracionMs), nodo);
        ft.setFromValue(0);
        ft.setToValue(1);
        ft.play();
    }

    public static void fadeOut(Node nodo, double duracionMs, Runnable onFinish) {
        FadeTransition ft = new FadeTransition(Duration.millis(duracionMs), nodo);
        ft.setFromValue(1);
        ft.setToValue(0);
        if (onFinish != null) ft.setOnFinished(e -> onFinish.run());
        ft.play();
    }

    public static void scaleHover(Node nodo, double factor) {
        nodo.setOnMouseEntered(e -> {
            ScaleTransition st = new ScaleTransition(Duration.millis(150), nodo);
            st.setToX(factor);
            st.setToY(factor);
            st.play();
        });
        nodo.setOnMouseExited(e -> {
            ScaleTransition st = new ScaleTransition(Duration.millis(150), nodo);
            st.setToX(1.0);
            st.setToY(1.0);
            st.play();
        });
    }

    public static void slideIn(Node nodo, double fromX, double duracionMs) {
        nodo.setTranslateX(fromX);
        TranslateTransition tt = new TranslateTransition(Duration.millis(duracionMs), nodo);
        tt.setToX(0);
        tt.setInterpolator(Interpolator.EASE_OUT);
        tt.play();
    }
}

Uso:

AnimationUtils.fadeIn(miPanel, 300);
AnimationUtils.scaleHover(miBoton, 1.1);
AnimationUtils.slideIn(sidebar, -250, 400);

Siguiente Paso

Con estas animaciones ya tienes las herramientas para crear interfaces que se sientan profesionales y vivas. En el próximo artículo exploraremos cómo crear componentes reutilizables como tarjetas, barras de estado y notificaciones toast.

forumComentarios

Deja tu comentario

progress_activityCargando comentarios...