Jam Javascript menghitung lebih dari 60 untuk menit dan detik

Sep 29 2020

Saya telah membuat jam Javascript, ketika detik dan menit mencapai 60 itu akan menghitung lebih dari 60 dan terus berjalan ...

function increment(){
  if(running == 1){
    setTimeout(function(){
      Dtime++;
      var hours = Math.floor(Dtime / 10 / 3600);
      if(hours <= 9){
        hours = "0" + hours;
      }
      var mins = Math.floor(Dtime / 10 / 60);
      if(mins <= 9){
        mins = "0" + mins;
      }
      var secs = Math.floor(Dtime / 10);
      if(secs <= 9){
        secs = "0" + secs;
      }
      document.getElementById("outputt").innerHTML = hours + ":" + mins + ":" + secs;
      increment();
    }, 100);
  }
}

var Dtime=0;
var running = 1;
increment();
<div id="outputt" class="timerClock" value="00:00:00">00:00:00</div>

Pada dasarnya jam menghitung melewati 60 untuk menit dan detik, saya ingin ini disetel ulang ke 0 daripada mencapai 60. Saya belum punya waktu untuk menguji jam meskipun saya yakin akan melewati 24 juga.

Tolong bisakah seseorang menjelaskan bagaimana ini akan dilakukan? Saya yakin ini sangat sederhana tetapi saya telah berhasil berjuang dengan itu terlalu lama dan saya menjadi frustrasi.

Jawaban

2 Ivar Sep 29 2020 at 20:46

Anda dapat menggunakan operator sisa ( %) untuk membungkus kembali ke 0 ketika sebuah angka melewati 60.

Sebagai contoh

  • 59 % 60 === 59
  • 60 % 60 === 0
  • 61 % 60 === 1

Jadi kode Anda akan terlihat seperti ini:

function increment() {
  if (running == 1) {
    setTimeout(function() {
      Dtime++;
      var hours = Math.floor(Dtime / 10 / 3600);
      if (hours <= 9) {
        hours = "0" + hours;
      }
      var mins = Math.floor(Dtime / 10 / 60) % 60; // Remainder operator
      if (mins <= 9) {
        mins = "0" + mins;
      }
      var secs = Math.floor(Dtime / 10) % 60; // Remainder operator
      if (secs <= 9) {
        secs = "0" + secs;
      }
      document.getElementById("outputt").innerHTML = hours + ":" + mins + ":" + secs;
      increment();
    }, 100);
  }
}

var running = 1;
var Dtime = 35980; //Setting it just under 1 hour for testing purposes
increment();
<div id="outputt" class="timerClock" value="00:00:00">00:00:00</div>

Perhatikan bahwa timer ini mungkin bergeser seiring waktu. Untuk mengapa dan bagaimana Anda bisa mengatasinya, lihat Bagaimana membuat pengatur waktu yang akurat dalam javascript?

2 RickardElimää Sep 29 2020 at 21:32

Anda tidak dapat mempercayai bahwa setTimeout atau setInterval akan dieksekusi tepat dalam X milidetik. Lihat video berikut tentang loop acara untuk memahami alasannya. Itu adalah sesuatu yang harus Anda ketahui saat memprogram javascript.

Yang perlu Anda lakukan adalah memperbarui elemen keluaran setiap kali layar menggambar ulang, yang dapat Anda lakukan dengan requestAnimationFrame . Anda perlu menyimpan saat jam mulai, yang bisa dilakukan dalam milidetik, dan kemudian menghitung dari selisih antara waktu mulai dan waktu saat ini (dengan Date.now()) ketika jendela akan melakukan pengecatan ulang. requestAnimationFramemengambil callback sebagai parameter, yang seharusnya menjadi metode yang memperbarui elemen keluaran Anda.

EDIT: Saya mempercepat pengatur waktu untuk menunjukkan kasus reset menit dan kedua.

const outputElement = document.getElementById("output");
var startTime = 0;

function startTimer() {
  startTime = Date.now();
  updateTimer();
}

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

  outputElement.innerText = timeStr;

  requestAnimationFrame(updateTimer);
}

function calculateTime(timeInMillis) {
  const SECONDS = 10; // should be 1000 - only 10 to speed up the timer
  const MINUTES = 60;
  const HOURS   = 60;
  const RESET   = 60;
  
  let hours   = Math.floor(timeInMillis / SECONDS / MINUTES / HOURS);
  let minutes = Math.floor(timeInMillis / SECONDS / MINUTES) % RESET;
  let seconds = Math.floor(timeInMillis / SECONDS) % RESET;
  
  return {hours, minutes, seconds};
}

