post

[Download] Construa o Seu Próprio Cronometro Online com HTML, CSS e JS

Publicado em: 23/04/2024 / Atualizado em: 23/04/2024

Categorias: BlogCSSHTMLJavaScript (JS)JS

Neste artigo vou disponibilizar todo o código de um cronometro online que usa pouco código HTML, CSS e JavaScript para rodar. Ele pode ser instalado facilmente em qualquer hospedagem simples, e roda muito bem.

Você pode testar ele online neste link: https://sites.projetosdeclientes.com.br/@drive/cronometro-online/

Segue os códigos abaixo para estudo e implementação:

Arquivo (index.html):

<!DOCTYPE html>
<html lang="pt-br">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Contador Online</title>
    <link rel="stylesheet" href="style.css?v=1.1.1">
    <link rel="preconnect" href="https://fonts.googleapis.com">
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
    <link href="https://fonts.googleapis.com/css2?family=DM+Mono:ital,wght@0,300;0,400;0,500;1,300;1,400;1,500&display=swap" rel="stylesheet">
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/confetti.browser.min.js"></script>
</head>
<body>
    
<div class="container">
    <h1>Cronometro Online</h1>
    <div id="display">00:00:00:000</div>
    <div class="buttons">
        <button id="startButton">Iniciar</button>
        <button id="pauseButton" style="display: none;">Pausar</button>
    </div>
    <div id="commentSection" style="display: none;">
        <textarea id="commentText" placeholder="Adicione um comentario..."></textarea>
        <button id="saveTime">Salvar Tempo</button>
    </div>
    <div id="headerSaveTimes" class="headerSaveTimes">
        <div class="title">Tempos salvos:</div>
        <button id="removeAll">Remover Todos</button>
    </div>
    <ul id="savedTimes"></ul>
</div>

<script src="script.js?v=1.1.1"></script>
</body>
</html>

Arquivo (script.js):

let startTime;
let elapsed = 0;
let interval;
const display = document.getElementById('display');
const startButton = document.getElementById('startButton');
const pauseButton = document.getElementById('pauseButton');
const commentSection = document.getElementById('commentSection');
const saveTimeButton = document.getElementById('saveTime');
const removeAllButton = document.getElementById('removeAll');
const savedTimesList = document.getElementById('savedTimes');
const headerSaveTimes = document.getElementById('headerSaveTimes');


// Carrega os tempos salvos quando a página é carregada
document.addEventListener("DOMContentLoaded", () => {
    loadSavedTimes();
});

function updateDisplay(time) {
    let milissegundos = time % 1000;
    let segundos = Math.floor(time / 1000) % 60;
    let minutos = Math.floor(time / 60000) % 60;
    let horas = Math.floor(time / 3600000);
    display.textContent = 
        `${horas.toString().padStart(2, '0')}:${minutos.toString().padStart(2, '0')}:${segundos.toString().padStart(2, '0')}:${milissegundos.toString().padStart(3, '0')}`;
}

function startTimer() {
    if (!interval) {
        startTime = Date.now() - elapsed;
        interval = setInterval(() => {
            elapsed = Date.now() - startTime;
            updateDisplay(elapsed);
        }, 10);
    }
}

function stopTimer() {
    clearInterval(interval);
    interval = null;
}

startButton.addEventListener('click', function() {
    if (startButton.textContent === "Iniciar") {
        startTimer();
        startButton.textContent = "Resetar";
        pauseButton.style.display = "inline";
        pauseButton.textContent = "Pausar";
        commentSection.style.display = 'none';  // Esconder a seção de comentário ao iniciar
    } else { // Resetar
        elapsed = 0;
        updateDisplay(0);
        stopTimer();
        startButton.textContent = "Iniciar";
        pauseButton.style.display = "none";
    }
});

pauseButton.addEventListener('click', function() {
    if (pauseButton.textContent === "Pausar") {
        stopTimer();
        pauseButton.textContent = "Continuar";
        commentSection.style.display = 'block';  // Mostrar a seção de comentário ao pausar
        fireConfetti();
    } else { // Continuar
        startTimer();
        pauseButton.textContent = "Pausar";
        commentSection.style.display = 'none';  // Esconder a seção de comentário ao continuar
    }
});

