Saltar al contenido principal

View Transitions

Abrir en ChatGPT
Java API
25.11 Experimental

Las transiciones de vista proporcionan transiciones animadas cuando el DOM cambia, reduciendo la incomodidad visual y manteniendo el contexto espacial durante la navegación o las actualizaciones de contenido. webforJ se integra con la API de transición de vista del navegador para manejar la complejidad de coordinar animaciones entre estados antiguos y nuevos.

Mostrar Código

Característica experimental
Esta función es experimental y puede cambiar o eliminarse en una versión futura.

Uso básico

Para crear una transición de vista, utiliza Page.getCurrent().startViewTransition(), que devuelve un constructor para configurar la transición:

Page.getCurrent().startViewTransition()
.onUpdate(done -> {
container.remove(oldView);
container.add(newView);
done.run();
})
.start();

El proceso de transición captura una instantánea del estado actual, aplica tus cambios de DOM en el callback onUpdate, y luego anima desde la instantánea antigua hasta el nuevo contenido. Debes llamar a done.run() para señalizar cuando tus cambios están completos.

El callback onUpdate es obligatorio

Llamar a start() sin establecer un callback de actualización lanza un IllegalStateException.

Aplicando transiciones

webforJ proporciona tipos de transición predefinidos que puedes aplicar a componentes que entran o salen del DOM:

ConstanteEfecto
ViewTransition.NONESin animación
ViewTransition.FADEDesvanecimiento cruzado entre contenido antiguo y nuevo
ViewTransition.SLIDE_LEFTEl contenido fluye hacia la izquierda (como navegación hacia adelante)
ViewTransition.SLIDE_RIGHTEl contenido fluye hacia la derecha (como navegación hacia atrás)
ViewTransition.SLIDE_UPEl contenido fluye hacia arriba
ViewTransition.SLIDE_DOWNEl contenido fluye hacia abajo
ViewTransition.ZOOMEl contenido antiguo se encoge, el contenido nuevo crece
ViewTransition.ZOOM_OUTEl contenido antiguo crece, el contenido nuevo se encoge

Utiliza enter() para animar un componente que se está agregando y exit() para animar un componente que se está eliminando:

// Animar un componente entrando en el DOM
Page.getCurrent().startViewTransition()
.enter(chatPanel, ViewTransition.ZOOM)
.onUpdate(done -> {
container.add(chatPanel);
done.run();
})
.start();

// Animar un componente saliendo del DOM
Page.getCurrent().startViewTransition()
.exit(chatPanel, ViewTransition.FADE)
.onUpdate(done -> {
container.remove(chatPanel);
done.run();
})
.start();

Transiciones de componentes compartidos

Las transiciones de componentes compartidos crean un efecto de transformación donde un componente parece transformarse desde su posición en la vista antigua a su posición en la nueva vista. Esto se logra al dar a los componentes el mismo nombre de transición utilizando el método setViewTransitionName(), que está disponible en cualquier componente que implemente la interfaz HasStyle.

// En la vista de tarjeta
image.setViewTransitionName("blog-image");

// En la vista de detalle - el mismo nombre crea la transformación
image.setViewTransitionName("blog-image");

Al transitar entre estas vistas, el navegador anima el componente entre posiciones, creando una experiencia visual conectada.

Utiliza nombres únicos

Al trabajar con listas o componentes repetidos, incluye un identificador único en el nombre de la transición. Cada componente requiere su propio nombre distinto para transformarse correctamente en su componente correspondiente en la nueva vista. Usar el mismo nombre para múltiples componentes visibles causa un comportamiento indefinido.

Mostrar Código

Reordenamiento de listas

Un caso de uso común para las transiciones de componentes compartidos es animar elementos de lista cuando su orden cambia. Al asignar un view-transition-name único a cada elemento, el navegador anima automáticamente los componentes a sus nuevas posiciones:

// Cada tarjeta recibe un nombre de transición único basado en su ID
card.setViewTransitionName("card-" + item.id());

