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=wheelCanvas debe llamarse así porque archivo JS lo usa para dibujar la ruleta.

  • id=spinButton debe llamarse así porque también el archivo JS engancha el evento del click.

  • id=resultadoPremio debe 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