function fireConfetti() {
    confetti({
        particleCount: 100,
        spread: 70,
        origin: { y: 0.6 }
    });
}

saveTimeButton.addEventListener('click', function() {
    const commentText = document.getElementById('commentText').value;
    const time = display.textContent;
    const savedTimes = JSON.parse(sessionStorage.getItem('savedTimes')) || [];
    savedTimes.push({ time, comment: commentText });
    sessionStorage.setItem('savedTimes', JSON.stringify(savedTimes));
    addTimeToList(time, commentText, savedTimes.length - 1);
    document.getElementById('commentText').value = ''; // Limpar caixa de texto após salvar
});

removeAllButton.addEventListener('click', function() {
    sessionStorage.removeItem('savedTimes');
    savedTimesList.innerHTML = ''; // Limpa a lista na interface
    updateHeaderVisibility();
});

function addTimeToList(time, comment, index) {
    const li = document.createElement('li');
    li.innerHTML = `<div style="position: relative; z-index: 1;"><strong>${time}</strong> - ${comment}</div>`;
    const removeBtn = document.createElement('button');
    removeBtn.innerHTML = '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="18" fill="currentColor" viewBox="0 0 24 26"><path fill-rule="evenodd" d="M2.515 8.638a.875.875 0 0 1 1.013.71l2.328 13.238a1.458 1.458 0 0 0 1.436 1.206h9.416c.708 0 1.314-.509 1.436-1.206l2.328-13.238a.875.875 0 0 1 1.723.304l-2.327 13.237a3.208 3.208 0 0 1-3.16 2.653H7.292a3.208 3.208 0 0 1-3.16-2.653L1.805 9.652a.875.875 0 0 1 .71-1.014Zm7.881-6.43c-.806 0-1.459.653-1.459 1.459v1.458h6.126V3.667c0-.806-.653-1.459-1.459-1.459h-3.208Zm6.416 2.917V3.667A3.208 3.208 0 0 0 13.604.458h-3.208a3.208 3.208 0 0 0-3.209 3.209v1.458H1.5a.875.875 0 1 0 0 1.75h21a.875.875 0 0 0 0-1.75h-5.688Z" clip-rule="evenodd"/></svg>';
    removeBtn.className = 'remove';
    removeBtn.onclick = () => removeTime(index);
    li.appendChild(removeBtn);
    savedTimesList.appendChild(li);
    updateHeaderVisibility();
}

function removeTime(index) {
    const savedTimes = JSON.parse(sessionStorage.getItem('savedTimes')) || [];
    const itemToRemove = savedTimesList.children[index];

    if (itemToRemove) {
        itemToRemove.classList.add('collapsing');
        itemToRemove.addEventListener('animationend', () => {
            savedTimes.splice(index, 1);
            sessionStorage.setItem('savedTimes', JSON.stringify(savedTimes));
            updateListDisplay(); // Redesenha a lista após a remoção
        });
    }
}


function updateListDisplay() {
    savedTimesList.innerHTML = '';
    const savedTimes = JSON.parse(sessionStorage.getItem('savedTimes')) || [];
    savedTimes.forEach((item, index) => addTimeToList(item.time, item.comment, index));
    updateHeaderVisibility();
}

function loadSavedTimes() {
    const savedTimes = JSON.parse(sessionStorage.getItem('savedTimes')) || [];
    savedTimes.forEach((item, index) => addTimeToList(item.time, item.comment, index));
    updateHeaderVisibility();
}

function updateHeaderVisibility() {
    const hasItems = savedTimesList.children.length > 0;
    headerSaveTimes.style.display = hasItems ? 'flex' : 'none';
}

Arquivo (style.css):

/* style.css */
body, html {
    height: 100%;
    margin: 0;
    font-family: 'DM Mono', monospace;
    background-color: #f5f5f5;
    display: flex;
    justify-content: center;
    align-items: center;
}

.container {
    text-align: center;
    background-color: #ffffff;
    padding: 20px;
    border-radius: 10px;
    box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
    width: 300px;
}

h1 {
    font-size: 24px;
    margin-bottom: 20px;
}

#display {
    font-size: 40px;
    font-weight: 400;
    margin-bottom: 20px;
    color: #333333;
}

