En este tutorial te explicaré paso a paso como implementar un contador regresivo (ó en ingles Countdown Timer) en HTML, con SVG para dibujar las formas, con CSS para los estilos visuales y con JavaScript para realizar el conteo regresivo y las animaciones. Nota: No usaremos ninguna librería extra así que nuestro código será rápido y ligero. Empecemos!
No olvides seguirnos en nuestras redes sociales y nuestra canal de Youtube donde publicamos contenidos relacionados con el desarrollo frontend. Síguenos, dale like y suscríbete, nos ayudas a seguir publicando más contenidos que pueden ayudar a muchos!
Mockup / Wireframe
Indice:
Video de codificación
Estructura HTML
La parte de HTML, tal como se ve en el mockup, tendrá un texto de cabecera y los círculos, y dentro de estos una etiqueta para los días, horas, minutos y segundos respectivamente.
Para efectuar el efecto de los circulos en teoría funciona así:
Un div en forma de circulo con un fondo transparente y un borde grueso.
El siguiente elemento será un SVG, y dentro una forma de circulo. Usamos aquí SVG por que a este circulo le crearemos el efecto de desplazamiento tipo ajuga de reloj.
Finalmente al frente un etiqueta con el texto del conteo regresivo, sea dia, hora, minutos o segundo.
index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Countdown timer</title> <link rel="stylesheet" href="css/style.css"> </head> <body> <section class="container"> <h1>Comming soon</h1> <p>Save the date</p> <div class="charts"> <div class="chart"> <!-- un circulo inicial de fondo --> <div class="circle center-abs"></div> <!-- area para SVG --> <svg class="center-abs" width="150" height="150"> <!-- un segundo circulo en SVG con su ubicacion en coordenadas x,y y el radio de expansion --> <circle class="outer" cx="75" cy="75" r="70" /> </svg> <!-- etiqueta para el contador, en este caso el dia --> <span class="text center-abs" id="days"></span> <h3>Days</h3> </div> <div class="chart"> <div class="circle center-abs"></div> <svg class="center-abs" width="150" height="150"> <circle class="outer" cx="75" cy="75" r="70" /> </svg> <span class="text center-abs" id="hours"></span> <h3>Hours</h3> </div> <div class="chart"> <div class="circle center-abs"></div> <svg class="center-abs" width="150" height="150"> <circle class="outer" cx="75" cy="75" r="70" /> </svg> <span class="text center-abs" id="minutes"></span> <h3>Minutes</h3> </div> <div class="chart"> <div class="circle center-abs"></div> <svg class="center-abs" width="150" height="150"> <circle class="outer" cx="75" cy="75" r="70" /> </svg> <span class="text center-abs" id="seconds"></span> <h3>Seconds</h3> </div> </div> </section> <script src="js/script.js"></script> </body> </html>
Hoja de estilos
Ahora dar estilo visual a nuestro HTML. Fijate bien sobre todo la parte de los circulos SVG.
Explicaremos algunos atributos para el circulo SVG:
- stroke-width: define el grosor del contorno del circulo.
- stroke-dasharray: define el patrón de rayas y espacios utilizados para pintar el contorno de la forma. A mayor numero más poblado creando un efecto de contorno lleno.
- stroke-dashoffset: define un desplazamiento del patrón de rayas, esta en contraparte con stroke-dasharray. Ejemplo: si stroke-dasharray tiene un valor de 300, y stroke-dashoffset un valor de 150, creara un circulo con un borde solo a la mitad.
style.css
@import url(https://fonts.googleapis.com/css?family=Lato:300,400,700); *{ font-family: 'Lato', 'sans-serif'; padding: 0; margin: 0; box-sizing: border-box; } body{ background-image: url(../images/bg.jpg); background-size: cover; background-repeat: no-repeat; min-height: 100vh; } .container{ max-width: 900px; margin:60px auto; } .container h1, .container p{ color:#fff; text-align: center; padding: 20px 0; } .container h1{ font-size: 4em; } .container p{ font-size: 2em; } .center-abs{ top:40%; left:50%; transform:translate(-50%, -50%); position: absolute; } .charts{ display: flex; } .chart{ position: relative; width:25%; height: 260px; } .chart h3{ color:#fff; font-size: 1.8em; position: absolute; bottom:10px; text-align: center; width: 100%; text-shadow: 1px 1px 10px #000; } .chart svg{ z-index: 2; } /* DIV CIRCULO DE FONDO */ .circle{ width: 150px; height:150px; border-radius: 50%; z-index:1; border:10px #baeaff solid; } .text{ z-index: 3; text-align: center; width: 100%; font-size: 3.8em; font-weight: 700; color:#0096da } /* SVG CIRCULO */ .outer{ fill:transparent; stroke: #0096da; stroke-width: 10; /* grosor del borde */ stroke-dasharray: 439; /* numero de relleno del borde, se usa el mismo valor en el script.js */ transform: rotate(270deg) translate(-150px, 0); /* giramos el circulo para que su apertura sea en la parte superior y ajustamos su posicion */ }
Funciones JavaScript
Para el conteo regresivo existe muchas funciones googleando, encontré una muy práctica y se acomoda a nuestro proyecto es de w3schools.
La vamos a modificar en primer lugar, establecido una fecha distinta a gusto de ustedes (la fecha es en formato ingles).
Además vamos añadir una función extra que capture el valor de la cuenta regresiva y establezca la animación de los círculos.
script.js
// Set the date we're counting down to // Establecer la fecha aqui, en formato ingles var countDownDate = new Date("Oct 20, 2021 14:00:00").getTime(); // Update the count down every 1 second var x = setInterval(function() { // Get today's date and time var now = new Date().getTime(); // Find the distance between now and the count down date var distance = countDownDate - now; // Time calculations for days, hours, minutes and seconds var days = Math.floor(distance / (1000 * 60 * 60 * 24)); var hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)); var minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60)); var seconds = Math.floor((distance % (1000 * 60)) / 1000); // Display the result in the element with id="demo" document.getElementById("days").innerHTML = days; document.getElementById("hours").innerHTML = hours; document.getElementById("minutes").innerHTML = minutes; document.getElementById("seconds").innerHTML = seconds; // aqui añadimos nuestra funcion, para que se segun // el conteo regresivo anime los circulos effectCircle(days, hours, minutes, seconds); }, 1000); effectCircle = function(d, h, m, s){ // valores maximos const max_sec = 60; const max_min = 60; const max_hour = 24; const max_day = 30; // valor del relleno del contorno // ojo es el mismo establecido en la hoja de estilos const strokeDashoffset = 439; var circleSVG = document.getElementsByClassName('outer'); // circulo dias var valPerDay = strokeDashoffset / max_day; // el valor de cada periodo segun la longitud del circulo var size = strokeDashoffset - (valPerDay * d); // restamos el valor del periodo a la longitud del circulo circleSVG[0].style.strokeDashoffset = size; // establemos nuevo valor al la longitud del circulo // circulo horas var valPerHour = strokeDashoffset / max_hour; var size = strokeDashoffset - (valPerHour * h); circleSVG[1].style.strokeDashoffset = size; // circulo minutos var valPerMin = strokeDashoffset / max_min; var size = strokeDashoffset - (valPerMin * m); circleSVG[2].style.strokeDashoffset = size; // circulo segundos var valPerSecond = strokeDashoffset / max_sec; var size = strokeDashoffset - (valPerSecond * s); circleSVG[3].style.strokeDashoffset = size; }
Ahora podremos ejecutar y veremos funcionando nuestro contador, mientras que el borde de los círculos crean un efecto de desplazamiento, similar a: contrario a las ajugas de reloj.
Dudas, preguntas, comentarios me lo hacen llegar, aquí en el post o el video en Youtube espero poder ayudarles.
Descarga el código desde nuestro github. Espero le sirva esta herramienta.