Hace ya bastante tiempo, en mi aplicación personal de Oracle APEX (donde tengo mi currículum/portafolio), agregué una sección tipo “juego” para que la comunidad interactúe: una Ruleta de la Fortuna.
Con el tiempo, muchos alumnos y gente de la comunidad me empezaron a preguntar lo mismo:
“¿Cómo hiciste esa ruleta en APEX?”
La respuesta es que no es un “truco” ni un plugin raro: es Canvas + JavaScript + CSS, pero bien armado y bien integrado al flujo de APEX. Y lo mejor es que, una vez que entendemos la base, se puede llevar a un nivel totalmente usable en una app real.
En este artículo te voy a mostrar paso a paso cómo construir la base completa de la ruleta desde cero en una app nueva. La idea es que al terminar tengas una rueda responsive, con flecha, premios, textos y botón para girar, lista para que después le agregues la parte de “reclamar” cupones o cualquier premio que se te ocurra.
Resultado final
Al terminar vas a tener en APEX:
-
Ruleta circular y responsive (se adapta en móvil y escritorio)
-
Secciones con colores + texto
-
“Flecha” (puntero) arriba (dibujada en Canvas)
-
Botón Girar que inicia el giro
-
Lista informativa de premios debajo (opcional)
1) Crear la aplicación
Vamos a crear una nueva aplicación en nuestro espacio de trabajo
Nombre: GIRA_Y_GANA_DEMO
Crear una página en blanco:
-
-
Page: 2
-
Nombre: Ruleta de la Fortuna (o “Gira y gana”, como prefieras 🙂 )
-
2) Subir los archivos (JS y CSS) a APEX
Si no subís estos archivos, la ruleta se verá mal y/o no funcionará.
Descargar los archivos AQUI
Componentes Compartidos → Static Application Files
Subí estos archivos:
-
-
styles-rueda-fortuna.css(APEX te crea también styles-rueda-fortuna.min.css) -
rueda-de-la-fortuna.js(APEX te crea también rueda-de-la-fortuna.min.js)
-
3) Enlazar los archivos en la Página 2
En la página 2 ir a las propiedades de la pagina y hacer las referencias a estos archivos:
JavaScript File URLs
#APP_FILES#rueda-de-la-fortuna.js – (si lo usas en producción utiliza el archivo #APP_FILES#rueda-de-la-fortuna.min.js)
CSS File URLs
#APP_FILES#styles-rueda-fortuna.css – (si lo usas en producción utiliza el archivo styles-rueda-fortuna.min.css)
4) Crear la región con el Canvas y el botón “Girar”
En la página 2 creá una región:
-
Type: Static Content
-
Title: Ruleta
- Template: Blank with Attributes
-
(Opcional) Static ID:
ruleta_area
En el Source pegá este HTML:
<div class="ruleta-container" style="text-align:center;"> <h1>¡Girá y ganá!</h1> <p>Probá tu suerte</p> <canvas id="wheelCanvas" style="max-width: 90%; height: auto;"></canvas> <button id="spinButton" type="button">Girar</button> <!-- Resultado del giro --> <div id="resultadoPremio" class="resultado-premio"></div> </div>
Importante:
-
id=wheelCanvasdebe llamarse así porque archivo JS lo usa para dibujar la ruleta. -
id=spinButtondebe llamarse así porque también el archivo JS engancha el evento del click. -
id=resultadoPremiodebe existir porque el archivo JS lo usa para mostrar el texto “Premio obtenido: …” al terminar el giro.
5) (Opcional) Región con los premios / cupones
Creá otra región Static Content debajo, con template Balnk with Attributes y pegá el siguiente código:
<div id="cursos"> <h2>Cupones disponibles</h2> <h3>Oracle APEX en Español</h3> <h5>Curso online: Ejemplo Demo 1</h5> <p>A - 10 Off --> cupón de 10% de descuento</p> <p>A - 20 Off --> cupón de 20% de descuento</p> <p>A - 25 Off --> cupón de 25% de descuento</p> <h5>Curso online: Ejemplo Demo 2</h5> <p>B - 10 Off --> cupón de 10% de descuento</p> <p>B - 20 Off --> cupón de 20% de descuento</p> <p>B - 25 Off --> cupón de 25% de descuento</p> <h5>Curso online: Ejemplo Demo 3</h5> <p>C - 10 Off --> cupón de 10% de descuento</p> <p>C - 20 Off --> cupón de 20% de descuento</p> <p>C - 25 Off --> cupón de 25% de descuento</p> </div>
6) CSS completo (styles-rueda-fortuna.css)
Este CSS es el que hace que se vea bien, centrado y responsive:
/* =========================================================
RUEDA DE LA FORTUNA - estilos base (responsive)
Archivo: styles-rueda-fortuna.css
========================================================= */
.ruleta-container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
width: 100%;
max-width: 500px;
margin: 0 auto;
}
canvas {
width: 100%;
height: auto;
max-width: 500px;
border-radius: 50%;
border: 5px solid #333;
}
#spinButton {
margin-top: 20px;
padding: 10px 20px;
font-size: 20px;
background-color: green;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
}
#spinButton:hover {
background-color: darkgreen;
}
/* Texto del resultado (Premio obtenido / Ganaste) */
.resultado-premio{
margin-top: 10px;
font-size: 14px; /* <-- acá se achica */
font-weight: 600;
color: #333;
}
/* Opcional: sección de cursos */
#cursos {
background-color: #f0f0f0;
text-align: center;
padding: 15px;
border-radius: 10px;
margin-top: 20px;
}
7) Qué hace el JavaScript (en términos simples)
El archivo rueda-de-la-fortuna.js hace estas tareas clave:
resizeCanvas()
Ajusta el tamaño real del canvas (width y height) para que la ruleta sea circular y se adapte al ancho disponible. Cada vez que cambia el tamaño, vuelve a dibujar la ruleta.
drawRouletteWheel()
Dibuja toda la ruleta: segmentos con colores, textos, el círculo central con “APEX” y llama al puntero.
drawPointer()
Dibuja la flecha/puntero arriba del canvas, que es lo que “marca” el premio final cuando se detiene la rueda.
rotateWheel()
Hace la animación del giro con setTimeout() cada ~30ms y aplica desaceleración gradual multiplicando la velocidad por decelerationFactor.
stopRotateWheel()
Cuando la velocidad ya es mínima, detiene el giro, calcula el premio ganador según el ángulo final y lo muestra debajo en #resultadoPremio. También vuelve a mostrar el botón “Girar”.
bindSpinButton()
Registra el click del botón spinButton, evita doble click usando isSpinning, genera una velocidad inicial aleatoria y dispara la animación.
8) Conclusión
Con esto ya tenés la base real de la ruleta funcionando dentro de Oracle APEX: se dibuja en Canvas, es responsive, gira con desaceleración y te devuelve un premio al final. Nada de magia, solo JavaScript bien aplicado y ordenado.
Lo importante de este primer paso es que te queda una estructura limpia para seguir creciendo sin romper todo después. En el próximo artículo vamos a dar el salto a lo que la gente suele querer de verdad: cómo conectar el premio con APEX, cómo manejar el “reclamo” del cupón y cómo evitar que los links queden expuestos en el código del navegador.
Aviso / Disclaimer
Este artículo es 100% educativo. Los scripts, ejemplos y archivos descargables (PL/SQL, SQL, JavaScript y CSS) se entregan “tal cual” (AS IS), sin garantías de ningún tipo: ni de funcionamiento, ni de seguridad, ni de compatibilidad, ni de que sea “listo para producción”.
Cada persona es responsable de importar, configurar, revisar, adaptar y probar todo en su propio entorno antes de usarlo en una aplicación real. Según la versión de Oracle APEX/ORDS, el tipo de autenticación, las políticas de seguridad, timeouts, CSP, permisos del workspace y configuración de la app, puede requerir ajustes.
Este ejemplo no debe copiarse y pegarse en producción sin los cuidados necesarios: revisión de seguridad, validaciones adicionales, auditoría, manejo de sesiones, control de reintentos, limpieza de tokens vencidos, monitoreo y pruebas completas.
La autora no asume responsabilidad por pérdidas de datos, fallas, interrupciones, problemas de seguridad o cualquier consecuencia derivada del uso (o mal uso) de este material.
— Ing. Clarisa Maman Orfali














