Skip to content

Instantly share code, notes, and snippets.

@GeekyDeaks
Last active November 7, 2022 12:12
Show Gist options
  • Save GeekyDeaks/635b0f0fb767f84a48c157aa9f684c49 to your computer and use it in GitHub Desktop.
Save GeekyDeaks/635b0f0fb767f84a48c157aa9f684c49 to your computer and use it in GitHub Desktop.
Simple Stopwatch
<html>
<head>
<title>Stopwatch</title>
<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=Overpass+Mono&display=swap" rel="stylesheet">
<style>
html { height: 100%; }
body {
font-family: 'Arial', sans-serif; margin: 0em;
width: 100%;
}
#app {
width: 100%;
display: flex;
flex-direction: column;
align-items: center;
}
button {
display: inline-block;
background-color: #555;
margin: 0.2em;
padding: 0.25em 0.75em 0.25em 0.75em;
border-radius: .25em;
color: white;
font-size: 1.25em;
}
button:disabled {
color: lightgray;
background-color: #777;
}
.buttonbox {
width: auto;
display: flex;
align-items: center;
flex-direction: row;
}
.timerbox {
display: flex;
flex-direction: column;
align-items: center;
width: 100%;
}
#elapsedtime {
font-family: 'Overpass Mono', monospace;
font-size: 1.5em;
color: #555;
}
#splittime {
font-family: 'Overpass Mono', monospace;
font-size: 1.75em;
font-weight: bold;
padding-top: 0.25em;
}
table { border-collapse: collapse; width: 100%; }
tr:nth-child(even) { background: #FFF }
tr:nth-child(odd) { background: #EEE }
tr:first-child {font-weight: bold; background: #BBB }
table, th, td { border: 1px solid gray; padding: 5px }
td { font-family: 'Overpass Mono', monospace; }
</style>
</head>
<body>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<div id="app">
<div class="timerbox">
<div id="splittime">{{ splitTime }}</div>
<div id="elapsedtime">{{ elapsedTime }}</div>
</div>
<div class="buttonbox">
<button id="startbutton" class="button" @click="start" v-if="!timer">start</button>
<button id="stopbutton" class="button" @click="stop" v-if="timer">stop</button>
<button id="splitbutton" class="button" @click="split" :disabled="!timer">split</button>
<button id="resetbutton" class="button" @click="reset">reset</button>
</div>
<table>
<tr><th>lap</th><th>split</th><th>elapsed</th></tr>
<tr v-for="lap in laps">
<td>{{ lap.lap }}</td>
<td>{{ lap.splitTime }}</td>
<td>{{ lap.elapsedTime }}</td>
</tr>
</table>
</div>
<script>
const { createApp } = Vue
function createTimer() {
let last = 0
let total = 0
return {
start(now = Date.now()) {
last = now
},
update(now = Date.now()) {
total += now - last
last = now
},
toString() {
let ms = total % 1000
let sec = Math.floor(total % 60000 / 1000)
let min = Math.floor(total % 3600000 / 1000 / 60)
let hour = Math.floor(total / 1000 / 3600)
return hour.toString().padStart(2, '0') + ':'
+ min.toString().padStart(2, '0') + ':'
+ sec.toString().padStart(2, '0') + '.'
+ ms.toString().padStart(3, '0')
}
}
}
let app = createApp({
data() {
return {
laps: [],
timer: undefined,
elapsedTimer: createTimer(),
elapsedTime: '',
splitTimer: createTimer(),
splitTime: ''
}
},
methods: {
update(now = Date.now()) {
this.elapsedTimer.update(now)
this.elapsedTime = this.elapsedTimer.toString()
this.splitTimer.update(now)
this.splitTime = this.splitTimer.toString()
},
start() {
if(this.timer) return
let now = Date.now()
this.elapsedTimer.start(now)
this.splitTimer.start(now)
this.timer = setInterval(this.update.bind(this), 10)
},
split() {
if(!this.timer) return
// add the latest times to the laps
let now = Date.now()
this.update(now)
let lap = this.laps.length + 1
this.laps.unshift({ lap, elapsedTime: this.elapsedTime, splitTime: this.splitTime })
this.splitTimer = createTimer()
this.splitTimer.start(now)
},
stop() {
if(!this.timer) return
clearInterval(this.timer)
this.timer = undefined
this.update()
},
reset() {
this.stop()
this.elapsedTimer = createTimer()
this.splitTimer = createTimer()
this.laps = []
this.update(0)
}
},
mounted() {
this.update(0)
}
}).mount('#app')
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment