Can't get 'setTimeout' to delay with random time [duplicate] - javascript

This question already has answers here:
Calling functions with setTimeout()
(6 answers)
Closed 2 years ago.
I found a great countdown-timer which counts down to every full minute on the clock and have paired it with a progress bar to better visualize the remaining time. When time is up (=the countdown reaches 1 second) it triggers a certain button press.
However I would like to add a random 0-10 seconds before it calls the button press. I have followed this, this and this post, but can't seem to get it to work. What am I missing?
Here's my code so far:
//timer
setInterval(function () {
var d = new Date();
var seconds = d.getMinutes() * 60 + d.getSeconds(); //convet 00:00 to seconds for easier caculation
var totaltime = 60 * 1; //five minutes is 300 seconds!
var timeleft = totaltime - seconds % totaltime; // let's say 01:30, then current seconds is 90, 90%300 = 90, then 300-90 = 210. That's the time left!
var result = parseInt(timeleft / 60) + ':' + timeleft % 60; //formart seconds into 00:00
document.getElementById('countdown_timer').innerHTML = result;
//progressbar
function progress(timeleft, timetotal, $element) {
var progressBarWidth = (timetotal - timeleft) * ($element.width() / timetotal);
$element.find('div').animate({
width: progressBarWidth
}, "linear");
}
progress(timeleft, totaltime, $('#progress_bar'));
if (timeleft == 1) {
setTimeout (document.getElementById('next_btn').click(), Random () );
function Random() { //randomgenerator
var min = 0;
var max = 10;
var random = Math.floor(Math.random() * (max - min + 1) + min);
// document.getElementById('randomNumber').value = random;
// setTimeout(function() {document.getElementById('next_btn').click();},random)
}
}
}, 1000)
#progress_bar {
box-sizing: border-box;
width: 95%;
height: 26px;
bottom: 22px;
left: 50%;
transform: translate(-50%);
position: fixed;
background-color: #1D789F;
border-radius: 8px;
z-index: 2;
}
#progress_bar div {
height: 100%;
line-height: 23px; /* same as #progressBar height if we want text middle aligned */
width: 0;
border-radius: 8px;
background-color: #A05336;
}
#countdown_timer {
position: fixed;
bottom: 15px;
left: 15%;
z-index: 3;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="progress_bar">
<div></div></div>
<div id="countdown_timer"></div>
</div>

The second argument to setTimeout is the number of milliseconds to delay before the function runs. Your current Random function returns a number between 0 and 10; a delay of 0ms is indistinguishable from a delay of 10ms.
Multiply the result by 1000 before passing to setTimeout.
setTimeout (() => document.getElementById('next_btn').click(), 1000 * Random() );
You also need to pass a function to setTimeout (a function that, when invoked, clicks), instead of invoking the .click immediately.
//timer
setInterval(function () {
var d = new Date();
var seconds = d.getMinutes() * 60 + d.getSeconds(); //convet 00:00 to seconds for easier caculation
var totaltime = 60 * 1; //five minutes is 300 seconds!
var timeleft = totaltime - seconds % totaltime; // let's say 01:30, then current seconds is 90, 90%300 = 90, then 300-90 = 210. That's the time left!
var result = parseInt(timeleft / 60) + ':' + timeleft % 60; //formart seconds into 00:00
document.getElementById('countdown_timer').innerHTML = result;
//progressbar
function progress(timeleft, timetotal, $element) {
var progressBarWidth = (timetotal - timeleft) * ($element.width() / timetotal);
$element.find('div').animate({
width: progressBarWidth
}, "linear");
}
progress(timeleft, totaltime, $('#progress_bar'));
if (timeleft == 1) {
setTimeout( () => { document.getElementById('next_btn').click(); }, 1000 * Random() );
function Random() { //randomgenerator
var min = 0;
var max = 10;
var random = Math.floor(Math.random() * (max - min + 1) + min);
// document.getElementById('randomNumber').value = random;
// setTimeout(function() {document.getElementById('next_btn').click();},random)
}
}
}, 1000)
#progress_bar {
box-sizing: border-box;
width: 95%;
height: 26px;
bottom: 22px;
left: 50%;
transform: translate(-50%);
position: fixed;
background-color: #1D789F;
border-radius: 8px;
z-index: 2;
}
#progress_bar div {
height: 100%;
line-height: 23px; /* same as #progressBar height if we want text middle aligned */
width: 0;
border-radius: 8px;
background-color: #A05336;
}
#countdown_timer {
position: fixed;
bottom: 15px;
left: 15%;
z-index: 3;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="progress_bar">
<div></div></div>
<div id="countdown_timer"></div>
</div>