function pad(time) {
  return time.toString().padStart(2, '0');
}

startTimer();
<div id="output" class="timerClock" value="00:00:00">00:00:00</div>

1 DerekWang Sep 29 2020 at 20:49

Anda dapat menggunakan String.padStartuntuk memasukkan 0simbol untuk nilai digital.

Dan alih-alih memanggil fungsi di dalam setTimeoutuntuk recursive, Anda dapat menggunakan setInterval. Untuk menghapus pengendali waktu, Anda dapat menggunakan clearInterval.

Dan parameter kedua setIntervaladalah milisecondsnilai sehingga untuk menghitung waktu per detik, itu akan bagus untuk diatur 1000 - 1 second.

let Dtime = 0;
setInterval(function() {
  Dtime++;
  const hours = Math.floor(Dtime / 3600).toString();
  const mins = Math.floor((Dtime % 3600) / 60).toString();
  const secs = (Dtime % 60).toString();
  document.getElementById("outputt").innerHTML = hours.padStart(2, '0') + ":" + mins.padStart(2, '0') + ":" + secs.padStart(2, '0');
}, 1000);
<div id="outputt" class="timerClock" value="00:00:00">00:00:00</div>

epascarello Sep 30 2020 at 01:07

Ini agak berlebihan untuk apa yang Anda lakukan, tetapi memiliki metode yang bagus untuk memformat string waktu. Ini juga menunjukkan bagaimana menggunakan Date.now () untuk melacak perbedaan waktu.

class StopWatch { 

  startTime = 0
  previousDuration = 0
  currentDuration = 0
  timer = null;
  listeners = {
    update: [],
    mark: [],
    reset: []
  }
  marks = []
  
  start() {
    if (this.timer) return;
    this.previousDuration += this.currentDuration;
    this.currentDuration = 0;
    this.startTime = Date.now();
    this.run();
  }
  
  stop() {
    if (!this.timer) return;
    this.setDuration();
    window.clearTimeout(this.timer);
    this.timer = null;
  }
  
  run() {
    this.setDuration();
    this.timer = window.setTimeout(this.run.bind(this), 10);
  }
  
  setDuration () {
    this.currentDuration = Date.now() - this.startTime;
    this.trigger('update');
  }
  
  trigger (evtName) {
    const details = {
      time: this.msToTime(this.currentDuration + this.previousDuration),
      marks: [...this.marks]
    };
    this.listeners[evtName].forEach(cb => cb(details));
  }
  
  mark () {
    this.marks.push(this.msToTime(this.currentDuration + this.previousDuration));
    this.trigger('mark');
  }
  
  reset() {
    if (this.timer) window.clearTimeout(this.timer);
    this.currentDuration = 0;
    this.previousDuration = 0;
    this.marks = [];
    this.trigger('update');
    this.trigger('reset');
  }
  
  on (event, callback) {
    var arr = this.listeners[event];
    if (!arr) throw(`unknown event ${event}`);
    arr.push(callback);
    return this;
  }
  
  msToTime (duration) {
    let milliseconds = parseInt((duration % 1000));
    let seconds = Math.floor((duration / 1000) % 60);
    let minutes = Math.floor((duration / (1000 * 60)) % 60);
    let hours = Math.floor((duration / (1000 * 60 * 60)) % 24);

    hours = hours.toString().padStart(2, '0');
    minutes = minutes.toString().padStart(2, '0');
    seconds = seconds.toString().padStart(2, '0');
    milliseconds = milliseconds.toString().padStart(3, '0');

    return hours + ":" + minutes + ":" + seconds + "." + milliseconds;
  }
}

const out = document.querySelector("#out");
const list = document.querySelector("#list");

const myStopWatch = new StopWatch();
myStopWatch
  .on('update', function(data) {
    out.textContent = data.time;
  })
  .on('mark', function(data) {
    var li = document.createElement("li");
    li.textContent = data.marks.pop();
    list.appendChild(li);
  }).on('reset', function () {
    list.innerHTML = '';
  });

const wrapper = document.querySelector("#actions");
wrapper.addEventListener("click", function (evt) {
  const action = evt.target.dataset.action;
  myStopWatch[action]();
});
<div id="out"></div>
<div id="actions">
  <button data-action="start">Start</button>
  <button data-action="stop">Stop</button>
  <button data-action="mark">Mark Time</button>
  <button data-action="reset">Reset</button>
</div>

<ol id="list"></ol>