Mejorando la interfaz de Oracle APEX con Lottie.js

I am a technology professional with about a decade of experience in software development, specialising in Oracle APEX. My career began in telecommunications engineering, but my passion for technology and software development led me to transition into this field. Since then, I have been deeply involved in leading teams and driving digital transformation across various projects. As a part of my daily tasks, I focus on fostering collaboration, efficiency, and technical excellence, ensuring that the projects where I'm involved embrace digital advancements effectively. I take great pride in sharing my knowledge and experience, whether through mentorship, conferences, or engaging with the tech community.
Mientras esperamos la inminente aparición de una nueva versión de Oracle APEX, estoy aprovechando para organizar notas antiguas de distintos proyectos. Muchas veces, al revisarlas con perspectiva, aparecen patrones interesantes que merece la pena compartir.
Desde su aparición en 2015, Universal Theme ha acompañado a los desarrolladores evolucionando multitud de componentes declarativos a lo largo de más de una década. Nos ha proporcionado un diseño unificado, responsive y con una capacidad de personalización sencilla gracias al uso de Theme Roller.
Sin embargo, hay determinados proyectos - especialmente aquellos donde construimos aplicaciones con un fuerte foco en la experiencia de usuario o en entornos orientados a cliente - en los que los componentes estándar pueden quedarse cortos. No porque APEX no sea capaz, sino porque dar el siguiente paso implica integrar capacidades externas al framework declarativo.
Aquí es donde entra en juego una idea clave:
APEX no es solo low-code. Es una plataforma extensible sobre la que podemos construir prácticamente cualquier cosa que exista en el ecosistema web.
Una de las áreas donde esto se aprecia con mayor claridad es en las micro-interacciones y animaciones ligeras: mensajes de éxito, estados vacíos, loaders personalizados, ilustraciones animadas… pequeños detalles que elevan la percepción de calidad de una aplicación sin comprometer el rendimiento.
En este contexto, Lottie.js se convierte en una herramienta especialmente interesante. Nos permite incorporar animaciones vectoriales en formato JSON, extremadamente ligeras y totalmente responsive, aportando una capa adicional de sofisticación visual a nuestras aplicaciones APEX.
En este post veremos:
Cómo integrar correctamente una librería JavaScript externa en Oracle APEX.
Qué consideraciones técnicas debemos tener en cuenta (ciclo de vida de página, carga de recursos, rendimiento).
Y un ejemplo práctico implementando animaciones Lottie dentro de una aplicación APEX.
¿Qué es Lottie y por qué encaja tan bien con Oracle APEX?
Lottie es una librería JavaScript que permite renderizar animaciones vectoriales a partir de archivos JSON, normalmente exportados desde Adobe After Effects.
En lugar de trabajar con GIFs pesados o vídeos embebidos, Lottie utiliza una representación declarativa de la animación en formato JSON. El navegador interpreta ese JSON y genera la animación en tiempo real utilizando SVG o Canvas.
Esto tiene varias implicaciones interesantes:
1. Peso extremadamente reducido
Un GIF animado de unos pocos segundos puede fácilmente superar varios cientos de KB o incluso varios MB.
Una animación equivalente en Lottie puede pesar apenas unos pocos KB, especialmente si está bien optimizada.
En aplicaciones APEX donde cada petición HTTP cuenta (sobre todo en entornos SaaS o con usuarios concurrentes), esto no es un detalle menor.
2. Totalmente responsive y escalable
Al tratarse de gráficos vectoriales:
No hay pérdida de calidad.
Se adaptan perfectamente a cualquier resolución.
Funcionan de forma natural dentro del grid del Universal Theme.
Esto encaja especialmente bien con la filosofía responsive de APEX y el Universal Theme.
3. Control programático
Aquí es donde empieza a ponerse interesante desde el punto de vista técnico.
Una animación Lottie no es un simple recurso estático. Podemos:
Reproducirla bajo demanda.
Pausarla.
Controlar su velocidad.
Lanzarla tras algún evento concreto.
Sincronizarla con procesos PL/SQL o Dynamic Actions.
Y aquí es donde la integración con APEX cobra sentido real.
¿Y por qué esto también tiene sentido en aplicaciones empresariales?
A menudo asociamos animaciones con marketing o aplicaciones de consumo, pero en entornos empresariales pueden aportar muchísimo valor:
Estados vacíos más expresivos en Interactive Reports.
Confirmaciones visuales tras procesos críticos.
Indicadores de carga personalizados en procesos asíncronos.
Pantallas de onboarding en aplicaciones internas.
Refuerzo visual en dashboards ejecutivos.
No se trata de “hacer bonito”. Se trata de mejorar percepción de calidad, reducir fricción y comunicar estado de sistema de forma más clara.
Y lo mejor: todo esto se puede integrar en APEX sin romper el modelo declarativo, simplemente ampliándolo.
Integrando librerías JavaScript externas en Oracle APEX (de forma correcta)
Uno de los grandes puntos fuertes de Oracle APEX es que, aunque nos movemos en un paradigma declarativo y de poco o ningún código, seguimos estando sobre una aplicación web estándar: HTML, CSS y JS. Eso significa que podemos integrar cualquier librería JavaScript moderna… siempre que entendamos cómo funciona el ciclo de vida de una página APEX.
Antes de empezar a pegar <script> en cualquier sitio, conviene tener claros tres conceptos:
Dónde cargar la librería.
Cuándo se ejecuta el código.
Cómo evitar conflictos con el motor JavaScript de APEX.
1. Dónde cargar la librería: App-level vs Page-level
Tenemos varias opciones:
Opción A — Cargar desde CDN (rápido y sencillo)
Podemos incluir Lottie directamente desde un CDN oficial:
<https://cdnjs.cloudflare.com/ajax/libs/lottie-web/5.12.2/lottie.min.js>
Esto se añade en:
Shared Components > User Interface > JavaScript > File URLs
Ventajas:
Rápido de implementar.
Siempre última versión estable.
Inconvenientes:
Dependencia externa.
Puede no ser aceptable en entornos con restricciones de seguridad o sin acceso a Internet.
Opción B — Static Application Files (recomendado en entornos corporativos)
Descargamos lottie.min.js y lo subimos a:
Shared Components > Static Application Files
Por ejemplo:
#APP_FILES#lottie.min.js
Esto nos da:
Control total de versión.
Sin dependencia externa.
Mayor alineación con políticas corporativas.
En proyectos empresariales o SaaS multi-tenant, esta suele ser la opción adecuada.
2. Entender el ciclo de vida de una página APEX
Este es el punto que suele generar más errores.
APEX no es una página HTML “estática”. Tiene:
Renderizado del servidor.
Inicialización del motor JavaScript.
Dynamic Actions.
Eventos propios como
apexready.
Si ejecutamos código demasiado pronto, el DOM puede no estar preparado. De momento, introduzco la teoría, y lo vemos en la práctica cuando construyamos nuestro ejemplo…
3. Separar librería de lógica
Buena práctica importante:
La librería (lottie.min.js) debe cargarse como recurso.
La lógica de inicialización debe ir en:
Page > JavaScript > Function and Global Variable Declaration
O en un archivo JS propio dentro de Static Files.
Evitemos poner lógica compleja en “Execute when Page Loads” si va a crecer.
Esto nos permite:
Reutilizar código.
Versionar mejor.
Mantener arquitectura limpia.
Dicho esto, para el propósito del ejemplo que vamos a construir, optaré por mostrarlo todo de la forma más simple posible e incluiremos nuestro JS a nivel de página.
4. Estructura mínima para usar Lottie en APEX
Ya presentadas todas las variables que intervienen, podemos recapitular sobre todo lo que necesitamos. Una animación Lottie necesita:
Un contenedor HTML.
El JSON de la animación.
Una llamada a
lottie.loadAnimation().
Para concluir, una nota más:
Podemos subir también el archivo JSON de la animación a Static Application Files, exactamente igual que la librería JS.
Esto mantiene todo dentro del ciclo de despliegue de la aplicación y, como antes, elimina dependencias de recursos externos o acceso a la red.
Ejemplo práctico: animación de éxito tras un proceso PL/SQL
Cómo siempre, la teoría está fenomenal pero hagamos un poco de APEX…
En el ejemplo de hoy, vamos a evitar depender de objetos, y vamos a mostrar una animación tras la ejecución de un proceso. Para ello, vamos a utilizar:
Un botón que dispare un proceso PL/SQL.
Un proceso que, simplemente, cuente 3 segundos.
Cuando el proceso finalice con éxito, mostraremos una pequeña animación Lottie.
Una vez vistas las bases, vamos a construir un ejemplo completo desde cero para integrar animaciones Lottie en una aplicación Oracle APEX.
Además, aprovecharemos el ejemplo para ver cómo coordinar:
un proceso PL/SQL
un flag en session state
un Ajax Callback
y algo de JavaScript en la página
Todo ello sin romper el modelo declarativo de APEX.
1. Crear una aplicación APEX en blanco
Comenzamos creando una aplicación mínima.
En App Builder:
Create → New Application
Elegimos:
Name:
Demo AnimationsCreate Application
No necesitamos añadir páginas adicionales, ya que trabajaremos directamente con la Página 1, por simplicidad.
2. Añadir un botón para ejecutar el proceso
En la Página 1, añadimos un botón dentro del Breadcrumb.
Create → Button
Configuración básica:
Name:
RUN_PROCESSLabel:
Run processPosition:
Next
Este botón será el encargado de ejecutar nuestro proceso PL/SQL, realizando un Submit Page.
3. Crear un item oculto para controlar la animación
Necesitamos una forma de indicar a la página que debe mostrar la animación cuando el proceso termine. Ya que lo estamos realizando todo en la misma página, actuará como una especie de flag.
Para ello creamos un item oculto dentro de la región Breadcrumb:
Create → Item
Type: Hidden
Name: P1_SHOW_ANIMATION
Settings -> Value Protected: FALSE
Durante la ejecución del proceso, estableceremos su valor a YES, y usaremos ese valor para mostrar nuestra animación usando JavaScript.
4. Crear el proceso PL/SQL
Ahora creamos el proceso que ejecutará el botón.
Processing → Create Process
Configuración:
Name: RUN_PROCESS
Type: Execute Code
Point: Processing
Código PL/SQL:
BEGIN
-- Simulación de lógica de negocio
dbms_session.sleep(3);
-- Activamos la bandera para mostrar la animación
if :P1_SHOW_ANIMATION is null then
:P1_SHOW_ANIMATION := 'YES';
else
:P1_SHOW_ANIMATION := null;
end if;
END;
En un escenario real aquí podríamos tener:
inserciones,
llamadas a APIs,
cálculos,
o cualquier otra lógica de negocio
Para el ejemplo simplemente simulamos un proceso que tarda unos segundos.
5. Crear un Ajax Callback
Antes de continuar vamos a crear un Ajax Callback.
De momento solo necesitamos crearlo; dentro de un momento veremos por qué será necesario, pero se puede intuir que nos hace falta al estar todo en una misma página.
Create Process → Ajax Callback
Name: CLEAR_ANIMATION_FLAG
Código:
BEGIN
APEX_UTIL.SET_SESSION_STATE('P1_SHOW_ANIMATION', NULL);
END;
Este proceso nos permitirá limpiar la variable de sesión (nuestro flag) una vez que la animación haya sido mostrada.
6. Crear el diálogo donde se mostrará la animación
Ahora creamos una región que actuará como diálogo de confirmación.
Create → Region
Type: Static Content
Title: Process completed
En las propiedades avanzadas de la región:
Template: Popup Dialog
Static ID: success_dialog
Dentro del contenido HTML de la región añadimos el contenedor donde Lottie renderizará la animación. Aquí, por supuesto que podéis ser todo lo creativos que os apetezca.
<div id="AnimationContainer" style="width: 260px; height: 260px; margin: 0 auto;"></div>
<p style="text-align:center; margin-top:1rem;">
Proceso completado correctamente.
</p>
Este contenedor será el punto donde la librería cargará la animación.
7. Añadir la librería Lottie
Necesitamos incluir la librería JavaScript. Por comodidad para el ejemplo, lo haremos desde una CDN, pero recordad que podríamos incorporar la librería en nuestros App o Workspace Files. Para ello, añadimos esta URL
<https://cdnjs.cloudflare.com/ajax/libs/lottie-web/5.12.2/lottie.min.js>
en Shared Components → User Interface → JavaScript → File URLs
8. Añadir el JavaScript a la página
En esta parte, entra en juego el código JavaScript que cargará las animaciones.
En la página 1, dentro de Page → JavaScript → Function and Global Variable Declaration, añadimos:
let successAnim;
const animations = [
'<https://lottie.host/2b453cd3-68a3-4d5f-8de1-8b614e119f7c/5j2IMwu9BK.json>',
'<https://lottie.host/d4632a60-aa60-4651-8d89-2b1230ad5a83/miEvthU2mz.json>',
'<https://lottie.host/ecb34e4b-038b-4559-99f8-c95a093acbd1/ktb7Qhvfrp.json>'
];
function showSuccessLottie() {
const container = document.getElementById('AnimationContainer');
if (!container) {
return;
}
const randomAnimation =
animations[Math.floor(Math.random() * animations.length)];
// Clear previous DOM content if needed
container.innerHTML = '';
// Destroy previous animation instance if it exists
if (successAnim) {
successAnim.destroy();
}
successAnim = lottie.loadAnimation({
container: container,
path: randomAnimation,
renderer: 'svg',
loop: true,
autoplay: true,
name: 'success-animation'
});
}
Esta función se encargará de:
elegir una animación aleatoria, de las tres disponibles, que hemos sacado de este enlace, y que mostramos a partir de una CDN,
inicializar Lottie,
y renderizar nuestra animación en el contenedor del diálogo.