Related

Working of Digital Analog Clock in Javascript

I am a beginner and I couldn't understand the working of a Digital analog it left me confused. I was given a clock.png and only the working of clock's hand was a bit complicating.
Javascript -
const deg = 6; // setting up the value
const hr = document.querySelector('#hr');
const mn = document.querySelector('#mn');
const sc = document.querySelector('#sc');
setInterval(() => {
let day = new Date();
let hrs = day.getHours() * 30;
let min = day.getMinutes() * deg;
let sec = day.getSeconds() * deg;
hr.style.transform = `rotateZ(${(hrs)+(min/12)}deg)`;
mn.style.transform = `rotateZ(${min}deg)`;
sc.style.transform = `rotateZ(${sec}deg)`;
})
I just want to know how the set interval Function.
As stated in the docs MDN - setInterval, setInterval has optional second parameter, called delay (defined in milliseconds, default value 0). In your case, internval function needs to be called every second, so you need to pass 1000 as delay parameter value.
Below is complete working code, including example HTML/CSS.
const deg = 6;
const hr = document.querySelector('.hour-hand');
const mn = document.querySelector('.minute-hand');
const sc = document.querySelector('.second-hand');
setInterval(() => {
let day = new Date();
let hrs = day.getHours() * 30;
let min = day.getMinutes() * deg;
let sec = day.getSeconds() * deg;
// Rotating the hour, minute, and second hands to the appropriate positions
hr.style.transform = `rotateZ(${hrs + (min / 12)}deg)`;
mn.style.transform = `rotateZ(${min}deg)`;
sc.style.transform = `rotateZ(${sec}deg)`;
}, 1000); // Updating the clock every 1000 milliseconds (1 second)
.clock-container {
position: relative;
width: 250px;
height: 250px;
}
.clock-face {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
border-radius: 50%;
background-color: #333;
}
.clock-hand {
position: absolute;
background-color: white;
height: 50%;
top: 00%;
left: 50%;
transform-origin: 50% 100%;
border-radius: 4px;
}
.hour-hand {
width: 8px;
}
.minute-hand {
width: 6px;
}
.second-hand {
width: 4px;
}
<div class="clock-container">
<div class="clock-face">
<div class="clock-hand hour-hand"></div>
<div class="clock-hand minute-hand"></div>
<div class="clock-hand second-hand"></div>
</div>
</div>

How to create a progress timer based on two dates in javascript

