Working of Digital Analog Clock in Javascript - 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>

Related

How to add timer inside the progress bar

I want to add a timer which decrease Automatically (like 10 seconds, 9 seconds... till 0 seconds) but the progress bar will increase. And I am new to javascript, and the below code also copied from another site , so please help me in adding timer inside the progress bar
Till now I did this code
I want to make like this
Demo
<div class="progress"></div>
<style>
.progress-bar {
height: 20px;
background: #1da1f2;
box-shadow: 2px 14px 15px -7px rgba(30, 166, 250, 0.36);
border-radius: 50px;
transition: all 0.5s;
}
.progress {
width: 100%;
display: flex;
flex-flow: column nowrap;
justify-content: center;
align-items: start;
background: #e6e9ff;
border-radius: 20px;
box-shadow: 0px 10px 50px #abb7e9;
}
</style>
<script>
/*
* (class)Progress<nowValue, minValue, maxValue>
*/
//helper function-> return <DOMelement>
function elt(type, prop, ...childrens) {
let elem = document.createElement(type);
if (prop) Object.assign(elem, prop);
for (let child of childrens) {
if (typeof child == "string") elem.appendChild(document.createTextNode(child));
else elem.appendChild(elem);
}
return elem;
}
//Progress class
class Progress {
constructor(now, min, max, options) {
this.dom = elt("div", {
className: "progress-bar"
});
this.min = min;
this.max = max;
this.intervalCode = 0;
this.now = now;
this.syncState();
if(options.parent){
document.querySelector(options.parent).appendChild(this.dom);
}
else document.body.appendChild(this.dom)
}
syncState() {
this.dom.style.width = this.now + "%";
}
startTo(step, time) {
if (this.intervalCode !== 0) return;
this.intervalCode = setInterval(() => {
console.log("sss")
if (this.now + step > this.max) {
this.now = this.max;
this.syncState();
clearInterval(this.interval);
this.intervalCode = 0;
return;
}
this.now += step;
this.syncState()
}, time)
}
end() {
this.now = this.max;
clearInterval(this.intervalCode);
this.intervalCode = 0;
this.syncState();
}
}
let pb = new Progress(15, 0, 100, {parent : ".progress"});
//arg1 -> step length
//arg2 -> time(ms)
pb.startTo(5, 500);
//end to progress after 5s
setTimeout( () => {
pb.end()
}, 10000)
</script>
I think the core problem is that the code you copied is overly complicated especially for beginners. What I would recommend is to start from what you know and build up.
Here is the functionality you want written using only core principles of JavaScript and CSS.
let initialTime = 10; //All time in seconds
let timeLeft = initialTime;
let interval;
let progressBarTextElement = document.getElementById('progress-bar-text');
let progressBarElement = document.getElementById('progress-bar');
function render() {
let progressPercentage = (1 - (timeLeft / initialTime) ) * 100;
progressBarElement.style.width = progressPercentage + '%';
progressBarTextElement.innerHTML = timeLeft + 's';
}
function tick() {
timeLeft = timeLeft - 1;
if(timeLeft <= 0) {
clearInterval(interval); //Stops interval
}
render(); //Updates html
}
function startProgressBar() {
interval = setInterval(tick, 1000); //Will call tick every second
render();
}
startProgressBar();
html {font-family: -apple-system,BlinkMacSystemFont,"Segoe UI","Roboto","Oxygen","Ubuntu","Cantarell","Fira Sans","Droid Sans","Helvetica Neue",sans-serif;}
.progress-bar-continer {
height: 80px;
width: 100%;
position: relative;
display: flex;
justify-content: center;
align-items: center;
background-color: #406086;
}
.progress-bar {
background-color: #1b3e80;
position: absolute;
top: 0;
bottom: 0;
left: 0;
width: 0%;
transition: width 1s; /* Makes progressBar smooth */
transition-timing-function: linear; /* Try to remove this line for more tick tock feel */
}
.progress-bar-text {
color: white;
font-size: 24px;
font-weight: 700;
position: relative;
z-index: 1;
}
<div class="progress-bar-continer">
<div class="progress-bar" id="progress-bar"></div>
<div class="progress-bar-text" id="progress-bar-text"></div>
<div>
Try to understand the code best you can and you will have no problems adding any features you want on top of it. All the fancy stuff will come later with experience.

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

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>

Time conditions in javascript

