นาฬิกา Javascript นับผ่าน 60 นาทีและวินาที

Sep 29 2020

ฉันได้สร้างนาฬิกา Javascript เมื่อวินาทีและนาทีถึง 60 มันจะนับมากกว่า 60 และจะดำเนินต่อไป ...

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>

โดยทั่วไปนาฬิกาจะนับเวลาผ่านไป 60 นาทีเป็นนาทีและวินาทีฉันต้องการให้รีเซ็ตเป็น 0 แทนการกดปุ่ม 60 ฉันไม่มีเวลาทดสอบชั่วโมงแม้ว่าฉันแน่ใจว่าจะเลย 24 ไปแล้วก็ตาม

ใครช่วยอธิบายวิธีการนี้ได้บ้าง? ฉันมั่นใจว่ามันง่ายมาก แต่ฉันพยายามต่อสู้กับมันมานานเกินไปและเริ่มหงุดหงิด

คำตอบ

2 Ivar Sep 29 2020 at 20:46

คุณสามารถใช้ตัวดำเนินการส่วนที่เหลือ ( %) เพื่อตัดกลับเป็น 0 เมื่อตัวเลขผ่าน 60

ตัวอย่างเช่น

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

ดังนั้นรหัสของคุณจะมีลักษณะดังนี้:

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>

โปรดทราบว่าตัวจับเวลานี้อาจเลื่อนไปตามกาลเวลา สำหรับสาเหตุและวิธีแก้ปัญหานั้นโปรดดูวิธีสร้างตัวจับเวลาที่แม่นยำในจาวาสคริปต์

2 RickardElimää Sep 29 2020 at 21:32

คุณไม่สามารถวางใจได้ว่า setTimeout หรือ setInterval จะดำเนินการใน X มิลลิวินาที ดูวิดีโอต่อไปนี้เกี่ยวกับเหตุการณ์ที่เกิดขึ้นเพื่อทำความเข้าใจว่าเหตุใด เป็นสิ่งที่คุณควรรู้เมื่อเขียนโปรแกรมจาวาสคริปต์

สิ่งที่คุณแทนต้องทำคือการปรับปรุงองค์ประกอบของการส่งออกทุกครั้ง repaints หน้าจอที่คุณสามารถทำได้ด้วยrequestAnimationFrame คุณต้องจัดเก็บเมื่อนาฬิกาเริ่มต้นซึ่งสามารถทำได้ในหน่วยมิลลิวินาทีจากนั้นคำนวณจากความแตกต่างระหว่างเวลาเริ่มต้นและเวลาปัจจุบัน (ด้วยDate.now()) เมื่อหน้าต่างกำลังจะทาสีใหม่ requestAnimationFrameรับการเรียกกลับเป็นพารามิเตอร์ซึ่งควรเป็นวิธีการที่อัปเดตองค์ประกอบเอาต์พุตของคุณ

แก้ไข: ฉันเร่งตัวจับเวลาเพื่อแสดงกรณีการรีเซ็ตนาทีและวินาที

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

คุณสามารถใช้String.padStartเพื่อแทรก0สัญลักษณ์สำหรับค่าดิจิทัล

และแทนที่จะเรียกฟังก์ชั่นภายในsetTimeoutสำหรับคุณสามารถใช้recursive เพื่อล้างจัดการเวลาที่คุณสามารถใช้setIntervalclearInterval

และพระรามที่สองของการsetIntervalเป็นมูลค่าเพื่อที่จะนับเวลาจากวินาทีนั้นมันจะดีไปยังชุดmiliseconds1000 - 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

นี่เป็นวิธีที่ดีเกินไปสำหรับสิ่งที่คุณกำลังทำ แต่มีวิธีที่ดีในการจัดรูปแบบสตริงเวลา นอกจากนี้ยังแสดงวิธีใช้ Date.now () เพื่อติดตามความแตกต่างของเวลา

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>