· tools
Running distance calculator
I recently got my first Garmin watch, and have been running an awful lot recently, following the training suggestions it’s been giving me.
Pace /km
Duration hh:mm
Distance 0:40:00@6:20
6.32 kmMost of my recent training suggestions have prompted me to run for a certain amount of time, at a specific pace. Not wanting to simply run for half the time and turn home, I decided to look for online tools to calculate how far I will travel, figuring I would then plot a route just over that distance…
Cue the frustration of trying to find one that isn’t overly complex, or requires me to mess around dismissing a cookie notice while attempting not to sign my life away!
Alas, here’s a tool I’ll be using pretty much daily, and I hope it proves useful for others too.
How does it work?
Firstly we need some arrays for the select inputs that we’ll display. Starting with the pace (the number of minutes and seconds it will take to travel 1km):
const pace = {
/**
* Create a sequence of 6 numbers starting from the number 3.
* [3,4,5,6,7,8]
*/
minutes: Array.from({ length: 6 }, (_, i) => i + 3),
/**
* Create a sequence of 12 numbers, starting from zero,
* increasing with a step of 5 each time.
* [0,5,10,15,20,...,50,55]
*/
seconds: Array.from({ length: 12 }, (_, i) => i * 5),
}
Next up we need some more arrays, that will be used for the select inputs for the duration (hours and minutes) that will be spent running:
const duration = {
/**
* Create a sequence of 7 numbers starting from zero.
* [0,1,2,3,4,5,6,7]
*/
hours: Array.from({ length: 7 }, (_, i) => i),
/**
* Create a sequence of 60 numbers, starting from zero.
* [0,1,2,3,4,...,58,59]
*/
minutes: Array.from({ length: 60 }, (_, i) => i),
}
Let’s set some sensible defaults, that will be used for the v-model
attributes for our select inputs. I’m presently in a build phase so 40:00@6:20
has been a pretty typical suggestion recently.
const paceMinutes = ref(6)
const paceSeconds = ref(20)
const durationHours = ref(0)
const durationMinutes = ref(40)
We’re also going to need a computed property, that will stay updated as changes are made to the select inputs.
const distance = computed(() => {
/**
* Calculate the pace in minutes /km as a single value by
* dividing the number of seconds by 60 and adding together.
*/
const minutesPerKm = paceMinutes.value + (paceSeconds.value / 60)
/**
* Calculate the number of minutes that will be spent running
* by multiplying the number of hourse by 60 and adding together.
*/
const minutesInTotal = durationHours.value * 60 + durationMinutes.value
/**
* The total distance travelled is a simple division of minutes by
* the pace, accurate to two decimal places by using `toFixed(2)` .
*/
return (minutesInTotal / minutesPerKm).toFixed(2)
})
So here’s the <script setup>
portion of the Vue component:
import { ref, computed } from 'vue'
const pace = {
minutes: Array.from({ length: 6 }, (_, i) => i + 3),
seconds: Array.from({ length: 12 }, (_, i) => i * 5),
}
const duration = {
hours: Array.from({ length: 7 }, (_, i) => i),
minutes: Array.from({ length: 60 }, (_, i) => i),
}
const paceMinutes = ref(6)
const paceSeconds = ref(20)
const durationHours = ref(0)
const durationMinutes = ref(40)
const distance = computed(() => {
const minutesPerKm = paceMinutes.value + (paceSeconds.value / 60)
const minutesInTotal = durationHours.value * 60 + durationMinutes.value
return (minutesInTotal / minutesPerKm).toFixed(2)
})
And the template, in its simplest form, devoid of any styling so that you can make it your own!
<template>
<select v-model="paceMinutes">
<option v-for="minutes in pace.minutes" :key="minutes" :value="minutes">
{{ minutes }} minutes
</option>
</select>
<select v-model="paceSeconds">
<option v-for="seconds in pace.seconds" :key="seconds" :value="seconds">
{{ seconds }} seconds
</option>
</select>
<select v-model="durationHours">
<option v-for="hours in duration.hours" :key="hours" :value="hours">
{{ hours }} {{ hours === 1 ? 'hour' : 'hours' }}
</option>
</select>
<select v-model="durationMinutes">
<option v-for="minutes in duration.minutes" :key="minutes" :value="minutes">
{{ minutes }} {{ minutes === 1 ? 'minute' : 'minutes' }}
</option>
</select>
{{ distance }}
</template>