could anyone help me with conditions based on time?
css:
Day {
position: absolute;
width: 360px;
height: 360px;
background-image: url("../image/BackgroundDay.png");
background-repeat: no-repeat;
}
Night {
position: relative;
width: 360px;
height: 360px;
background-image: url("../image/BackgroundNight.png");
background-repeat: no-repeat;
}
html
<img id="Day" alt="" style="opacity: 0;"/>
<img id="Night" alt="" style="opacity: 0;"/>
js
var dayToNight1 = '19:05:00';
var dayToNight2 = '19:05:05';
var dayToNight3 = '19:05:10';
var dayToNight4 = '19:05:15';
var dayToNight5 = '19:05:20';
var dayToNight6 = '19:05:25';
var dayToNight7 = '19:05:30';
var dayToNight8 = '19:05:35';
var dayToNight9 = '19:05:40';
var dayToNight10 = '19:05"45';
if(time > dayToNight1)
{
document.getElementById("Day").style.opacity = "0.9";
document.getElementById("Night").style.opacity = "0.1";
} // i got these conditions 10, I just didnt add them so it is not that long.
var nightToDay1 = '08:00:00';
var nightToDay2 = '08:00:05';
var nightToDay3 = '08:00:10';
var nightToDay4 = '08:00:15';
var nightToDay5 = '08:00:20';
var nightToDay6 = '08:00:25';
var nightToDay7 = '08:00:30';
var nightToDay8 = '08:00:35';
var nightToDay9 = '08:00:40';
var nightToDay10 = '08:00:45';
if(time > nightToDay1 && time <= '19:05:00')
{
document.getElementById("Day").style.opacity = "0.1";
document.getElementById("Night").style.opacity = "0.9";
}// same here 10 conditions
My problem is. I have two images layered on top of each other.
I would like to change from Day to Night if specific time comes. So if time reaches 19:00:00 I want to slowly change background from Day to Night just using opacity.
Then I will go from Night to Day in 08:00:00. But here comes the problem, I dont know how to make that condition and tell if (time > 19:00:00) start changing opacity for both images and go from Day to Night If time reaches 19:00:00 it just insta blick to the night without my opacity transition.
Could you give me quick idea how to make specific condition on time using javascript please? Thank you for any idea. Or if you have any other idea how to make something like that more effectively I would appreciate that
I think this might get you a little closer to what you need. Instead of specifying times manually, it's easier to find out how far you are between the start and end of the transition, and then use that to set the opacity.
Times are represented here as arrays of [hours, minutes] and we then find how many total minutes there are in each time.
I imagine this isn't quite perfect yet but it should hopefully illustrate what is possible:
const getTotalMinutes = ([hours, minutes]) =>
(hours * 60) + minutes;
const transitionStart = getTotalMinutes([9, 13]);
const transitionEnd = getTotalMinutes([9, 15]);
const getCurrentTransitionState = () => {
const now = new Date();
const totalMinutes = getTotalMinutes([
now.getHours(),
now.getMinutes(),
]);
const transitionTotal = transitionEnd - transitionStart;
const timeIntoTransition = totalMinutes - transitionStart;
if (timeIntoTransition >= transitionTotal) {
return 1;
}
return timeIntoTransition > 0 ?
timeIntoTransition / transitionTotal :
0;
}
setInterval(() => {
const current = getCurrentTransitionState();
document.getElementById('day').style.opacity = 1-current;
}, 1000);
img {
position: fixed;
top: 0;
left: 0;
transition: all 10s ease;
width: 100vw;
}
<img id="night" src="http://sarahstup.com/wp/wp-content/uploads/2017/01/night-time-background.jpg" />
<img id="day" src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT-OLKhRVHgSrPFxIY8n7ZmrgpZQFvgxeT7p3DWifbHBKoF1D57zg" />

Javascript div width countdown

I'm trying to visualize a countdown via a div's width. This could be used for something like a banner system showing when the next banner will slide in, or for a notification system showing how long the notification will be visible.
So in my example below, I have the .outer div emptied after 5 seconds, but the .timer div's width is not reaching width: 0%; at the same time as the setTimeout() kicks in.
The variable len would represent how long the banner or notification would be shown for.
The calculation in the variable offset is what is throwing me off (I think), I cannot seem to get the calculation correct. I would like it to be dynamic, meaning, no matter what len is and what the width of the outer/parent div is, it will always take len time to reach width: 0%;.
I hope my explanation makes sense. Any help would be greatly appreciated.
const len = 5000;
let outer = document.querySelector('.outer');
let timer = document.querySelector('.timer');
let timerWidth = timer.offsetWidth;
let offset = len / timerWidth;
let init = 100;
let interval = setInterval(() => {
init = init - offset;
timer.style.width = init + '%';
}, 1000);
setTimeout(() => {
outer.innerHTML = '';
clearInterval(interval);
}, len);
* {
box-sizing:border-box;
}
body {
padding: 100px 10px 10px;
}
.outer {
width: 100%;
border: 1px solid slategray;
padding: 10px;
}
.timer {
width: 100%;
height: 10px;
background: red;
transition: all 1000ms linear;
}
<div class="outer">
<div class="timer"></div>
<p>Some Message Here!</p>
</div>
Two problems with the code:
interval doesn't start as soon as the page is loaded so the CSS is late in transition.
offset was wrong indeed.
Here's how I fixed it:
let toElapse = 3000; // modify as you like
let tick = 1000; //if you modify this don't forget to replicate
//in CSS transition prop
let countDownEl = document.querySelector('#countdown');
let outer = document.querySelector('.outer');
let timer = document.querySelector('.timer');
let init = 100;
// we calculate the offset based on the tick and time to elapse
let offset = init / (toElapse/tick);
countDownEl.innerHTML = init;
setTimeout(()=>{
// we need to start the first CSS transition ASAP so it is not late.
init = init - offset;
timer.style.width = init.toFixed(2) + '%';
},0)
let interval = setInterval(() => {
// the same interval.
countDownEl.innerHTML = init;
init = init - offset;
timer.style.width = init.toFixed(2) + '%';
}, tick);
setTimeout(() => {
// the same clearance timeout
outer.innerHTML = '';
clearInterval(interval);
}, toElapse);
* {
box-sizing:border-box;
}
body {
padding: 100px 10px 10px;
}
.outer {
width: 100%;
border: 1px solid slategray;
padding: 10px;
}
.timer {
width: 100%;
height: 10px;
background: red;
transition: width 1s linear;
}
<div class="outer">
<div class="timer"></div><span id="countdown"></span>
<p>Some Message Here!</p>
</div>
If you use percentage in width you don't need to know the width of your box.
you just need to substract and add on offset to timeout.
const len = 5000;
let outer = document.querySelector('.outer');
let timer = document.querySelector('.timer');
let timerWidth = timer.offsetWidth;
let offset = 100 * 1000 / 5000;
let interval = setInterval(() => {
init = init - 20;
timer.style.width = init + '%';
}, 1000);
setTimeout(() => {
outer.innerHTML = '';
clearInterval(interval);
}, len + 1000);

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

Categories

Resources