.buttons {
    display: flex;
    justify-content: space-around;
    flex-direction: row;
    align-items: center;
    gap: 16px;
}

.buttons button, button#saveTime, button.remove, button#removeAll {
    padding: 10px 20px;
    font-size: 16px;
    margin: 5px 0;
    cursor: pointer;
    border: none;
    border-radius: 5px;
    outline: none;
    transition: background-color 0.3s ease;
    color: #818181;
    width: 100%;
}

.buttons button#startButton {
    background: #0001ff;
    color: #fff;
}

.buttons button#startButton:hover {
    background: #0001fb;
    color: #fff;
}

.buttons button:hover, button#saveTime:hover, button#removeAll:hover {
    background-color: #d2d2d2;
    color: #747474;
}

textarea {
    width: 100%;
    height: 60px;
    margin-top: 10px;
    padding: 10px;
    box-sizing: border-box;
    border-radius: 5px;
    border: 1px solid #ccc;
    resize: none;
    font-size: 16px;
    color: #333;
    background-color: #fff;
}

textarea:focus {
    border-color: #007BFF;
    box-shadow: 0 0 5px rgba(0, 123, 255, 0.5);
}

ul {
    list-style-type: none;
    padding: 0;
}

li {
    text-align: left;
    padding: 8px;
    margin-top: 5px;
    background-color: #eee;
    border-radius: 5px;
    font-size: 14px;
    display: flex;
    justify-content: space-between;
    align-items: center;
}

button#removeAll {
    background-color: transparent;
    color: #818181;
    margin: 0;
    width: auto;
}

button#removeAll:hover {
    background-color: #ffe6e6;
    color: #ff4343;
}

button.remove {
    padding: 8px;
    margin: 0;
    width: auto;
    opacity: 0.3;
}

button.remove:hover, button.remove:focus {
    background: #ffe6e6;
    opacity: 1;
    color: #ff4343;
}

.headerSaveTimes {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-top: 16px;
}

@keyframes popIn {
    0% {
        transform: scale(0.5);
        opacity: 0;
    }
    50% {
        transform: scale(1.2);
        opacity: 0.5;
    }
    100% {
        transform: scale(1);
        opacity: 1;
    }
}

@keyframes ripple {
    0% {
        box-shadow: 0 0 0 0 rgba(0, 123, 255, 0.7);
    }
    100% {
        box-shadow: 0 0 0 10px rgba(0, 123, 255, 0);
    }
}

li {
    animation: popIn 0.6s cubic-bezier(0.68, -0.55, 0.265, 1.55);
    position: relative;
    overflow: hidden;
}

li::after {
    content: '';
    position: absolute;
    top: 50%;
    left: 50%;
    width: 150%;
    height: 150%;
    background-color: rgba(0, 123, 255, 0.5);
    transform: translate(-50%, -50%) scale(0);
    border-radius: 50%;
    z-index: 0;
    animation: ripple 0.6s ease-out forwards;
}

@keyframes collapse {
    0% {
        transform: scale(1);
        opacity: 1;
        height: auto;
    }
    100% {
        transform: scale(0);
        opacity: 0;
        height: 0;
        padding: 0;
        margin: 0;
    }
}

li.collapsing {
    animation: collapse 0.5s ease-in forwards;
}

li.dragging {
    opacity: 0.5;
}

li.over {
    border: 2px dashed #000;
}

Este tipo de ferramenta ajuda a você a controlar e monitorar o tempo gasto de maneira intuitiva, e também disponibiliza uma maneira de salvar (temporariamente) o seu tempo, adicionando um nome para cada tempo contabilizado.

Publicações recomendadas:


Inscreva-se em Nossa News:

Seja notificando sempre que tiver conteúdo novo disponível no meu canal do Youtube ou artigo no meu Blog.

Bruno Devs News


Link Curto para Compartilhamento

Compartilhe esse conteudo nas redes sociais ou por mensagem usando o link curto abaixo. Basta clicar em cima do link para copiar.

bruno.art.br/pb/4928

ID de Referência: 4928

Sugira uma publicação

Envie uma mensagem e sugira um publicação sobre um assunto que tenha dificuldades de resolver.

Clique aqui e entre em contato


Comentários