Почему миллисекунды отображаются неверно в js секундомере - PullRequest
2 голосов
/ 13 июля 2020

Я делаю секундомер с js, но мои миллисекунды выглядят неверно, как будто они показывают не то. Думал, что с моим редактором что-то не так, но на repl.it он выглядит так же ... Я думаю, что секунды отображаются в миллисекундах или что-то в этом роде.

var startTimerButton = document.querySelector('.startTimer');
var pauseTimerButton = document.querySelector('.pauseTimer');
var timerDisplay = document.querySelector('.timer');
var startTime;
var updatedTime;
var difference;
var tInterval;
var savedTime;
var paused = 0;
var running = 0;

function startTimer() {
  if (!running) {
    startTime = new Date().getTime();
    tInterval = setInterval(getShowTime, 1);
    paused = 0;
    running = 1;
    startTimerButton.style.cursor = "auto";
    pauseTimerButton.style.cursor = "pointer";
  }
}

function pauseTimer() {
  if (!difference) {
    // if timer never started, don't allow pause button to do anything
  } else if (!paused) {
    clearInterval(tInterval);
    savedTime = difference;
    paused = 1;
    running = 0;
    pauseTimerButton.classList.add('lighter');
    startTimerButton.style.cursor = "pointer";
    pauseTimerButton.style.cursor = "auto";
  } else {}
}

function resetTimer() {
  document.location.reload();
}

