Muy buenas tardes por la mañana, en este bello día vamos a dedicar las horas a crear un cronómetro desde cero. Sí, has oído bien.

  • Desde cero
  • Usando HTML
  • CSS para el diseño
  • Y Javascript para la funcionalidad

Además vas a tener a tu disposición el código para descargarlo y un vídeo para ver todo el proceso paso a paso.

Descarga el código aquí.

Mira el vídeo aquí.

Sin más tonterías, vayamos hacia lo que nos interesa.

Parte 1. La interfaz del cronómetro

Crearemos la interfaz metiendo un poco de HTML y un poco de CSS, nada del otro mundo. Simple.

Para la parte estructural, el HTML, meteremos esto:

<!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>Cronómetro</title>
    <link href="https://fonts.googleapis.com/css2?family=Roboto+Mono:wght@100&display=swap" rel="stylesheet">
    <link href="styles.css" rel="stylesheet">
    <script src="script.js" defer></script>
</head>
<body>
    <main>
        <div class="circle">
            <div id="stopwatch" class="stopwatch">00:00</div>
            <div class="buttons">
                <div class="stop" onclick="stop()"></div>
                <div id="play-pause" class="paused" onclick="playPause()"></div>
            </div>
        </div>
        <div id="seconds-sphere" class="seconds-sphere"></div>
    </main>
</body>
</html>

Ya ves que no es ninguna locura, un simple contenedor al que hemos asociado una clase llamada circle, para poder darle estilo después. Y bueno, un par de elementos más en los que luego meteremos cositas con Javascript.

El código CSS para que el asunto quede medianamente decente es el siguiente:

main {
    font-family: 'Roboto Mono', monospace;
    position: relative;
}

.circle {
    border-radius: 50%;
    width: 120px;
    height: 120px;
    border: 1px solid #fff;
    color: #fff;
    margin: 50px auto;
    display: flex;
    justify-content: center;
    align-items: center;
    flex-direction: column;
}

.circle::before {
    content: '';
    border-radius: 50%;
    z-index: -1;
    position: absolute;
    width: 160px;
    height: 160px;
    left: calc(50% - 80px);
    top: calc(50% - 80px);
    background-color: #1d1d1d;
}

.seconds-sphere {
    width: 20px;
    height: 20px;
    border-radius: 50%;
    background-color: #fff;
    position: absolute;
    left: calc(50% - 10px);
    top: calc(50% - 10px);
    animation: rotacion 60s linear infinite;
    animation-play-state: paused;
}

@keyframes rotacion {
	from { 	transform: rotate(-90deg) translateX(60px); }
	to   {  transform: rotate(270deg) translateX(60px); }
}

.buttons {
    margin-top: 10px;
    display: inline-flex;
}

.paused {
    height: 10px;
    border-width: 5px 0 5px 10px;
    cursor: pointer;
    box-sizing: border-box;
    margin-left: 15px;
    border-color: transparent transparent transparent #fff;
    transition: 100ms all ease;
    will-change: border-width;
    border-style: solid;
}

.running {
    border-style: double;
    border-width: 0 0 0 10px;
}

.stop {
    background-color: #fff;
    height: 10px;
    width: 10px;
    cursor: pointer;
}

Es obvio que tú puedes editarlo a tu gusto, además es lo mejor que puedes hacer para aprender. Partir de esta base y luego cambiar cosas. Aunque sea un simple cambio de colores, ya es mucho más que los que no hacen nada. Así que ya sabes... marcha y motivación.

Parte 2. La lógica para controlar el tiempo

Necesitarás que tu precioso cronómetro haga algo. Porque simplemente dibujar un reloj en la pantalla no es suficiente. Lo que queremos es que funcione y el usuario pueda utilizarlo para algo práctico, como por ejemplo para hervir la pasta y dejarla al dente.

¿Te parece buena idea?

Yo creo que sí. Pues... vamos.

Si no tienes ganas de mirarte el vídeo, que sepas que la implementación en Javascript quedaría así:

const stopwatch = document.getElementById('stopwatch');
const playPauseButton = document.getElementById('play-pause');
const secondsSphere = document.getElementById('seconds-sphere');

let stopwatchInterval;
let runningTime = 0;

const playPause = () => {
    const isPaused = !playPauseButton.classList.contains('running');
    if (isPaused) {
        playPauseButton.classList.add('running');
        start();
    } else {
        playPauseButton.classList.remove('running');
        pause();
    }
}

const pause = () => {
    secondsSphere.style.animationPlayState = 'paused';
    clearInterval(stopwatchInterval);
}

const stop = () => {
    secondsSphere.style.transform = 'rotate(-90deg) translateX(60px)';
    secondsSphere.style.animation = 'none';
    playPauseButton.classList.remove('running');
    runningTime = 0;
    clearInterval(stopwatchInterval);
    stopwatch.textContent = '00:00';
}

const start = () => {
    secondsSphere.style.animation = 'rotacion 60s linear infinite';
    let startTime = Date.now() - runningTime;
    secondsSphere.style.animationPlayState = 'running';
    stopwatchInterval = setInterval( () => {
        runningTime = Date.now() - startTime;
        stopwatch.textContent = calculateTime(runningTime);
    }, 1000)
}

const calculateTime = runningTime => {
    const total_seconds = Math.floor(runningTime / 1000);
    const total_minutes = Math.floor(total_seconds / 60);

    const display_seconds = (total_seconds % 60).toString().padStart(2, "0");
    const display_minutes = total_minutes.toString().padStart(2, "0");

    return `${display_minutes}:${display_seconds}`
}

Seguro que has conseguido copiar y pegar el código y hacerlo funcionar.

También puedes echarle un ojo si quieres a cómo crear una calculadora con HTML, Javascript y CSS.