L'horloge Javascript compte au-delà de 60 minutes et secondes
J'ai fait une horloge Javascript, quand les secondes et les minutes atteindront 60, cela comptera plus de 60 et continuera ...
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>
Fondamentalement, l'horloge compte au-delà de 60 minutes et secondes, j'aimerais que cela soit remis à 0 au lieu d'atteindre 60. Je n'ai pas eu le temps de tester les heures même si je suis sûr que cela dépasserait 24 également.
Quelqu'un peut-il expliquer comment cela serait fait? Je suis certain que c'est très simple, mais j'ai réussi à me battre un peu trop longtemps et je suis frustré.
Réponses
Vous pouvez utiliser l' opérateur reste ( %) pour revenir à 0 lorsqu'un nombre dépasse 60.
Par exemple
59 % 60 === 5960 % 60 === 061 % 60 === 1
Donc, votre code ressemblerait à ceci:
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>
Notez que cette minuterie peut dériver avec le temps. Pour savoir pourquoi et comment résoudre ce problème, consultez Comment créer un minuteur précis en javascript?
Vous ne pouvez pas être sûr que setTimeout ou setInterval s'exécutera dans exactement X millisecondes. Regardez la vidéo suivante sur les boucles d'événements pour comprendre pourquoi. C'est quelque chose que vous devez savoir lors de la programmation de javascript.
Au lieu de cela, vous devez mettre à jour l'élément de sortie à chaque fois que l'écran est repeint, ce que vous pouvez faire avec requestAnimationFrame . Vous devez enregistrer le démarrage de l'horloge, ce qui peut être fait en millisecondes, puis calculer à partir de là la différence entre l'heure de début et l'heure actuelle (avec Date.now()) lorsque la fenêtre est sur le point de repeindre. requestAnimationFrameprend un rappel comme paramètre, qui devrait être la méthode qui met à jour votre élément de sortie.
EDIT: J'ai accéléré la minuterie pour afficher la réinitialisation des minutes et des secondes.
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>
Vous pouvez utiliser String.padStartpour insérer un 0symbole pour les valeurs numériques.
Et au lieu d'appeler function inside setTimeoutfor recursive, vous pouvez utiliser setInterval. Pour effacer le gestionnaire de temps, vous pouvez utiliser clearInterval.
Et le deuxième paramètre de setIntervalest milisecondsvalue donc pour compter le temps en secondes, il sera bon de le définir 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>
C'est un peu exagéré pour ce que vous faites, mais cela a une bonne méthode pour formater une chaîne de temps. Il montre également comment utiliser Date.now () pour suivre le décalage horaire.
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>