My goal is to create a progress bar that shows a countdown in seconds between one Javascript date and one MYSQL date. So far I have the dates and can subtract them, but I can't get a value that works in seconds for the progress bar. here is my code. Creation date is from a MYSQL datetime.
JAVASCRIPT
$(document).ready(function(){
var deadline= new Date(Date.parse("<? echo $creation_date; ?>"));
var x = setInterval(function() {
var now = Date.now();
var timeleft = deadline - now;
if (timeleft < 0) {
clearInterval(x);
timeleft = 0;
}, 1000);
// draw the bar
function progress(timeleft, timetotal, $element) {
var progressBarWidth = timeleft * $element.width() / timetotal;
$element.find('div').animate({ width: progressBarWidth }, timeleft == timetotal ? 0 : 1000, 'linear');
if(timeleft > 0) {
setTimeout(function() {
progress(timeleft - 1, timetotal, $element);
}, 1000);
}
};
// 86400 is 24 hours.
progress(timeleft, 86400, $('#timerBar'));
HTML
<div id="timerBar">
<div>Time Left</div>
</div>
CSS
#timerBar {
width: 90%;
margin: 10px auto;
height: 30px;
background-color: #efd0d0;
}
#timerBar div {
height: 100%;
text-align: right;
padding: 0 30px;
line-height: 22px;
width: 0;
background-color: #d05656;
box-sizing: border-box;
}

Dynamically change animation speed

For teaching myself javascript (and for getting/giving more insight in the field of astronomy :) ), I am setting up a page that displays relative positions of sun and moon.
Right now, the speed of the sun and moon movement is still fixed, but I would really like to make this dynamically user-definable via an input field. So, the initial speed is '30', and a user can speed this up or slow this down. Obviously, the ratio between sun and moon must stay fixed. I tried a lot of things (see some relics in the code, but I can't get it to work.
Anyone with more experience with javascript can assist me in doing this? Also, I notice CPU usage gets very high during this animation. Are there simple steps in making this script more efficient?
var dagen = 0;
function speed($this){
var speedSetting = $this.value;
//alert(speedSetting);
//return per;
}
function periode(bolletje, multiplier=30){
if (bolletje == 'zon'){var per = (multiplier*24/2);}
if (bolletje == 'maan'){var per = (multiplier*24*29.5/2);}
return per;
}
function step(delta) {
elem.style.height = 100*delta + '%'
}
function animate(opts) {
var start = new Date
var id = setInterval(function() {
var timePassed = new Date - start
var progress = timePassed / opts.duration
if (progress > 1) progress = 1
var delta = opts.delta(progress)
opts.step(delta)
if (progress == 1) {
clearInterval(id)
}
}, opts.delay || 10)
}
function terugweg(element, delta, duration) {
var to = -300;
var bolletje = element.getAttribute('id');
per = periode(bolletje);
document.getElementById(bolletje).style.background='transparent';
animate({
delay: 0,
duration: duration || per,
//1 sec by default
delta: delta,
step: function(delta) {
element.style.left = ((to*delta)+300) + "px"
}
});
if(bolletje == 'zon'){
dagen ++;
}
bolletje = element;
document.getElementById('dagen').innerHTML = dagen;
//setInterval(function (element) {
setTimeout(function (element) {
move(bolletje, function(p) {return p})
}, per);
}
function move(element, delta, duration) {
var to = 300;
var bolletje = element.getAttribute('id');
per = periode(bolletje);
document.getElementById(bolletje).style.background='yellow';
animate({
delay: 0,
duration: duration || per,
//1 sec by default
delta: delta,
step: function(delta) {
element.style.left = to*delta + "px"
}
});
bolletje = element;
//setInterval(function (element) {
setTimeout(function (element) {
terugweg(bolletje, function(p) {return p})
}, per);
}
hr{clear: both;}
form{display: block;}
form label{width: 300px; float: left; clear: both;}
form input{float: right;}
.aarde{width: 300px; height: 300px; border-radius: 150px; background: url('https://domain.com/img/aarde.png');}
#zon{width: 40px; height: 40px; background: yellow; border: 2px solid yellow; border-radius: 20px; position: relative; margin-left: -20px; top: 120px;}
#maan{width: 30px; height: 30px; background: yellow; border: 2px solid yellow; border-radius: 16px; position: relative; margin-left: -15px; top: 115px;}
<form>
<div onclick="move(this.children[0], function(p) {return p}), move(this.children[1], function(p) {return p})" class="aarde">
<div id="zon"></div>
<div id="maan"></div>
</div>
Dagen: <span id="dagen">0</span>
</form>
<form>
<label><input id="snelheid" type="range" min="10" max="300" value="30" oninput="speed(this)">Snelheid: <span id="snelheidDisplay">30</span></label>
</form>
First, change onlick to oninput in speed input tag.
<input id="snelheid" type="number" value="30" oninput="speed(this)">
And in your speed() function set multiplier = $this.value. multiplier should be global:
var multiplier = 30;
function speed($this){
console.log($this.value);
multiplier = $this.value;
//alert(speedSetting);
//return per;
}
function periode(bolletje){
if (bolletje == 'zon'){var per = (multiplier*24/2);}
if (bolletje == 'maan'){var per = (multiplier*24*29.5/2);}
return per;
}
Here is an example:
https://jsfiddle.net/do4n9L03/2/
Note: multiplier is not speed, it is delay. If you increase it it become slower

How to show minute, second, hour in time progress bar

I have a time progress bar. I use this code. In this time bar, I get the time in seconds, but I want to show minute, second, hour in the time progress bar.
var timer = 0,
timeTotal = 2500,
timeCount = 20,
timeStart = 0,
cFlag;
function updateProgress(percentage) {
var x = (percentage/timeTotal)*100,
y = x.toFixed(3);
$('#pbar_innerdiv').css("width", x + "%");
$('#pbar_innertext').css("left", x + "%").text((percentage / 1000).toFixed(2) + "\00a0s");
}
function animateUpdate() {
var perc = new Date().getTime() - timeStart;
if(perc < timeTotal) {
updateProgress(perc);
timer = setTimeout(animateUpdate, timeCount);
} else {
updateProgress(timeTotal);
}
}
$(document).ready(function() {
$('#pbar_outerdiv').click(function() {
if (cFlag == undefined) {
clearTimeout(timer);
cFlag = true;
timeStart = new Date().getTime();
animateUpdate();
}
else if (!cFlag) {
cFlag = true;
animateUpdate();
}
else {
clearTimeout(timer);
cFlag = false;
}
});
});
jsfiddle.net/McNetic/hnfRe/397
You can try this. DEMO LINK HERE
<div id="pbar_outerdiv" style="width: 300px; height: 20px; border: 1px solid grey; z-index: 1; position: relative; border-radius: 5px; -moz-border-radius: 5px;">
<div id="pbar_innerdiv" style="background-color: lightblue; z-index: 2; height: 100%; width: 0%;"></div>
<div id="pbar_innertext" style="z-index: 3; position: absolute; top: 0; left: 0; height: 100%; color: black; font-weight: bold; text-align: center;">0 s</div>
</div>
<p>Click once to start!</p>
<p>Click again to toggle Start/Stop</p>
JS...
var timer = 0,
timeTotal = 250000,
timeCount = 20,
timeStart = 0,
cFlag;
function updateProgress(percentage) {
var x = (percentage/timeTotal)*100,
y = x.toFixed(3);
var totalSec= (percentage / 1000);
var min = parseInt(totalSec/60);
var sec = parseInt(totalSec%60);
var hr= parseInt(min/60);
min = parseInt(min % 60);
$('#pbar_innerdiv').css("width", x + "%");
$('#pbar_innertext').css("left", x + "%").text(hr+":"+min+":"+sec + "");
}
function animateUpdate() {
var perc = new Date().getTime() - timeStart;
if(perc < timeTotal) {
updateProgress(perc);
timer = setTimeout(animateUpdate, timeCount);
} else {
updateProgress(timeTotal);
}
}
$(document).ready(function() {
$('#pbar_outerdiv').click(function() {
if (cFlag == undefined) {
clearTimeout(timer);
cFlag = true;
timeStart = new Date().getTime();
animateUpdate();
}
else if (!cFlag) {
cFlag = true;
animateUpdate();
}
else {
clearTimeout(timer);
cFlag = false;
}
});
});
CSS...
#pbar_outerdiv { cursor: pointer; }
With percentaje (line 11):
function updateProgress(percentage) {
var x = (percentage/timeTotal)*100,
y = x.toFixed(3);
$('#pbar_innerdiv').css("width", x + "%");
$('#pbar_innertext').css("left", x + "%").text(x.toFixed(2) + '%');
}
SEE DEMO
With hours, minutes and seconds:
var seconds = 1000;
var minutes = seconds * 60;
var hours = minutes * 60;
var days = hours * 24;
var years = days * 365;
function updateProgress(percentage) {
var x = (percentage/timeTotal)*100,
y = x.toFixed(3);
$('#pbar_innerdiv').css("width", x + "%");
$('#pbar_innertext').css("left", x + "%").text( Math.floor(percentage/hours) + 'h ' + Math.floor(percentage/minutes) + 'm ' + Math.floor(percentage/seconds) + 's');
}
SEE DEMO.
I think for that you should use requestAnimationFrame:
var timeTotal = 2500,
timeStart = 0,
cFlag = false;
var seconds = 1000;
var minutes = seconds * 60;
var hours = minutes * 60;
var days = hours * 24;
var years = days * 365;
function updateProgress() {
var time = new Date().getTime() - timeStart;
var x = (time/timeTotal)*100,
y = x.toFixed(3);
$('#pbar_innerdiv').css("width", x + "%");
$('#pbar_innertext').css("left", x + "%").text( Math.floor(time/hours) + 'h ' + Math.floor(time/minutes) + 'm ' + Math.floor(time/seconds) + 's');
if(time <= timeTotal && cFlag) {
requestAnimationFrame(updateProgress);
}
}
$(document).ready(function() {
$('#pbar_outerdiv').click(function() {
if (cFlag === false) {
cFlag = true;
timeStart = new Date().getTime();
updateProgress();
}
else {
cFlag = false;
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="pbar_outerdiv" style="width: 300px; height: 20px; border: 1px solid grey; z-index: 1; position: relative; border-radius: 5px; -moz-border-radius: 5px;">
<div id="pbar_innerdiv" style="background-color: lightblue; z-index: 2; height: 100%; width: 0%;"></div>
<div id="pbar_innertext" style="z-index: 3; position: absolute; top: 0; left: 0; height: 100%; color: black; font-weight: bold; text-align: center;">0h 0m 0s</div>
</div>
<p>Click once to start!</p>
<p>Click again to toggle Start/Stop</p>
UPDATED WITH PAUSE ALLOW AND RESUME:
var timeTotal = 5 * minutes,
timePaused = 0,
timePausedStart = 0,
timeStart = 0,
cFlag = false,
stopped = false;
var seconds = 1000;
var minutes = seconds * 60;
var hours = minutes * 60;
var days = hours * 24;
var years = days * 365;
function updateProgress() {
if( !timePausedStart ) { // if not paused
var time = new Date().getTime() - timeStart - timePaused;
var x = (time/timeTotal)*100,
y = x.toFixed(3);
$('#pbar_innerdiv').css("width", x + "%");
$('#pbar_innertext').css("left", x + "%").text( Math.floor(time/hours%24) + 'h ' + Math.floor(time/minutes%60) + 'm ' + Math.floor(time/seconds) + 's');
if(time > timeTotal) {
cFlag = false;
}
if( Math.floor(time/seconds) == 3*60+30 && !stopped){ // pause at 3 m 30 s
stopped = true;
pause();
}
}
if( cFlag )
requestAnimationFrame(updateProgress);
}
$(document).ready(function() {
$('#pbar_outerdiv').click(function() {
if (cFlag === false) {
cFlag = true;
timeStart = new Date().getTime();
timePaused = 0;
updateProgress();
} else if( cFlag === true && timePausedStart ){ // reset pause
timePaused += new Date().getTime() - timePausedStart;
timePausedStart = 0;
}
else {
pause();
}
});
});
var pause = function(){
timePausedStart = new Date().getTime();
};
#pbar_outerdiv { cursor: pointer; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="pbar_outerdiv" style="width: 300px; height: 20px; border: 1px solid grey; z-index: 1; position: relative; border-radius: 5px; -moz-border-radius: 5px;">
<div id="pbar_innerdiv" style="background-color: lightblue; z-index: 2; height: 100%; width: 0%;"></div>
<div id="pbar_innertext" style="z-index: 3; position: absolute; top: 0; left: 0; height: 100%; color: black; font-weight: bold; text-align: center;">0h 0m 0s</div>
</div>
<p>Click once to start!</p>
<p>Click again to toggle Start/Stop</p>
Instead of printing (percentage / 1000).toFixed(2), you can use percentage to split your time in millisecond to h:m's.ms
You can simply compute the desired values with integer divisions
h = Math.floor(percentage / 3600000);
m = Math.floor((percentage - h * 3600000) / 60000);
s = Math.floor((percentage - h * 3600000 - m * 60000) / 1000);
ms = Math.floor(percentage - h * 3600000 - m * 60000 - s * 1000);
Then, you can just use toString() to convert your int to strings. I concatenated the values with 0 and and used slice() to keep only the two last character. This allow you to print hours, minutes, ... in two digits format
text = ("0" + h.toString() ).slice(-2) + ":" +
("0" + m.toString() ).slice(-2) + "'" +
("0" + s.toString() ).slice(-2) + "\"" +
("0" + ms.toString()).slice(-2);

Delay until fully loaded

There's a clock in my page that loads pretty fast but there's an instant when it loads where you can see it stopped. I want to make it appear only when it's fully loaded.
This is the code of the clock:
<style type="text/css">
* {
margin: 0;
padding: 0;
}
#clock {
position: relative;
width: 500px;
height: 480px;
background: url(images/clockface.png);
list-style: none;
}
#sec, #min, #hour {
position: absolute;
width: 30px;
height: 600px;
top: 0px;
left: 225px;
}
#sec {
background: url(images/sechand.png);
z-index: 3;
}
#min {
background: url(images/minhand.png);
z-index: 2;
}
#hour {
background: url(images/hourhand.png);
z-index: 1;
}
p {
text-align: center;
padding: 10px 0 0 0;
}
</style>
<script type="text/javascript">
$(document).ready(function() {
setInterval( function() {
var seconds = new Date().getSeconds();
var sdegree = seconds * 6;
var srotate = "rotate(" + sdegree + "deg)";
$("#sec").css({"-moz-transform" : srotate, "-webkit-transform" : srotate});
}, 1000 );
setInterval( function() {
var hours = new Date().getHours();
var mins = new Date().getMinutes();
var hdegree = hours * 30 + (mins / 2);
var hrotate = "rotate(" + hdegree + "deg)";
$("#hour").css({"-moz-transform" : hrotate, "-webkit-transform" : hrotate});
}, 1000 );
setInterval( function() {
var mins = new Date().getMinutes();
var mdegree = mins * 6;
var mrotate = "rotate(" + mdegree + "deg)";
$("#min").css({"-moz-transform" : mrotate, "-webkit-transform" : mrotate});
}, 1000 );
});
</script>
Thanks
<ul id="clock" style="visibility: hidden"> <!-- this is so the browser computes the position of the element but doesn't show it just yet -->
<li id="sec"></li>
<li id="hour"></li>
<li id="min"></li>
</ul>
Then:
<script type="text/javascript">
window.onload = function() { // this will be run when the whole page is loaded
document.getElementById("clock").style.visibility = "display";
};
</script>
A div does not have a load event.
On DOM ready, I would hide the clock...
document.getElementById("clock").style.display = 'none';
...and then at the end of the code of the clock, when it is finished, I would set its display to block...
document.getElementById("clock").style.display = 'block';
...or inline if that is more appropriate in your situation.

Categories

Resources