首页 > 解决方案 > 如何修复此 Javascript 秒表时钟中的停止启动过程?

问题描述

我在这里有一个 JavaScript 秒表,我需要开始-停止按钮在继续时保持相同的时间。目前,如果我停止并继续时钟差异是荒谬的,例如 '-19330839:-3:-53'

谁能解释这是如何解决的?

我制作了各种方法秒表;但是我宁愿使用实际日期时间而不是计数器,这是因为(我在意识到这一点后进行了测试)计数器在一段时间内非常不准确。

任何帮助深表感谢。

html:

请暂时忽略重置按钮。我稍后会配置它。

        <input id="startstopbutton" class="buttonZ" style="width: 120px;" type="button" name="btn" value="Start" onclick="startstop();">
        <input id="resetbutton" class="buttonZ" style="width: 120px;" type="button" name="btnRst1" id='btnRst1' value="Reset" onclick="resetclock();"/>   
        <div id="outputt" class="timerClock" value="00:00:00">00:00:00</div>

JS:

    const outputElement = document.getElementById("outputt");
    var startTime = 0;
    var running = false;
    var splitcounter = 0;
    
    
    function startstop() {
      if (running == false) {
        running = true;
        startTime = new Date(sessionStorage.getItem("time"))
        if (isNaN(startTime)) startTime = Date.now();
        startstopbutton.value = 'Stop';
        document.getElementById("outputt").style.backgroundColor = "#2DB37B";
        updateTimer();
      } else {
        running = false;
        logTime();
        startstopbutton.value = 'Start';
        document.getElementById("outputt").style.backgroundColor = "#B3321B";
      }
    }
    
    function updateTimer() {
      if (running == true) {
        let differenceInMillis = Date.now() - startTime;
        sessionStorage.setItem("time", differenceInMillis)
        let {
          hours,
          minutes,
          seconds
        } = calculateTime(differenceInMillis);
        let timeStr = `${pad(hours)}:${pad(minutes)}:${pad(seconds)}`;
        
        outputElement.innerText = timeStr;
        requestAnimationFrame(updateTimer);
      }
    }
    
    function calculateTime(milliS) {
      const SECONDS = 1000; // should be 1000 - only 10 to speed up the timer
      const MINUTES = 60;
      const HOURS = 60;
      const RESET = 60;
      
      let hours = Math.floor(milliS / SECONDS / MINUTES / HOURS);
      let minutes = Math.floor(milliS / SECONDS / MINUTES) % RESET;
      let seconds = Math.floor(milliS / SECONDS) % RESET;
      
      return {
        hours,
        minutes,
        seconds
      };
    }
    
    function pad(time) {
      return time.toString().padStart(2, '0');
    }

我只需要计时器从它停止的地方继续。

标签: javascripthtmlcss

解决方案


您的代码存在问题:

  • 您从 sessionStorage 的初始值开始,Date.now然后在更新时保存差异。
  • 您与会话存储进行了很多交互。与外部 API 的任何通信都是昂贵的。而是使用局部变量并找到一个事件来初始化值。
  • 时差逻辑有点不对劲。
    • Date.now - startTime不考虑停止动作和开始动作之间的区别。
    • 您可以使用此逻辑:如果定义了 startTime,则计算差异并将其添加到开始时间。如果不是,将其初始化为Date.now()

建议:

  • 不要添加样式,而是使用类。这将帮助您重置功能
  • 定义小特征,并在此基础上定义小功能。这将使可重用性变得容易
  • 尝试通过传递参数使函数独立,并且只依赖它们。这样你会减少副作用

注意:由于 SO 不允许访问 Session Storage,我已经删除了所有相关代码。

const outputElement = document.getElementById("outputt");
var running = false;
var splitcounter = 0;
var lastTime = 0;
var startTime = 0;

function logTime() {
  console.log('Time: ', lastTime)
}

function resetclock() {
  running = false;
  startTime = 0;
  printTime(Date.now())
  applyStyles(true)
}

function applyStyles(isReset) {
  startstopbutton.value = running ? 'Stop' : 'Start';
  document.getElementById("outputt").classList.remove('red', 'green')
  if (!isReset) {
    document.getElementById("outputt").classList.add(running ? 'red' : 'green')
  }
}
function startstop() {
  running = !running;
  applyStyles();
  if (running) {
    if (startTime) {
      const diff = Date.now() - lastTime;
      startTime = startTime + diff;
    } else {
      startTime = Date.now()
    }
    
    updateTimer(startTime);
  } else {
    lastTime = Date.now()
    logTime();
  }
}

function printTime(startTime) {
  let differenceInMillis = Date.now() - startTime;
  let {
    hours,
    minutes,
    seconds
  } = calculateTime(differenceInMillis);
  let timeStr = `${pad(hours)}:${pad(minutes)}:${pad(seconds)}`;
  outputElement.innerText = timeStr;
}

function updateTimer(startTime) {
  if (running == true) {
    printTime(startTime)
    requestAnimationFrame(() => updateTimer(startTime));
  }
}

function calculateTime(milliS) {
  const SECONDS = 1000; // should be 1000 - only 10 to speed up the timer
  const MINUTES = 60;
  const HOURS = 60;
  const RESET = 60;

  let hours = Math.floor(milliS / SECONDS / MINUTES / HOURS);
  let minutes = Math.floor(milliS / SECONDS / MINUTES) % RESET;
  let seconds = Math.floor(milliS / SECONDS) % RESET;

  return {
    hours,
    minutes,
    seconds
  };
}

function pad(time) {
  return time.toString().padStart(2, '0');
}
.red {
  background-color: #2DB37B
}

.green {
  background-color: #B3321B
}
<input id="startstopbutton" class="buttonZ" style="width: 120px;" type="button" name="btn" value="Start" onclick="startstop();">
<input id="resetbutton" class="buttonZ" style="width: 120px;" type="button" name="btnRst1" id='btnRst1' value="Reset" onclick="resetclock();" />
<div id="outputt" class="timerClock" value="00:00:00">00:00:00</div>


推荐阅读