こんにちはハッピーサトです。
PCでもスマホでも使いやすいシンプルな焙煎記録アプリを開発しました。
タイマーには#1~#8と番号を付けているので、当日の焙煎メニューと連動させてご活用下さい☆彡
コーヒー自家焙煎タイマー
#1
00:00
#2
00:00
#3
00:00
#4
00:00
#5
00:00
#6
00:00
#7
00:00
#8
00:00
プログラム内容
アプリのHTML、CSS、JAVAコードを公開しておきます。
HTMLコード
<p><!-- 各タイマーのコンテナ。以下をタイマーの数だけ繰り返します --><br /> <!-- タイマー #1 --></p> <div id="timer1" class="timer-container"> <div class="timer-header"> <div class="timer-title">#1</div> <div class="timer-display">00:00</div> </div> <div class="buttons-container"><button class="start">Start</button><br /> <button class="first-crack">1st<br /> Crack</button><br /> <button class="second-crack">2nd<br /> Crack</button><br /> <button class="stop-reset">Stop<br /> Reset</button></div> <div class="crack-times"></div> </div> <div id="timer2" class="timer-container"> <div class="timer-header"> <div class="timer-title">#2</div> <div class="timer-display">00:00</div> </div> <div class="buttons-container"><button class="start">Start</button><br /> <button class="first-crack">1st<br /> Crack</button><br /> <button class="second-crack">2nd<br /> Crack</button><br /> <button class="stop-reset">Stop<br /> Reset</button></div> <div class="crack-times"></div> </div> <div id="timer3" class="timer-container"> <div class="timer-header"> <div class="timer-title">#3</div> <div class="timer-display">00:00</div> </div> <div class="buttons-container"><button class="start">Start</button><br /> <button class="first-crack">1st<br /> Crack</button><br /> <button class="second-crack">2nd<br /> Crack</button><br /> <button class="stop-reset">Stop<br /> Reset</button></div> <div class="crack-times"></div> </div> <div id="timer4" class="timer-container"> <div class="timer-header"> <div class="timer-title">#4</div> <div class="timer-display">00:00</div> </div> <div class="buttons-container"><button class="start">Start</button><br /> <button class="first-crack">1st<br /> Crack</button><br /> <button class="second-crack">2nd<br /> Crack</button><br /> <button class="stop-reset">Stop<br /> Reset</button></div> <div class="crack-times"></div> </div> <div id="timer5" class="timer-container"> <div class="timer-header"> <div class="timer-title">#5</div> <div class="timer-display">00:00</div> </div> <div class="buttons-container"><button class="start">Start</button><br /> <button class="first-crack">1st<br /> Crack</button><br /> <button class="second-crack">2nd<br /> Crack</button><br /> <button class="stop-reset">Stop<br /> Reset</button></div> <div class="crack-times"></div> </div> <div id="timer6" class="timer-container"> <div class="timer-header"> <div class="timer-title">#6</div> <div class="timer-display">00:00</div> </div> <div class="buttons-container"><button class="start">Start</button><br /> <button class="first-crack">1st<br /> Crack</button><br /> <button class="second-crack">2nd<br /> Crack</button><br /> <button class="stop-reset">Stop<br /> Reset</button></div> <div class="crack-times"></div> </div> <div id="timer7" class="timer-container"> <div class="timer-header"> <div class="timer-title">#7</div> <div class="timer-display">00:00</div> </div> <div class="buttons-container"><button class="start">Start</button><br /> <button class="first-crack">1st<br /> Crack</button><br /> <button class="second-crack">2nd<br /> Crack</button><br /> <button class="stop-reset">Stop<br /> Reset</button></div> <div class="crack-times"></div> </div> <div id="timer8" class="timer-container"> <div class="timer-header"> <div class="timer-title">#8</div> <div class="timer-display">00:00</div> </div> <div class="buttons-container"><button class="start">Start</button><br /> <button class="first-crack">1st<br /> Crack</button><br /> <button class="second-crack">2nd<br /> Crack</button><br /> <button class="stop-reset">Stop<br /> Reset</button></div> <div class="crack-times"></div> </div> <p><script src="script.js"></script></p>
CSSコード
.crack-times { font-size: 14px; text-align: left; margin-top: 0px; margin-bottom: 0; /* クラックタイム表示部分の下部マージンを減らす */ } .timer-container { background-color: #fff; border: none; padding: 10px; margin-bottom: 10px; /* タイマーコンテナ間の間隔 */ text-align: center; border-bottom: 1px solid #ddd; /* 各タイマーコンテナの下部にボーダーを追加 */ } /* 最後のタイマーコンテナにはボーダーを追加しない */ .timer-container:last-child { border-bottom: none; } .timer-header { display: flex; justify-content: center; align-items: center; margin-bottom: 0px; } .timer-title { font-size: 24px; font-weight: bold; margin-right: 10px; order: -1; /* タイトルを左に移動 */ } .timer-display { background-color: black; color: white; font-size: 42px; padding: 0px 45px; margin: 3px 0; } .buttons-container { display: flex; justify-content: center; flex-wrap: nowrap; } button { background-color: #8B4513; /* 薄茶色より少し濃い茶色 */ color: white; border: none; padding: 10px 10px; margin: 5px; font-size: 16px; cursor: pointer; min-width: 80px;
JAVAコード
document.addEventListener('DOMContentLoaded', function() { const timers = document.querySelectorAll('.timer-container'); timers.forEach((timerContainer, index) => { let startTime = 0; let timerInterval = null; let firstCrackTimes = []; let secondCrackTimes = []; let stopTime = 0; let resetCount = 0; const timerDisplay = timerContainer.querySelector('.timer-display'); const crackTimesDisplay = timerContainer.querySelector('.crack-times'); function formatTime(time) { const minutes = Math.floor(time / 60000).toString().padStart(2, '0'); const seconds = ((time % 60000) / 1000).toFixed(0).padStart(2, '0'); return `${minutes}:${seconds}`; } function updateTimerDisplay(time) { timerDisplay.textContent = formatTime(time); } function updateCrackTimesDisplay() { const firstCracks = firstCrackTimes.map(t => formatTime(t)).join(', '); const secondCracks = secondCrackTimes.map(t => formatTime(t)).join(', '); const stopDisplay = stopTime ? `Stop: ${formatTime(stopTime)}` : ''; crackTimesDisplay.innerHTML = [ firstCracks ? `1st Crack: ${firstCracks}` : '', secondCracks ? `2nd Crack: ${secondCracks}` : '', stopDisplay ].filter(Boolean).join('<br>'); } function startTimer() { if (!timerInterval) { startTime = Date.now() - (stopTime ? stopTime : 0); timerInterval = setInterval(() => { updateTimerDisplay(Date.now() - startTime); }, 1000); } } function recordCrack(crackArray) { if (timerInterval && crackArray.length < 2) { crackArray.push(Date.now() - startTime); updateCrackTimesDisplay(); } } function stopResetTimer() { if (timerInterval) { clearInterval(timerInterval); stopTime = Date.now() - startTime; timerInterval = null; updateCrackTimesDisplay(); resetCount = 0; } else { resetCount++; if (resetCount === 3) { timerDisplay.textContent = '00:00'; firstCrackTimes = []; secondCrackTimes = []; stopTime = 0; updateCrackTimesDisplay(); resetCount = 0; } } } timerContainer.querySelector('.start').addEventListener('click', startTimer); timerContainer.querySelector('.first-crack').addEventListener('click', () => recordCrack(firstCrackTimes)); timerContainer.querySelector('.second-crack').addEventListener('click', () => recordCrack(secondCrackTimes)); timerContainer.querySelector('.stop-reset').addEventListener('click', stopResetTimer); }); });