9. Ejecutar la animación al cargar la página
Por último añadimos el código que controla cuándo debe mostrarse la animación.
En el atributo inmediatamente inferior al anterior, Page → JavaScript → Execute when Page Loads, añadimos:
apex.jQuery(function ($) {
if ($v('P1_SHOW_ANIMATION') === 'YES') {
apex.theme.openRegion('success_dialog');
showSuccessLottie();
// Clear item in browser
$s('P1_SHOW_ANIMATION', '');
// Clear session state in server
apex.server.process('CLEAR_ANIMATION_FLAG', {}, {
dataType: 'text'
});
}
});
Este pequeño bloque coordina toda la lógica del ejemplo:
Comprueba si el proceso activó la bandera.
Abre el diálogo.
Carga una animación Lottie aleatoria.
Limpia el flag para evitar que vuelva a aparecer en un refresh.
Cabe señalar en este punto que podríamos haber seguido una aproximación declarativa, y montar esta acción como Acción dinámica en carga de página, pero ¡seguro que eso podéis resolverlo sin mi ayuda!
10. Ejecutar la aplicación
En este punto, guardamos los cambios y ejecutamos la aplicación. Tan pronto pulsemos nuestro botón, el proceso PL/SQL se ejecuta, la página se recarga, se abre el diálogo de confirmación y se reproduce una animación Lottie elegida aleatoriamente.
De un modo sencillo, hemos aprendido a extender nuestra aplicación con un pequeño detalle visual que aporta una experiencia de usuario mucho más agradable que un simple mensaje de confirmación.
Buenas prácticas y consideraciones de rendimiento
El ejemplo anterior cumple bien su objetivo: demostrar que integrar una librería JavaScript externa en Oracle APEX puede ser algo bastante directo y que el resultado visual puede elevar mucho la percepción de calidad de una aplicación.
Ahora bien, como casi siempre ocurre, una demo sencilla no debería trasladarse a producción sin pasar antes por algunas consideraciones adicionales.
Evitar dependencias externas cuando el entorno es corporativo
En el ejemplo hemos utilizado un CDN para simplificar la explicación y varias animaciones alojadas en URLs externas de LottieFiles. Para una prueba rápida es perfectamente válido, pero en un entorno productivo lo más razonable suele ser:
subir la librería
lottie.min.jsa Static Application Filesalmacenar también los JSON de las animaciones dentro de la propia aplicación
versionar estos recursos junto con el resto del desarrollo
Esto reduce dependencias externas, evita problemas de conectividad y facilita despliegues controlados entre entornos.
No abusar de las animaciones
Una animación puede mejorar mucho la experiencia de usuario. Varias animaciones simultáneas, repetitivas o mal ubicadas pueden conseguir exactamente lo contrario.
Como norma general, Lottie funciona especialmente bien en:
confirmaciones de éxito
estados vacíos
indicadores de carga
onboarding o pantallas introductorias
pequeños refuerzos visuales en zonas concretas
No debería convertirse en un elemento decorativo omnipresente. En aplicaciones APEX, y especialmente en entornos enterprise, normalmente funciona mejor cuando aporta contexto o feedback real al usuario.
Cuidado con el loop: true
En el ejemplo hemos dejado la animación en bucle continuo porque visualmente resultaba más agradecido para la demo. Sin embargo, en muchos casos reales tendrá más sentido:
reproducir una sola vez
cerrar el diálogo automáticamente tras unos segundos
o permitir que el usuario lo cierre manualmente
Si el objetivo es reforzar una confirmación, dejar la animación en bucle infinito puede acabar siendo innecesario o incluso molesto.
Limpiar correctamente estado y recursos
Aquí hay dos detalles importantes que conviene no olvidar.
Por un lado, si utilizamos un item como P1_SHOW_ANIMATION para coordinar backend y frontend, debemos asegurarnos de limpiarlo no solo en cliente, sino también en session state, como hemos hecho mediante el Ajax Callback.
Por otro, cuando reutilizamos un mismo contenedor para varias animaciones, conviene destruir la instancia anterior con successAnim.destroy() antes de crear una nueva. Esto evita comportamientos extraños y mantiene el DOM más limpio.
Evitar latencia artificial en producción
En el ejemplo hemos usado una pausa deliberada en PL/SQL para simular un proceso que tarda unos segundos y hacer visible el flujo completo. Como recurso didáctico funciona bien, pero en una aplicación real no deberíamos introducir retardos artificiales como parte del comportamiento normal.
Si un proceso tarda, la animación puede servir como feedback visual útil. Si no tarda, no tiene sentido forzarlo solo para justificar el efecto.
Pensar en accesibilidad y contexto de uso
No todos los usuarios reaccionan igual ante elementos animados, y no todos los contextos requieren el mismo nivel de expresividad visual. Conviene plantearse siempre si la animación:
aporta información útil
ayuda a interpretar mejor el estado del sistema
o simplemente adorna sin mejorar realmente la interacción
En otras palabras: en APEX, como en casi cualquier otra capa de interfaz, menos suele ser más.
Ideas de uso en aplicaciones APEX reales
Más allá del ejemplo de este artículo, este patrón puede aplicarse de forma bastante natural en otros puntos de una aplicación:
diálogos de confirmación tras procesos de negocio
estados vacíos en informes o dashboards
loaders personalizados durante llamadas Ajax
mensajes de bienvenida o onboarding
feedback visual tras acciones largas o especialmente relevantes
Aquí es donde Lottie empieza a tener sentido de verdad: no como un “extra visual”, sino como una herramienta más dentro del diseño de experiencia de usuario de una aplicación APEX.
Conclusión
Una de las grandes virtudes de Oracle APEX es que nos permite avanzar muy rápido con un enfoque declarativo, pero sin cerrarnos la puerta al ecosistema web moderno. Y precisamente por eso integrar una librería como Lottie.js resulta tan interesante: no obliga a romper APEX, sino simplemente a extenderlo con criterio.
A lo largo del ejemplo hemos visto que, con muy pocas piezas, podemos construir una interacción bastante más rica que el clásico mensaje de confirmación:
un proceso PL/SQL
un flag de control
un
Ajax Callbackuna región tipo diálogo
y una pequeña capa JavaScript a nivel de página
No es una integración compleja, pero sí lo bastante expresiva como para demostrar una idea importante:
APEX puede apoyarse en librerías JavaScript externas de forma limpia, mantenible y perfectamente compatible con su modelo de trabajo.
Como casi siempre, la clave no está en añadir efectos por añadirlos, sino en utilizarlos donde realmente aporten valor. Una animación ligera, bien ubicada y alineada con el flujo funcional de la aplicación puede mejorar bastante la experiencia percibida por el usuario. Y eso, en ciertos proyectos, marca una diferencia real.
Lottie es solo un ejemplo, pero también sirve para ilustrar algo más amplio: cuando entendemos bien cómo se carga una librería, cómo se coordina con el ciclo de vida de una página APEX y cómo separar la lógica visual del backend, el abanico de posibilidades se amplía bastante.
Y seguramente ahí esté una de las mejores noticias para quienes trabajamos con APEX: seguir aprovechando toda la velocidad del desarrollo declarativo, sin renunciar a enriquecer la interfaz cuando el proyecto lo necesita.
Como siempre, ¡gracias por llegar hasta aquí!
Happy coding,
Juan L.






