This is suppose to be a respawn countdown timer for the bosses in my game. I have this object that has individual unix-formatted timestamp, I need to make the function that displays a countdown timer.
my code:
<script setup lang="ts">
function convertUnixtoReadable(time: number) {
const Countdown = new Date(time * 1000).getTime() //2019-12-9 10:30:15
var now = new Date().getTime();
var distance = Countdown - now;
var days = Math.floor(distance / (1000 * 60 * 60 * 24));
var hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
var minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
var seconds = Math.floor((distance % (1000 * 60)) / 1000);
if (now > Countdown) {
return ("alive")
} else {
return (days + "d " + hours + "h "
+ minutes + "m " + seconds + "s ")
}
}
</script>
and my template:
<div v-for="i in MVPTimer.value" :key="i" class="mvp">
<div class="mvp-info">
{{ i.mobname }} -
{{ convertUnixtoReadable(i.respawntime) }}
</div>
</div>
Currently it works. it displays if the 'monster' is alive, or the 'time' remaining for it to respawn. but it doesn't "count down" I know I need a setInterval or computed... or both? I'd be able to do this if I were to use options API; but I'd rather practice script setup
Here's a vue3 way of doing it with the reactive store state.
//store.js
import { reactive, readonly } from 'vue'
const state = reactive({
countdownPaused: false
})
function toggleCountdownPlayPause() {
state.countdownPaused = !state.countdownPaused
}
export const store = readonly({
state,
toggleCountdownPlayPause
})
//main.js
import { createApp } from 'vue'
import store from './store'
import App from './App.vue'
const app = createApp(App)
app.use(store)
app.config.globalProperties.$store=store
app.mount("#app")
// components/Timer.vue
<template>
<b>
<span>{{ cowntdown }}</span>
</b>
</template>
<script>
import store from '../../store'
export default {
data() {
return {
store,
timerCountdown: 120,
timeout: null
}
},
watch: {
paused(isPaused) {
if (!isPaused) {
this.timerCountdown--
} else {
clearTimeout(this.timeout)
}
},
timerCount: {
handler(value) {
if (value > 0 && !this.paused) {
this.timeout = setTimeout(() => this.timerCountdown--, 1000)
}
},
immediate: true
}
},
computed: {
paused() {
return store.state.countdownPaused
},
formattedCountdown() {
const minutes = Math.floor(this.timerCount / 60) > 0 ? Math.floor(this.timerCount / 60 ) : "00"
const seconds = this.timerCount % 60 > 9 ? this.timerCount % 60 : "0" + [this.timerCount % 60]
return `${minutes}:${seconds}`
}
}
</script>
// components/TimerPlayPauseButton.vue
<template>
<button :class="{'paused':paused}" @click="togglePlayPause"></button>
</template>
<script>
import { store } from '../../store'
export default {
data() {
return {
store,
paused: store.state.countdownPaused
}
},
methods: {
togglePlayPause(e) {
this.store.toggleCountdownPlayPause()
}
}
}
</script>
<style>
.paused:after {
content: "ll"
}
//App.vue
<template><div><timer /><timer-play-pause-button /></div></template>
<script>
import Timer from './components/Timer.vue'
import TimerPlayPauseButton from './components/TimerPlayPauseButton.vue'
export default {
components: {
'timer': Timer,
'timer-play-pause-button': TimerPlayPauseButton
}
}