728x90
JavaScript의 시간 관련 API와 상태 관리를 활용하여 타이머와 스톱워치를 만들어보도록 하겠습니다.
html:
먼저 타이머와 스톱워치의 기본 구조를 HTML로 작성하겠습니다.
각 섹션은 시간을 표시할 디스플레이와 제어 버튼들로 구성됩니다.
css:
사용자가 직관적으로 사용할 수 있도록
깔끔하고 모던한 디자인을 CSS로 구현하겠습니다.
js:
타이머와 스톱워치의 기능을 클래스로 구현하여
효율적으로 상태를 관리하고 코드를 구조화하겠습니다.
Date.now()를 사용하여 정확한 시간을 계산,
setInterval로 실시간 업데이트를 구현해보겠습니다.
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>타이머 & 스톱워치</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: Arial, sans-serif;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
background: #f0f0f0;
}
.container {
display: flex;
gap: 30px;
padding: 20px;
}
.timer-section,
.stopwatch-section {
background: white;
padding: 30px;
border-radius: 10px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
text-align: center;
}
.display {
font-size: 3em;
font-weight: bold;
margin: 20px 0;
font-family: monospace;
}
.controls {
display: flex;
gap: 10px;
justify-content: center;
}
button {
padding: 10px 20px;
border: none;
border-radius: 5px;
cursor: pointer;
font-size: 1em;
transition: all 0.3s ease;
}
button:hover {
opacity: 0.8;
}
.start {
background: #4CAF50;
color: white;
}
.stop {
background: #f44336;
color: white;
}
.reset {
background: #2196F3;
color: white;
}
.timer-input {
display: flex;
gap: 10px;
margin-bottom: 20px;
justify-content: center;
}
.timer-input input {
width: 60px;
padding: 5px;
text-align: center;
font-size: 1.2em;
}
h2 {
color: #333;
margin-bottom: 20px;
}
.lap-times {
margin-top: 20px;
max-height: 150px;
overflow-y: auto;
text-align: left;
}
.lap-time {
padding: 5px;
border-bottom: 1px solid #eee;
}
</style>
</head>
<body>
<div class="container">
<!-- 타이머 섹션 -->
<div class="timer-section">
<h2>타이머</h2>
<div class="timer-input">
<input type="number" id="hours" placeholder="시" min="0" max="99">
<input type="number" id="minutes" placeholder="분" min="0" max="59">
<input type="number" id="seconds" placeholder="초" min="0" max="59">
</div>
<div class="display" id="timer-display">00:00:00</div>
<div class="controls">
<button class="start" id="timer-start">시작</button>
<button class="stop" id="timer-stop">정지</button>
<button class="reset" id="timer-reset">리셋</button>
</div>
</div>
<!-- 스톱워치 섹션 -->
<div class="stopwatch-section">
<h2>스톱워치</h2>
<div class="display" id="stopwatch-display">00:00:00</div>
<div class="controls">
<button class="start" id="stopwatch-start">시작</button>
<button class="stop" id="stopwatch-stop">정지</button>
<button class="reset" id="stopwatch-reset">리셋</button>
<button class="start" id="stopwatch-lap">랩</button>
</div>
<div class="lap-times" id="lap-times"></div>
</div>
</div>
<script>
// 타이머 클래스
class Timer {
constructor(display) {
this.display = display;
this.interval = null;
this.remainingSeconds = 0;
this.isRunning = false;
}
start(hours, minutes, seconds) {
if (this.isRunning) return;
this.remainingSeconds = hours * 3600 + minutes * 60 + seconds;
if (this.remainingSeconds <= 0) return;
this.isRunning = true;
this.interval = setInterval(() => {
this.remainingSeconds--;
this.updateDisplay();
if (this.remainingSeconds <= 0) {
this.stop();
alert('타이머가 종료되었습니다!');
}
}, 1000);
}
stop() {
clearInterval(this.interval);
this.isRunning = false;
}
reset() {
this.stop();
this.remainingSeconds = 0;
this.updateDisplay();
}
updateDisplay() {
const hours = Math.floor(this.remainingSeconds / 3600);
const minutes = Math.floor((this.remainingSeconds % 3600) / 60);
const seconds = this.remainingSeconds % 60;
this.display.textContent = `${String(hours).padStart(2, '0')}:${String(minutes).padStart(2, '0')}:${String(seconds).padStart(2, '0')}`;
}
}
// 스톱워치 클래스
class Stopwatch {
constructor(display, lapTimesContainer) {
this.display = display;
this.lapTimesContainer = lapTimesContainer;
this.interval = null;
this.startTime = 0;
this.elapsedTime = 0;
this.isRunning = false;
this.lapTimes = [];
}
start() {
if (this.isRunning) return;
this.isRunning = true;
this.startTime = Date.now() - this.elapsedTime;
this.interval = setInterval(() => this.updateDisplay(), 10);
}
stop() {
if (!this.isRunning) return;
clearInterval(this.interval);
this.elapsedTime = Date.now() - this.startTime;
this.isRunning = false;
}
reset() {
this.stop();
this.elapsedTime = 0;
this.updateDisplay();
this.lapTimes = [];
this.lapTimesContainer.innerHTML = '';
}
lap() {
if (!this.isRunning) return;
const lapTime = this.formatTime(this.elapsedTime);
this.lapTimes.push(lapTime);
const lapElement = document.createElement('div');
lapElement.className = 'lap-time';
lapElement.textContent = `랩 ${this.lapTimes.length}: ${lapTime}`;
this.lapTimesContainer.insertBefore(lapElement, this.lapTimesContainer.firstChild);
}
updateDisplay() {
const currentTime = this.isRunning ? Date.now() - this.startTime : this.elapsedTime;
this.display.textContent = this.formatTime(currentTime);
}
formatTime(ms) {
const hours = Math.floor(ms / 3600000);
const minutes = Math.floor((ms % 3600000) / 60000);
const seconds = Math.floor((ms % 60000) / 1000);
return `${String(hours).padStart(2, '0')}:${String(minutes).padStart(2, '0')}:${String(seconds).padStart(2, '0')}`;
}
}
// 타이머 초기화
const timer = new Timer(document.getElementById('timer-display'));
document.getElementById('timer-start').addEventListener('click', () => {
const hours = parseInt(document.getElementById('hours').value) || 0;
const minutes = parseInt(document.getElementById('minutes').value) || 0;
const seconds = parseInt(document.getElementById('seconds').value) || 0;
timer.start(hours, minutes, seconds);
});
document.getElementById('timer-stop').addEventListener('click', () => timer.stop());
document.getElementById('timer-reset').addEventListener('click', () => timer.reset());
// 스톱워치 초기화
const stopwatch = new Stopwatch(
document.getElementById('stopwatch-display'),
document.getElementById('lap-times')
);
document.getElementById('stopwatch-start').addEventListener('click', () => stopwatch.start());
document.getElementById('stopwatch-stop').addEventListener('click', () => stopwatch.stop());
document.getElementById('stopwatch-reset').addEventListener('click', () => stopwatch.reset());
document.getElementById('stopwatch-lap').addEventListener('click', () => stopwatch.lap());
</script>
</body>
</html>
시연영상
'HTML/CSS' 카테고리의 다른 글
[HTML/CSS]스탑워치 기능을 활용한 10초 클릭 게임 만들기 (2) | 2024.12.09 |
---|---|
[HTML/CSS] 반응형 웹페이지 만들기 (2) | 2024.12.01 |
[HTML/CSS/JS] 프로그램 카드 가로 스크롤 슬라이더 만들기 (11) | 2024.11.24 |
[HTML/CSS] CSS transition 속성 transition-timing-function (2) | 2024.10.22 |
[HTML/CSS]CSS Flexbox에 대한 가이드 (0) | 2024.07.10 |