// Al mezclar, solo actualiza el DOM - el navegador maneja la animación
Page.getCurrent().startViewTransition()
.onUpdate(done -> {
renderList();
done.run();
})
.start();
Mostrar Código

Animaciones CSS personalizadas

Para tener un control total sobre las animaciones, puedes definir keyframes CSS personalizados. webforJ añade sufijos -enter o -exit a tus nombres de transición, los cuales usas para dirigirte a los pseudo-elementos de transición de vista:

/* Definir keyframes para componentes que entran */
@keyframes flip-enter {
from {
opacity: 0;
transform: perspective(1000px) rotateX(-90deg);
}
to {
opacity: 1;
transform: perspective(1000px) rotateX(0deg);
}
}

/* Aplicar al pseudo-elemento de transición de vista */
::view-transition-new(flip-in-enter) {
animation: flip-enter 450ms cubic-bezier(0.34, 1.56, 0.64, 1);
transform-origin: top center;
}

::view-transition-old(flip-in-enter) {
display: none;
}

Referencia tu animación personalizada pasando su nombre (sin el sufijo) a enter() o exit():

// Usar "flip-in" - webforJ añade automáticamente el sufijo "-enter"
Page.getCurrent().startViewTransition()
.enter(notification, "flip-in")
.onUpdate(done -> {
stage.add(notification);
done.run();
})
.start();

// Usar "blur-out" para salir - webforJ añade automáticamente el sufijo "-exit"
Page.getCurrent().startViewTransition()
.exit(notification, "blur-out")
.onUpdate(done -> {
stage.remove(notification);
done.run();
})
.start();
Mostrar Código

Personalización CSS

Cada tipo de transición predefinido expone propiedades CSS personalizables para ajustes finos:

VariablePredeterminadoDescripción
--vt-fade-duration200msDuración de la animación
--vt-fade-easingcubic-bezier(0.4, 0, 0.2, 1)Función de desaceleración
VariablePredeterminadoDescripción
--vt-slide-left-duration200msDuración de la animación
--vt-slide-left-easingcubic-bezier(0.4, 0, 0.2, 1)Función de desaceleración
--vt-slide-left-distance30%Distancia de deslizamiento
VariablePredeterminadoDescripción
--vt-slide-right-duration200msDuración de la animación
--vt-slide-right-easingcubic-bezier(0.4, 0, 0.2, 1)Función de desaceleración
--vt-slide-right-distance30%Distancia de deslizamiento
VariablePredeterminadoDescripción
--vt-slide-up-duration200msDuración de la animación
--vt-slide-up-easingcubic-bezier(0.4, 0, 0.2, 1)Función de desaceleración
--vt-slide-up-distance30%Distancia de deslizamiento
VariablePredeterminadoDescripción
--vt-slide-down-duration200msDuración de la animación
--vt-slide-down-easingcubic-bezier(0.4, 0, 0.2, 1)Función de desaceleración
--vt-slide-down-distance30%Distancia de deslizamiento
VariablePredeterminadoDescripción
--vt-zoom-duration200msDuración de la animación
--vt-zoom-easingcubic-bezier(0.4, 0, 0.2, 1)Función de desaceleración
--vt-zoom-scale0.8Factor de escala (el viejo se aleja a este valor, el nuevo se acerca desde este valor)
VariablePredeterminadoDescripción
--vt-zoom-out-duration200msDuración de la animación
--vt-zoom-out-easingcubic-bezier(0.4, 0, 0.2, 1)Función de desaceleración
--vt-zoom-out-scale1.2Factor de escala (el viejo se acerca a este valor, el nuevo se aleja desde este valor)

Para personalizar, sobrescribe estas variables en tu CSS:

:root {
--vt-fade-duration: 300ms;
--vt-slide-left-distance: 50%;
}

Para una personalización avanzada, dirígete a los pseudo-elementos de transición de vista directamente:

::view-transition-old(vt-slide-left-exit) {
animation-duration: 400ms;
}

::view-transition-new(vt-slide-left-enter) {
animation-timing-function: ease-out;
}