javascript 带有自动暂停功能的精密时计w/Vue.js

qgelzfjb  于 2023-10-14  发布在  Java
关注(0)|答案(2)|浏览(97)

HelloWorld!

我正在编写一个记忆游戏,它可以显示你完成游戏所需的时间。我提供的代码只是我使用的功能的一个更基本的Vue模板,但它是一个非常相似的用例。我的问题在于每个函数的注解。基本上我遇到的问题与停止计时器和un-stoping它.

我需要什么?

  • 在我的html上显示自您开始点击交互以来的格式化时间,这里由startChrono()函数表示。
  • 自动停止时间,如果你没有互动的一段时间,如果游戏结束。
  • 自动恢复时间,如果你再次互动。
  • 在代码和DOM中完全重置时间。
<script setup>
import { ref } from 'vue';

const startTime = ref(0); // Initial TimeStamp
const endTime = ref(false); // Boolean to stop the Chrono
const elapsedTime = ref(0); // Chrono Time
const isGameActive = ref(false);

function startChrono() {
  /* 
  I want pauseChrono() to be used here IF the startChrono() function hasnt been called since "x" time  
  or IF the isGameActive boolean is set to false
  (auto pause if you're not clicking on the start button in other words) 
  In my mind I should use a Debounce but cant really figure how to do it properly...
  */
  isGameActive.value = true;
  startTime.value = new Date().getTime();
  endTime.value = false;
  updateChrono();
}

function pauseChrono() {
  /*
  Issue here is when you stop the pause it still uses the initial timestamp
  so the delta time is still counted instead of 
  adding the time elapsed before the pause to a new timestamp chrono time...
  */
  if (endTime.value === true) endTime.value = false;
  if (endTime.value === false) endTime.value = true;
  updateChrono();
}

function updateChrono() {
  const intervalId = setInterval(() => {
    const currentTime = new Date().getTime();
    elapsedTime.value = Math.floor((currentTime - startTime.value) / 1000);

    if (endTime.value == true) {
      clearInterval(intervalId);
    }
  }, 1000);
}

function formatTime(seconds) {
  if (seconds < 0 || seconds > 3600) {
    return;
  }
  const minutes = Math.floor(seconds / 60);
  const remainingSeconds = seconds % 60;
  if (minutes === 0) {
    return `${remainingSeconds} s`;
  } else {
    return `${minutes} min ${remainingSeconds} s`;
  }
}

function resetChrono() {
  isGameActive.value = false;
  startTime.value = 0;
  endTime.value = true;
  elapsedTime.value = 0;
  updateChrono();
}
</script>

<template>
  <main>
    <h1>
      Time:<span>{{ formatTime(elapsedTime) }}</span>
    </h1>
    <button @click="startChrono()">Start</button>
    <button @click="pauseChrono()">Pause</button>
    <button @click="resetChrono()">Reset</button>
  </main>
</template>

<style scoped>
main {
  background-color: lightslategray;
  padding: 5rem;
}
button {
  font-weight: bold;
  font-size: 18px;
  padding: 0.2rem 1rem;
  margin-right: 1rem;
  margin-block: 1rem 0;
  cursor: pointer;
}
span {
  color: rgb(2, 255, 120);
  margin-left: 1rem;
}
</style>
ix0qys7i

ix0qys7i1#

解决pause/unpause问题:
要暂停计时器,请在setInterval返回值上调用clearInterval。在下面的代码中,当计时器启动时,将返回值分配给新值isRunning
然后在pause函数中,如果isRunning有一个值,清除间隔并将isRunning设置回null/undefined将暂停游戏。否则,通过再次调用updateChrono来取消暂停(这将为isRunning分配一个新的setTime值)。此外,startTime将需要设置为当前时间减去经过的时间,以便计时器从其先前的值继续运行。

const isRunning = ref(null)

function updateChrono() {
  isRunning.value = setInterval(() => {
    const currentTime = new Date().getTime();
    elapsedTime.value = Math.floor((currentTime - startTime.value) / 1000);
  }, 1000);
}

function pauseChrono() {
  if (isRunning.value) { // pause
    isRunning.value = clearInterval(isRunning.value);
  } else { // unpause
    startTime.value = new Date().getTime() - elapsedTime.value * 1000;
    updateChrono();
  }
}

VuePlayground#1
我认为有多种方法可以处理“空闲计时器”
一个基本的想法是一个函数,它有一个setTimeout函数,在X时间后调用pauseChrono

const idleTimer = ref(null);

function resetIdle() {
  clearTimeout(idleTimer.value);
  idleTimer.value = setTimeout(() => {
    pauseChrono();
  }, 10000); // auto-pause after 10 seconds
}

它还清除自己的计时器每次调用,重新开始倒计时,只要它继续被调用。如果用户每次与游戏交互时都调用此函数,并且用户每X秒交互一次以上,则计时器永远不会命中。否则,游戏将在X秒没有互动后暂停。
VuePlayground#2

pw9qyyiw

pw9qyyiw2#

1.在暂停时将Date.now();写入某个变量,并在恢复时将其考虑在内。
1.如果你想停止计时器,例如,const pausedTime = 5; // pauseChrono after 5s,在更新计时器时比较elapsedTime.value的值。
这是你的出发点:* 香港迪士尼乐园**

相关问题