function getShowTime() {
  updatedTime = new Date().getTime();
  if (savedTime) {
    difference = (updatedTime - startTime) + savedTime;
  } else {
    difference = updatedTime - startTime;
  }
  var hours = Math.floor((difference % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
  var minutes = Math.floor((difference % (1000 * 60 * 60)) / (1000 * 60));
  var seconds = Math.floor((difference % (1000 * 60)) / 1000);
  var milliseconds = Math.floor((difference % (1000 * 60)) / 100);
  hours = (hours < 10) ? "0" + hours : hours;
  minutes = (minutes < 10) ? "0" + minutes : minutes;
  seconds = (seconds < 10) ? "0" + seconds : seconds;
  milliseconds = (milliseconds < 100) ? (milliseconds < 10) ? "00" + milliseconds : "0" + milliseconds : milliseconds;
  timerDisplay.innerHTML = hours + ':' + minutes + ':' + seconds + ':' + milliseconds;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.13.1/css/all.min.css" rel="stylesheet" />
<h1>Stopwatch</h1>
<div class="timer">00:00:00:00</div>
<div class="startTimer reset" onclick="startTimer()"> Start
  <i class="fas fa-play"></i>
</div>
<div class="pauseTimer reset" onclick="pauseTimer()"> Stop
  <i class="fas fa-pause"></i>
</div>
<div class="resetTimer reset" onclick="resetTimer()">Reset</div>

Ответы [ 6 ]

2 голосов
/ 13 июля 2020

Для миллисекунд вам не нужно ничего делить, вы просто модифицируете их на 1000, потому что именно столько миллисекунд в секунде.

var milliseconds = Math.floor(difference % 1000);

Кроме того, вы начинаете время 00:00:00:00 отсутствует последний ноль, т.е. :000.

Создание констант избавляет ваш мозг от большого объема синтаксического анализа.

const MS_PER_SEC  = 1000
const MS_PER_MIN  = MS_PER_SEC  * 60
const MS_PER_HOUR = MS_PER_MIN  * 60
const MS_PER_DAY  = MS_PER_HOUR * 24

Это делает функцию форматирования самодокументированной.

function formatTime(ms) {
  var hours        = Math.floor((ms % MS_PER_DAY)  / MS_PER_HOUR);
  var minutes      = Math.floor((ms % MS_PER_HOUR) / MS_PER_MIN);
  var seconds      = Math.floor((ms % MS_PER_MIN)  / MS_PER_SEC);
  var milliseconds = Math.floor( ms % MS_PER_SEC);

  return [
    ('' + hours).padStart(2, '0'),
    ('' + minutes).padStart(2, '0'),
    ('' + seconds).padStart(2, '0'),
    ('' + milliseconds).padStart(3, '0')
  ].join(':');
}

Демо

const MS_PER_SEC  = 1000;
const MS_PER_MIN  = MS_PER_SEC  * 60;
const MS_PER_HOUR = MS_PER_MIN  * 60;
const MS_PER_DAY  = MS_PER_HOUR * 24;

var startTimerButton = document.querySelector('.startTimer');
var pauseTimerButton = document.querySelector('.pauseTimer');
var timerDisplay = document.querySelector('.timer');
var startTime;
var updatedTime;
var difference;
var tInterval;
var savedTime;
var paused = 0;
var running = 0;

function startTimer() {
  if (!running) {
    startTime = new Date().getTime();
    tInterval = setInterval(getShowTime, 1);
    paused = 0;
    running = 1;
    startTimerButton.style.cursor = "auto";
    pauseTimerButton.style.cursor = "pointer";
  }
}

function pauseTimer() {
  if (!difference) {
    // if timer never started, don't allow pause button to do anything
  } else if (!paused) {
    clearInterval(tInterval);
    savedTime = difference;
    paused = 1;
    running = 0;
    pauseTimerButton.classList.add('lighter');
    startTimerButton.style.cursor = "pointer";
    pauseTimerButton.style.cursor = "auto";
  } else {}
}

function resetTimer() {
  document.location.reload();
}

function getShowTime() {
  updatedTime = new Date().getTime();
  if (savedTime) {
    difference = (updatedTime - startTime) + savedTime;
  } else {
    difference = updatedTime - startTime;
  }
  
  timerDisplay.innerHTML = formatTime(difference);
}

function formatTime(ms) {
  var hours        = Math.floor((ms % MS_PER_DAY)  / MS_PER_HOUR);
  var minutes      = Math.floor((ms % MS_PER_HOUR) / MS_PER_MIN);
  var seconds      = Math.floor((ms % MS_PER_MIN)  / MS_PER_SEC);
  var milliseconds = Math.floor( ms % MS_PER_SEC);

  return [
    ('' + hours).padStart(2, '0'),
    ('' + minutes).padStart(2, '0'),
    ('' + seconds).padStart(2, '0'),
    ('' + milliseconds).padStart(3, '0')
  ].join(':');
}
.timer {
  font-family: monospace;
  font-size: 2em;
}

.reset {
  display: inline-block;
  border: thin solid grey;
  padding: 0.25em;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.13.1/css/all.min.css" rel="stylesheet" />
<h1>Stopwatch</h1>
<div class="timer">00:00:00:000</div>
<div class="startTimer reset" onclick="startTimer()"> Start
  <i class="fas fa-play"></i>
</div>
<div class="pauseTimer reset" onclick="pauseTimer()"> Stop
  <i class="fas fa-pause"></i>
</div>
<div class="resetTimer reset" onclick="resetTimer()">Reset</div>
2 голосов
/ 13 июля 2020

Ваш расчет milliseconds неверен. Поскольку difference - это общее количество миллисекунд, все, что вам нужно сделать для получения миллисекундной части результата, - это взять модуль 1000.

var milliseconds = difference % 1000;

var startTimerButton = document.querySelector('.startTimer');
var pauseTimerButton = document.querySelector('.pauseTimer');
var timerDisplay = document.querySelector('.timer');
var startTime;
var updatedTime;
var difference;
var tInterval;
var savedTime;
var paused = 0;
var running = 0;

function startTimer() {
  if (!running) {
    startTime = new Date().getTime();
    tInterval = setInterval(getShowTime, 1);
    paused = 0;
    running = 1;
    startTimerButton.style.cursor = "auto";
    pauseTimerButton.style.cursor = "pointer";
  }
}

function pauseTimer() {
  if (!difference) {
    // if timer never started, don't allow pause button to do anything
  } else if (!paused) {
    clearInterval(tInterval);
    savedTime = difference;
    paused = 1;
    running = 0;
    pauseTimerButton.classList.add('lighter');
    startTimerButton.style.cursor = "pointer";
    pauseTimerButton.style.cursor = "auto";
  } else {}
}

function resetTimer() {
  document.location.reload();
}

function getShowTime() {
  updatedTime = new Date().getTime();
  if (savedTime) {
    difference = (updatedTime - startTime) + savedTime;
  } else {
    difference = updatedTime - startTime;
  }
  var hours = Math.floor((difference % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
  var minutes = Math.floor((difference % (1000 * 60 * 60)) / (1000 * 60));
  var seconds = Math.floor((difference % (1000 * 60)) / 1000);
  var milliseconds = difference % 1000;
  hours = (hours < 10) ? "0" + hours : hours;
  minutes = (minutes < 10) ? "0" + minutes : minutes;
  seconds = (seconds < 10) ? "0" + seconds : seconds;
  milliseconds = (milliseconds < 100) ? (milliseconds < 10) ? "00" + milliseconds : "0" + milliseconds : milliseconds;
  timerDisplay.innerHTML = hours + ':' + minutes + ':' + seconds + ':' + milliseconds;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.13.1/css/all.min.css" rel="stylesheet" />
<h1>Stopwatch</h1>
<div class="timer">00:00:00:00</div>
<div class="startTimer reset" onclick="startTimer()"> Start
  <i class="fas fa-play"></i>
</div>
<div class="pauseTimer reset" onclick="pauseTimer()"> Stop
  <i class="fas fa-pause"></i>
</div>
<div class="resetTimer reset" onclick="resetTimer()">Reset</div>
1 голос
/ 13 июля 2020

в вашей строке var milliseconds = Math.floor((difference % (1000 * 60)) / 100); неверный расчет. Метод getTime объекта Date уже возвращает значение в миллисекундах.

var startTimerButton = document.querySelector('.startTimer');
var pauseTimerButton = document.querySelector('.pauseTimer');
var timerDisplay = document.querySelector('.timer');
var startTime;
var updatedTime;
var difference;
var tInterval;
var savedTime;
var paused = 0;
var running = 0;

function startTimer() {
  if (!running) {
    startTime = new Date().getTime();
    tInterval = setInterval(getShowTime, 1);
    paused = 0;
    running = 1;
    startTimerButton.style.cursor = "auto";
    pauseTimerButton.style.cursor = "pointer";
  }
}

function pauseTimer() {
  if (!difference) {
    // if timer never started, don't allow pause button to do anything
  } else if (!paused) {
    clearInterval(tInterval);
    savedTime = difference;
    paused = 1;
    running = 0;
    pauseTimerButton.classList.add('lighter');
    startTimerButton.style.cursor = "pointer";
    pauseTimerButton.style.cursor = "auto";
  } else {}
}

function resetTimer() {
  document.location.reload();
}

function getShowTime() {
  updatedTime = new Date().getTime();
  if (savedTime) {
    difference = (updatedTime - startTime) + savedTime;
  } else {
    difference = updatedTime - startTime;
  }
  var hours = Math.floor((difference % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
  var minutes = Math.floor((difference % (1000 * 60 * 60)) / (1000 * 60));
  var seconds = Math.floor((difference % (1000 * 60)) / 1000);

  //here!
  var milliseconds = difference % 1000; //<<<<<  this line
  //var milliseconds = Math.floor((difference % (1000 * 60)) / 100); //<<<<<  instead of this
  
  hours = (hours < 10) ? "0" + hours : hours;
  minutes = (minutes < 10) ? "0" + minutes : minutes;
  seconds = (seconds < 10) ? "0" + seconds : seconds;
  milliseconds = (milliseconds < 100) ? (milliseconds < 10) ? "00" + milliseconds : "0" + milliseconds : milliseconds;
  timerDisplay.innerHTML = hours + ':' + minutes + ':' + seconds + ':' + milliseconds;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.13.1/css/all.min.css" rel="stylesheet" />
<h1>Stopwatch</h1>
<div class="timer">00:00:00:00</div>
<div class="startTimer reset" onclick="startTimer()"> Start
  <i class="fas fa-play"></i>
</div>
<div class="pauseTimer reset" onclick="pauseTimer()"> Stop
  <i class="fas fa-pause"></i>
</div>
<div class="resetTimer reset" onclick="resetTimer()">Reset</div>

Я как можно меньше менял код, но это далеко не оптимальное решение, код довольно сложно читать и может содержать слишком много шагов .

Главный вывод здесь заключается в том, что вам не нужно преобразовывать значение времени в миллисекундах, если оно уже указано в миллисекундах.

Вот фрагмент кода, который был бы больше читаемый:

//*********************************
//constants, state variables and object declarations
//*********************************
const MS_PER_SEC = 1000;
const MS_PER_MIN = MS_PER_SEC * 60;
const MS_PER_HOUR = MS_PER_MIN * 60;
const MS_PER_DAY = MS_PER_HOUR * 24;

var running = false;
var startTime = null;
var pausedTimer = null; //elapsed milliseconds already in timer

var timerObject = { //encapsulating data and methods (preferrably in a different file)
  hours: 0,
  minutes: 0,
  seconds: 0,
  milliseconds: 0,

  clearTimer: function() {
    this.hours = 0;
    this.minutes = 0;
    this.seconds = 0;
    this.milliseconds = 0;
  },
  
  setTimer: function(ms) {
    this.hours = Math.floor(ms % (MS_PER_DAY) / MS_PER_HOUR);
    this.minutes = Math.floor(ms % (MS_PER_HOUR) / MS_PER_MIN);
    this.seconds = Math.floor(ms % (MS_PER_MIN) / MS_PER_SEC);
    this.milliseconds = ms % MS_PER_SEC;
  },

  formatTime: function() {
    return [
        ("" + this.hours).padStart(2, '0'),
        ("" + this.minutes).padStart(2, '0'),
        ("" + this.seconds).padStart(2, '0'),
      ].join(":") +
      "." + ('' + this.milliseconds).padStart(3, '0');
  }
};


//*********************************
//Actual functions used in the page
//*********************************
function startTimer() {
  if (!running) { //ignore if already running
    if (startTime != null && pausedTimer != null) {
      //if timer was paused, both values should be != null

      startTime.setTime((new Date()).getTime() - pausedTimer);
      pausedTimer = null; //not necessary, but I like to make stuff crash when I make a mistake
    } else {
      //consider the timer as new or reset otherwise
      startTime = new Date();
    }

    running = true;
    updateTimer();
  }
}

function pauseTimer() {
  if (running) {
    running = false;
    var currentTime = new Date();
    pausedTimer = currentTime.getTime() - startTime.getTime();
  }
  updateTimer();
}

function resetTimer() {
  running = false;
  startTime = null;
  pausedTimer = null;
  timerObject.clearTimer();
  updateTimer();
}

function updateTimer() {
  if (running) {
    var currentTime = new Date();
    var difference = currentTime.getTime() - startTime.getTime();
    timerObject.setTimer(difference);
    setTimeout(updateTimer, 31);
  }


  var timerDisplay = document.getElementById("timer");
  timerDisplay.innerHTML = timerObject.formatTime();
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.13.1/css/all.min.css" rel="stylesheet" />
<h1>Stopwatch</h1>
<div class="timer" id="timer">
  00:00:00:000
</div>
<div class="startTimer reset" onclick="startTimer()">
  Start <i class="fas fa-play"></i>
</div>
<div class="pauseTimer reset" onclick="pauseTimer()">
  Pause <i class="fas fa-pause"></i>
</div>
<div class="resetTimer reset" onclick="resetTimer()">
  Reset
</div>
0 голосов
/ 13 июля 2020

Проблема в том, что код, который вычисляет миллисекунды.

Вместо ...

Math.floor((difference % (1000 * 60)) / 100);

... должен быть просто ...

Math.floor(difference % 1000);

Вот так:

var startTimerButton = document.querySelector('.startTimer');
var pauseTimerButton = document.querySelector('.pauseTimer');
var timerDisplay = document.querySelector('.timer');
var startTime;
var updatedTime;
var difference;
var tInterval;
var savedTime;
var paused = 0;
var running = 0;

function startTimer() {
  if (!running) {
    startTime = new Date().getTime();
    tInterval = setInterval(getShowTime, 1);
    paused = 0;
    running = 1;
    startTimerButton.style.cursor = "auto";
    pauseTimerButton.style.cursor = "pointer";
  }
}

function pauseTimer() {
  if (!difference) {
    // if timer never started, don't allow pause button to do anything
  } else if (!paused) {
    clearInterval(tInterval);
    savedTime = difference;
    paused = 1;
    running = 0;
    pauseTimerButton.classList.add('lighter');
    startTimerButton.style.cursor = "pointer";
    pauseTimerButton.style.cursor = "auto";
  } else {}
}

function resetTimer() {
  document.location.reload();
}

function getShowTime() {
  updatedTime = new Date().getTime();
  if (savedTime) {
    difference = (updatedTime - startTime) + savedTime;
  } else {
    difference = updatedTime - startTime;
  }
  var hours = Math.floor((difference % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
  var minutes = Math.floor((difference % (1000 * 60 * 60)) / (1000 * 60));
  var seconds = Math.floor((difference % (1000 * 60)) / 1000);
  var milliseconds = Math.floor(difference % 1000);
  hours = (hours < 10) ? "0" + hours : hours;
  minutes = (minutes < 10) ? "0" + minutes : minutes;
  seconds = (seconds < 10) ? "0" + seconds : seconds;
  milliseconds = (milliseconds < 100) ? (milliseconds < 10) ? "00" + milliseconds : "0" + milliseconds : milliseconds;
  timerDisplay.innerHTML = hours + ':' + minutes + ':' + seconds + ':' + milliseconds;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.13.1/css/all.min.css" rel="stylesheet" />
<h1>Stopwatch</h1>
<div class="timer">00:00:00:00</div>
<div class="startTimer reset" onclick="startTimer()"> Start
  <i class="fas fa-play"></i>
</div>
<div class="pauseTimer reset" onclick="pauseTimer()"> Stop
  <i class="fas fa-pause"></i>
</div>
<div class="resetTimer reset" onclick="resetTimer()">Reset</div>
0 голосов
/ 13 июля 2020

Первое:

Используйте такие вещи, как jsbin.

  var hours = Math.floor((difference % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
  var minutes = Math.floor((difference % (1000 * 60 * 60)) / (1000 * 60));
  var seconds = Math.floor((difference % (1000 * 60)) / 1000);
  var milliseconds = Math.floor((difference % (1000 * 60)) % 1e3 );

Это должно работать: https://jsbin.com/yihelay/3/edit?html, js, вывод

  • Вы очень странно рассчитываете это время.
  • Лучше использовать setTimeout вместо setInterval (риск перезаписи tid и утечки памяти)
  • Вы не должны использовать интервал 1 мс (это тоже fast) для пользователя, использующего монитор и глаза, достаточно 30-50 мс
  • Вы не должны зависеть от интервалов при расчете прошедшего времени - вы должны использовать new Date ();
0 голосов
/ 13 июля 2020

В этом коде кажется, что вы устанавливаете milliseconds на один порядок, отличный от seconds, тогда как он должен отличаться на три порядка:

var seconds = Math.floor((difference % (1000 * 60)) / 1000);
var milliseconds = Math.floor((difference % (1000 * 60)) / 100);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...