Tabla de contenido
Una vez más aquí. Hoy vengo a dejar un pequeño artículo sobre algo que me ha preguntado vía correo electrónico hace unos días. El caso es que imagino que este usuario está estudiando JavaScript, y me preguntó ¿cómo podría crear un reloj en forma de ruleta? La verdad es que no tengo muy claro a qué se refería exactamente, pero tras pensarlo un poco, creo que esto que vamos a ver a continuación, podría serle útil. Aun que como siempre, que cada cual adapte el código como necesite.
Este reloj digital que vamos a ver tiene la funcionalidad clásica de un reloj, y le vamos a dar un diseño un poco diferente que lo hace bastante llamativo. Ya sea que estés buscando una forma creativa de mantener el tiempo o simplemente quieras agregar un toque de estilo a tu espacio, el Reloj en forma de ruleta puede ser una elección perfecta.
Características de este reloj en forma de ruleta

- El reloj en forma de ruleta cuenta con un diseño visualemente llamativo. Su interfaz presenta una distribución única de dígitos que giran, creando un efecto «hipnotizante». Cada número está animado, proporcionando una experiencia de visualización atractiva y única.
- Tocando un poco las reglas CSS se puede personalizar de forma sencilla el esquema de colores según lo que cada uno quiera, lo cual permitirá integrar perfectamente el reloj en cualquier entornor.
- Además de mostrar la hora, el reloj también nos mostrará la fecha actual. La fecha se representa de una manera elegante, siguiendo el mismo estilo del reloj. Esto permitirá que el usuario obtenga tanto la fecha como la hora de un solo vistazo.
- A pesar de su diseño único, el Reloj Ruleta mantiene una visualización clara y precisa del tiempo. Los dígitos se actualizan sin problemas, garantizando que siempre tengas la hora exacta.
- Modificando mínimamente el código JavaScript, se puede elegir entre un formato de 12 o 24 horas, según tus preferencias.
El código del reloj en forma de ruleta
El Reloj Ruleta representa la perfecta convergencia entre arte y funcionalidad. Este reloj te ofrece una forma única de experimentar el paso del tiempo. Para crearlo, solo es necesario utilizar tres archivos combinados, uno html, otro CSS, y otro JS. A continuación vamos a ver que vamos a incluir dentro de cada uno de estos archivos.
Archivo Index.html
El archivo HTML va a proporcionar la estructura básica de la página web. Contiene elementos como la etiqueta div
que contiene el reloj y la fecha, y enlaces a los archivos CSS y JavaScript necesarios.
Dentro de este archivo vamos a encontrarnos el siguiente código:
<!DOCTYPE html> <html lang="es"> <head> <meta charset="UTF-8"> <title>Reloj ruleta</title> <link rel="icon" type="image/vnd.icon" href="favicon.ico"> <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> <link rel='stylesheet' href='https://fonts.googleapis.com/css2?family=Comfortaa:wght@300;400;700&display=swap'> <link rel="stylesheet" href="./style.css"> </head> <body> <div class="container"> <!--Fecha--> <div class="date-container"> <div class="date date-capitalized"></div> </div> <!--Reloj--> <div class="clock" aria-label="00:00:00"> <div class="clock__unit clock_unit--hr" aria-hidden="true" data-unit="h"> <div class="clock__digits" data-unit-pos>00</div> <div class="clock__digits" data-unit-pos>00</div> <div class="clock__digits" data-unit-pos>00</div> <div class="clock__digits" data-unit-pos>00</div> <div class="clock__digits" data-unit-pos>00</div> <div class="clock__digits" data-unit-pos>00</div> <div class="clock__digits" data-unit-pos>00</div> </div> <div class="clock__colon">:</div> <div class="clock__unit clock__unit--min" aria-hidden="true" data-unit="m"> <div class="clock__digits" data-unit-pos>00</div> <div class="clock__digits" data-unit-pos>00</div> <div class="clock__digits" data-unit-pos>00</div> <div class="clock__digits" data-unit-pos>00</div> <div class="clock__digits" data-unit-pos>00</div> <div class="clock__digits" data-unit-pos>00</div> <div class="clock__digits" data-unit-pos>00</div> </div> <div class="clock__colon">:</div> <div class="clock__unit clock__unit--sec" aria-hidden="true" data-unit="s"> <div class="clock__digits" data-unit-pos>00</div> <div class="clock__digits" data-unit-pos>00</div> <div class="clock__digits" data-unit-pos>00</div> <div class="clock__digits" data-unit-pos>00</div> <div class="clock__digits" data-unit-pos>00</div> <div class="clock__digits" data-unit-pos>00</div> <div class="clock__digits" data-unit-pos>00</div> </div> </div> </div> <script src="./script.js"></script> </body> </html>
El archivo CSS
Este archivo CSS contiene las reglas de estilo que determinan la apariencia de la aplicación. Define variables para colores y configuraciones de estilo, así como estilos específicos para elementos como el reloj y la fecha.
Dentro del archivo, vamos a encontrarnos el siguiente código:
* { border: 0; box-sizing: border-box; margin: 0; padding: 0; } :root { --hue: 290; --bg: hsl(var(--hue), 90%, 90%); --fg: hsl(var(--hue), 90%, 10%); --primary: hsl(var(--hue), 90%, 50%); --trans-dur: 0.3s; font-size: calc(40px + (80 - 40) * (100vw - 320px) / (2560 - 320)); } body { background-color: var(--bg); color: var(--fg); font: 1em/1.5 "Comfortaa", sans-serif; height: 100vh; transition: background-color var(--trans-dur), color var(--trans-dur); } /* Contenedor del reloj y la fecha */ .container { display: flex; flex-direction: column; justify-content: center; align-items: center; height: 100vh; text-align: center; } /* Fecha */ .date-container { text-align: center; font-family: "Comfortaa", sans-serif; font-size: calc(28px + (80 - 40) * (100vw - 320px) / (2560 - 320)); margin-top: 1rem; } .date { line-height: 1; text-align: center; font-size: inherit; /* Usa el tamaño de fuente heredado */ color: #a2a2a2; } /* Capitalizar la primera letra del día */ .date-capitalized:first-letter { text-transform: uppercase; } /* Reloj */ .clock { display: flex; align-items: center; margin: 0px; } .clock__colon, .clock__digits { line-height: 1; height: 1rem; text-align: center; } .clock__digits { font-variation-settings: "wght" 300; width: 2rem; } .clock__digits:nth-child(1), .clock__digits:nth-child(7) { transform: scale(0); } .clock__digits:nth-child(2), .clock__digits:nth-child(6) { transform: scale(0.33); } .clock__digits:nth-child(3), .clock__digits:nth-child(5) { transform: scale(0.67); } /* Línea central de números*/ .clock__digits:nth-child(4) { font-variation-settings: "wght" 800; border: 1px solid #fff; margin-top: 5px; margin-bottom: 5px; background-color: #a2a2a2; color: #000; padding-top: 5px; padding-bottom: 5px; } .clock__digits:not(:nth-child(4)) { user-select: none; -moz-user-select: none; -webkit-user-select: none; } .clock__unit--rolling .clock__digits { animation: digitsMove1 0.3s ease-in-out; } .clock__unit--rolling .clock__digits:nth-child(2) { animation-name: digitsMove2; } .clock__unit--rolling .clock__digits:nth-child(3) { animation-name: digitsMove3; } .clock__unit--rolling .clock__digits:nth-child(4) { animation-name: digitsMove4; } .clock__unit--rolling .clock__digits:nth-child(5) { animation-name: digitsMove5; } .clock__unit--rolling .clock__digits:nth-child(6) { animation-name: digitsMove6; } .clock__unit--rolling .clock__digits:nth-child(7) { animation: none; } /* Oscurecer fondo */ @media (prefers-color-scheme: dark) { :root { --bg: hsl(var(--hue), 90%, 10%); --fg: hsl(var(--hue), 90%, 90%); } } /* Animaciones */ @keyframes digitsMove1 { from { transform: translateY(100%) scale(0.33); } to { transform: translateY(0) scale(0); } } @keyframes digitsMove2 { from { transform: translateY(100%) scale(0.67); } to { transform: translateY(0%) scale(0.33); } } @keyframes digitsMove3 { from { font-variation-settings: "wght" 700; transform: translateY(100%) scale(1); } to { font-variation-settings: "wght" 300; transform: translateY(0) scale(0.67); } } @keyframes digitsMove4 { from { font-variation-settings: "wght" 300; transform: translateY(100%) scale(0.67); } to { font-variation-settings: "wght" 700; transform: translateY(0) scale(1); } } @keyframes digitsMove5 { from { transform: translateY(100%) scale(0.33); } to { transform: translateY(0) scale(0.67); } } @keyframes digitsMove6 { from { transform: translateY(100%) scale(0); } to { transform: translateY(0) scale(0.33); } }
El archivo JS
El código JavaScript se encarga de la funcionalidad del reloj. Crea una instancia de la clase Clock2
que maneja la actualización del tiempo y la fecha. Esta clase utiliza métodos para obtener y formatear la hora y la fecha, y actualiza la interfaz de usuario en consecuencia.
Dentro de este archivo, encontraremos el código:
window.addEventListener("DOMContentLoaded",() => { const c = new Clock2(".clock",true); }); class Clock2 { now = null; then = null; constructor(el,is24Hours = false) { this.el = document.querySelector(el); this.is24Hours = is24Hours; this.init(); } init() { this.timeUpdate(); } get timeAsObject() { const date = new Date(); let h = date.getHours(); const m = date.getMinutes(); const s = date.getSeconds(); const ap = h > 11 ? "PM" : "AM"; // milisegundos desde 1/1/1970 Gnu const since1970 = date.getTime() - date.getTimezoneOffset() * 60 * 1000; // tratar con medianoche y 13:00 si no se utiliza el reloj de 24 horas if (!this.is24Hours) { if (h === 0) h += 12; else if (h > 12) h -= 12; } return { h, m, s, ap, since1970 }; } get timeAsString() { let { h, m, s, ap } = this.timeAsObject; // anteponer 0 al minuto y segundo si son de un solo dígito if (m < 10) m = `0${m}`; if (s < 10) s = `0${s}`; let timestamp = `${h}:${m}:${s}`; if (!this.is24Hours) timestamp += ` ${ap}` return timestamp; } timeUpdate() { // actualizar etiqueta `aria-label` this.el?.setAttribute("aria-label", this.timeAsString); // reset animación const rolling = "clock__unit--rolling"; const unitEls = Array.from(this.el.querySelectorAll(`[data-unit]`)); unitEls.forEach(el => { el.classList.remove(rolling); }); void this.el.offsetWidth; // actualizar los objetos de tiempo this.then = this.now; this.now = this.timeAsObject; const { then, now } = this; Object.keys(now).forEach(unit => { const unitEl = this.el.querySelector(`[data-unit="${unit}"]`); if (!unitEl) return // añadir la animación rondante cuando los dígitos no sean iguales if (then !== null && then[unit] !== now[unit]) unitEl.classList.add(rolling); // actualizar los dígitos const unitPos = Array.from(unitEl.querySelectorAll(`[data-unit-pos]`)); let posIndex = -3; unitPos.forEach(pos => { let digits = now[unit] + posIndex; const unitLoop = unit === "h" ? 24 : 60; if (digits < 0) digits += unitLoop; else if (digits >= unitLoop) digits -= unitLoop; let digitsString = `${digits}`; if (digits < 10) digitsString = `0${digits}`; pos.innerText = digitsString; ++posIndex; }); }); // loop clearTimeout(this.timeUpdateLoop); this.timeUpdateLoop = setTimeout(this.timeUpdate.bind(this),1e3); } // Fecha updateDate() { const dateEl = document.querySelector('.date'); const dateOptions = { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' }; const today = new Date(); const formattedDate = today.toLocaleDateString('es-ES', dateOptions); const modifiedDate = formattedDate.replace(/(\s[a-z])/g, match => match.toUpperCase()); dateEl.textContent = modifiedDate; } init() { this.timeUpdate(); this.updateDate(); // Inicializar la fecha. } }
Este reloj en forma de ruleta se puede ver funcionando el siguiente enlace. Además, el código aquí mostrado, también se puede descargar desde el repositorio en GitHub en el que lo he alojado.
Para el usuario que me lo ha pedido, le digo que espero que este ejemplo te sea útil. Asegúrate de personalizarlo con detalles específicos que te pidieran. ¡Si necesitas más ayuda o ajustes, no dudes en decírlo en los comentarios!