I'm using angular 5 and I have a mat-progress-bar. I also have a timer with 2 * 60 value that means 2 minutes. I want to decrease the value of progress-bar each second and after 2 minutes the value of bar become 0! how can I do it?
You can use the following code as an example.
The component class will look like this:
export class AppComponent {
progressbarValue = 100;
curSec: number = 0;
startTimer(seconds: number) {
const time = seconds;
const timer$ = interval(1000);
const sub = timer$.subscribe((sec) => {
this.progressbarValue = 100 - sec * 100 / seconds;
this.curSec = sec;
if (this.curSec === seconds) {
sub.unsubscribe();
}
});
}
}
In the template you've the progress bar that uses the value of progressbarValue:
<mat-progress-bar mode="determinate" [value]="progressbarValue"></mat-progress-bar>
And a button to start the startTimer method:
<button mat-raised-button (click)="startTimer(60)">Start timer</button>
You can find a running code example here:
https://stackblitz.com/edit/angular-material-progress-bar-decrease
Related
const secondsInterval = () => {
const date = getNow();
if (dayjs(date).minute() % 5 !== 0 && dayjs(date).second() !== 0) {
console.log("return...");
return;
}
console.log("checking...");
...
};
// Check every second, if we're at the 5-minute interval check.
setInterval(secondsInterval, 1000);
This seems to get stuck. It's "checking" on every second of each 5 minute mark. What am I doing wrong? Thanks in advance.
Goal: To "check" every minute and 00 seconds: :00:00, :05:00, :10:00, , :15:00, etc Thanks again.
You should find out what's the time to your next rounded 5 min. like this:
const FIVE_MIN = 1000 * 60 * 5;
function waitAndDoSomething() {
const msToNextRounded5Min = FIVE_MIN - (Date.now() % FIVE_MIN);
console.log(`Waiting ${msToNextRounded5Min}ms. to next rounded 5Min.`);
setTimeout(() => {
console.log('It is now rounded 5 min');
waitAndDoSomething();
}, msToNextRounded5Min);
}
waitAndDoSomething();
If all you care about is executing some code every 5 mins, then don't have it execute every second needlessly, only to return out. Just have it run every 5 mins (300000 MS) and have it do what you need to do and remove all the checking for 5 minute mark code out its unnecessary.
const secondsInterval = () => {
// -------------------- Remove ----------------
//const date = getNow();
//if (dayjs(date).minute() % 5 !== 0 && dayjs(date).second() !== 0) {
// console.log("return...");
// return;
//}
// -------------------- Remove ----------------
console.log("checking...");
...
};
// Check every 5 mins
setInterval(secondsInterval, 300000);
Your logic for the if is screwy. Here I reversed it so the if takes care of "do the thing" and the else returns.
const secondsInterval = () => {
const date = dayjs(new Date());
if (dayjs(date).minute() % 5 == 0 && dayjs(date).second() == 0) {
console.log("checking...");
} else {
console.log("returning...");
return;
}
//...
};
// Check every second, if we're at the 5-minute interval check.
setInterval(secondsInterval, 1000);
<script src="https://unpkg.com/dayjs#1.8.21/dayjs.min.js"></script>
I have setInterval function where a timer will be running.
Issue:
For example if we have 2 menus, one is home and 2nd is timer(where our timer is running), if I stay in timer page, SetInterval timer is working fine, but if I visit home page, the timer is starting where I left the page.
Requirement:
Even if I visit the Home page, the timer should not stop, it should go continuesly.
Code:
const pad = (val) => {
return val > 9 ? val : '0' + val;
};
startTimer = () => {
let timer = setInterval(function() {
document.getElementById(`seconds-${accountId}`)
? (document.getElementById(`seconds-${accountId}`).innerHTML = pad(++sec % 60))
: null;
document.getElementById(`minutes-${accountId}`)
? (document.getElementById(`minutes-${accountId}`).innerHTML = pad(parseInt(sec / 60, 10)))
: null;
}, 1000);
}
componentDidUpdate(){
this.startTimer();
}
This question already has answers here:
How can I parse a string with a comma thousand separator to a number?
(17 answers)
Closed 1 year ago.
I'm attempting to add a count up animation using javascript on my page. I've been able to get a working solution but the counter stops working if the number has a comma for example : 53,210 the counter will display 53. How can I be able to have the counter animation with numbers that have a comma?
Here is a code snippet :
window.onload = function() {
runAnimations();
};
// How long you want the animation to take, in ms
const animationDuration = 2000;
// Calculate how long each ‘frame’ should last if we want to update the animation 60 times per second
const frameDuration = 1000 / 60;
// Use that to calculate how many frames we need to complete the animation
const totalFrames = Math.round( animationDuration / frameDuration );
// An ease-out function that slows the count as it progresses
const easeOutQuad = t => t * ( 2 - t );
// The animation function, which takes an Element
const animateCountUp = el => {
let frame = 0;
const countTo = parseInt( el.innerHTML, 10 );
// Start the animation running 60 times per second
const counter = setInterval( () => {
frame++;
// Calculate our progress as a value between 0 and 1
// Pass that value to our easing function to get our
// progress on a curve
const progress = easeOutQuad( frame / totalFrames );
// Use the progress value to calculate the current count
const currentCount = Math.round( countTo * progress );
// If the current count has changed, update the element
if ( parseInt( el.innerHTML, 10 ) !== currentCount ) {
el.innerHTML = currentCount;
}
// If we’ve reached our last frame, stop the animation
if ( frame === totalFrames ) {
clearInterval( counter );
}
}, frameDuration );
};
// Run the animation on all elements with a class of ‘countup’
const runAnimations = () => {
const countupEls = document.querySelectorAll( '.countup' );
countupEls.forEach( animateCountUp );
};
<ul>
<li><span class="countup">45</span></li>
<li><span class="countup">110</span></li>
<li><span class="countup">53,210</span></li>
</ul>
I am expecting the HTML to display the full number of 53,210 with the count up animation. Not stop at the number before the comma.
You could try to remove the , from the input before proceeding with the rest of the code. Something along the lines of:
// get input as string from HTML
const formattedNumber = el.innerHTML;
// Format as number input (removes commas)
const inputNumber = formattedNumber.replace(/\,/g,'');
const countTo = new Number(inputNumber);
See demo
window.onload = function() {
runAnimations();
};
// How long you want the animation to take, in ms
const animationDuration = 2000;
// Calculate how long each ‘frame’ should last if we want to update the animation 60 times per second
const frameDuration = 1000 / 60;
// Use that to calculate how many frames we need to complete the animation
const totalFrames = Math.round(animationDuration / frameDuration);
// An ease-out function that slows the count as it progresses
const easeOutQuad = t => t * (2 - t);
// The animation function, which takes an Element
const animateCountUp = el => {
let frame = 0;
// get input as string from HTML
const formattedNumber = el.innerHTML;
// Format as number input (removes commas)
const inputNumber = formattedNumber.replace(/\,/g,'');
const countTo = new Number(inputNumber);
// Start the animation running 60 times per second
const counter = setInterval(() => {
frame++;
// Calculate our progress as a value between 0 and 1
// Pass that value to our easing function to get our
// progress on a curve
const progress = easeOutQuad(frame / totalFrames);
// Use the progress value to calculate the current count
const currentCount = Math.round(countTo * progress);
// If the current count has changed, update the element
if (parseInt(el.innerHTML, 10) !== currentCount) {
el.innerHTML = currentCount;
}
// If we’ve reached our last frame, stop the animation
if (frame === totalFrames) {
clearInterval(counter);
}
}, frameDuration);
};
// Run the animation on all elements with a class of ‘countup’
const runAnimations = () => {
const countupEls = document.querySelectorAll('.countup');
countupEls.forEach(animateCountUp);
};
<ul>
<li><span class="countup">45</span></li>
<li><span class="countup">110</span></li>
<li><span class="countup">53,210</span></li>
</ul>
Need to parseInt with comma. :
parseInt(el.innerHTML.replace(/,/g, ''), 10)
Also display with comma need to following line change.
el.innerHTML = currentCount.toString().replace(/\B(?<!\.\d*)(?=(\d{3})+(?!\d))/g, ",");
Check following code.
window.onload = function() {
runAnimations();
};
// How long you want the animation to take, in ms
const animationDuration = 2000;
// Calculate how long each ‘frame’ should last if we want to update the animation 60 times per second
const frameDuration = 1000 / 60;
// Use that to calculate how many frames we need to complete the animation
const totalFrames = Math.round( animationDuration / frameDuration );
// An ease-out function that slows the count as it progresses
const easeOutQuad = t => t * ( 2 - t );
// The animation function, which takes an Element
const animateCountUp = el => {
let frame = 0;
const countTo = parseInt(el.innerHTML.replace(/,/g, ''), 10);
// Start the animation running 60 times per second
const counter = setInterval( () => {
frame++;
// Calculate our progress as a value between 0 and 1
// Pass that value to our easing function to get our
// progress on a curve
const progress = easeOutQuad( frame / totalFrames );
// Use the progress value to calculate the current count
const currentCount = Math.round( countTo * progress );
// If the current count has changed, update the element
if ( parseInt( el.innerHTML, 10 ) !== currentCount ) {
el.innerHTML = currentCount.toString().replace(/\B(?<!\.\d*)(?=(\d{3})+(?!\d))/g, ",");
}
// If we’ve reached our last frame, stop the animation
if ( frame === totalFrames ) {
clearInterval( counter );
}
}, frameDuration );
};
// Run the animation on all elements with a class of ‘countup’
const runAnimations = () => {
const countupEls = document.querySelectorAll( '.countup' );
countupEls.forEach( animateCountUp );
};
<ul>
<li><span class="countup">45</span></li>
<li><span class="countup">110</span></li>
<li><span class="countup">53,210</span></li>
</ul>
Add .toLocaleString('en-US'); to your const currentCount so that animation contain a comma according to US number system .
See this for .toLocaleString('en-US');
If you want to use comma in the class also than use .replace(',', '') to remove comma when function values are entered . Also if values contain more than 1 comma than use global attribute in like this .replace(/\,/g, '')
See this for Regular expressions
window.onload = function() {
runAnimations();
};
// How long you want the animation to take, in ms
const animationDuration = 2000;
// Calculate how long each ‘frame’ should last if we want to update the animation 60 times per second
const frameDuration = 1000 / 60;
// Use that to calculate how many frames we need to complete the animation
const totalFrames = Math.round(animationDuration / frameDuration);
// An ease-out function that slows the count as it progresses
const easeOutQuad = t => t * (2 - t);
// The animation function, which takes an Element
const animateCountUp = el => {
let frame = 0;
const countTo = parseInt(el.innerHTML.replace(/\,/g, ''), 10);
// Start the animation running 60 times per second
const counter = setInterval(() => {
frame++;
// Calculate our progress as a value between 0 and 1
// Pass that value to our easing function to get our
// progress on a curve
const progress = easeOutQuad(frame / totalFrames);
// Use the progress value to calculate the current count
const currentCount = Math.round(countTo * progress).toLocaleString('en-US');;
// If the current count has changed, update the element
if (parseInt(el.innerHTML, 10) !== currentCount) {
el.innerHTML = currentCount;
}
// If we’ve reached our last frame, stop the animation
if (frame === totalFrames) {
clearInterval(counter);
}
}, frameDuration);
};
// Run the animation on all elements with a class of ‘countup’
const runAnimations = () => {
const countupEls = document.querySelectorAll('.countup');
countupEls.forEach(animateCountUp);
};
<ul>
<li><span class="countup">45</span></li>
<li><span class="countup">110</span></li>
<li><span class="countup">53,210</span></li>
<li><span class="countup">5,3,2,1,0</span></li>
<li><span class="countup">53,215480</span></li>
</ul>
I'm trying to create a Pomodoro timer using Hooks and I have set up the basic functionality using useState and useEffect. I have a 25-minute timer that counts down and every time it gets to 0, it starts a break timer of 5 minutes. What I'm trying to figure out now is how to create an iteration that says "every 4 times the timer hits 0, change the break time from 5 minutes to 15 minutes and then, go back to 5 minutes." I thought of creating sessions that way it will say 4th session and then it will go back to 1. but I'm really not sure what to do here.
import React, { useState, useEffect } from "react";
function Pomodoro() {
const [minutes, setMinutes] = useState(25);
const [seconds, setSeconds] = useState(0);
const [displayMessage, setDisplayMessage] = useState(false);
const [session, setSession] = useState(1);
useEffect(() => {
let interval = setInterval(() => {
clearInterval(interval);
if (seconds === 0 && minutes !== 0) {
setSeconds(59);
setMinutes(minutes -1);
} else if (seconds === 0 && minutes === 0) {
let minutes = displayMessage ? 24 : 4;
let seconds = 59;
setSeconds(seconds);
setMinutes(minutes);
setDisplayMessage(!displayMessage);
} else {
setSeconds(seconds -1);
}
}, 1000);
}, [seconds]);
const timerMinutes = minutes < 10 ? `0${minutes}` : minutes;
const timerSeconds = seconds < 10 ? `0${seconds}` : seconds;
return (
<div className="pomodoro">
<div>Session:{session} </div>
<div className="message">
{displayMessage && <div>Break time! New Session starts in:</div>}
</div>
<div className="timer">
{timerMinutes}:{timerSeconds}
</div>
</div>
);
}
export default Pomodoro;
Your approach using a counter to keep track of the completed sessions seems to make sense. If you want to use a different amount of break time for every fourth iteration, you could use the remainder operator as below:
let breakTime = (session % 4) === 0 ? 14 : 0;
Then, you just need to make sure you are incrementing your session variable by one each time you complete a session. This also means you only want to increase it when you are not "on break" so you must make sure to guard against that.
Updating the answer with the full code that I tested to be working. Note the following changes I made:
I am only keeping track of the timer in seconds - this reduces the complexity inside useEffect and you can convert from seconds to other formats (try using the remainder operator again)
Moved the period lengths to constants
Renamed the variable displayMessage to isOnBreak for clarity
import React, { useState, useEffect } from "react";
// Define the period lengths (in seconds)
const workTime = 2;
const shortBreakTime = 4;
const longBreakTime = 6;
function Pomodoro() {
const [seconds, setSeconds] = useState(workTime);
// Renamed this variable for clarity to indicate it is a boolean
const [isOnBreak, setIsOnBreak] = useState(false);
const [session, setSession] = useState(1);
useEffect(() => {
let interval = setInterval(() => {
clearInterval(interval);
if (seconds === 0) {
let breakTime = (session % 4 === 0) ? longBreakTime : shortBreakTime;
let seconds = !isOnBreak ? breakTime : workTime;
// A session is complete when work and break is done,
// so only increment when finishing a break
if (isOnBreak) setSession(session+1);
setSeconds(seconds);
setIsOnBreak(!isOnBreak);
} else {
setSeconds(seconds -1);
}
}, 1000);
}, [seconds]);
// Here you could convert from seconds to minutes and seconds or whatever time format you prefer
const timerSeconds = seconds < 10 ? `0${seconds}` : seconds;
return (
<div className="pomodoro">
<div>Session:{session} </div>
<div className="message">
{isOnBreak && <div>Break time! New Session starts in:</div>}
</div>
<div className="timer">
{timerSeconds}
</div>
</div>
);
}
I have this variables changing constantly, from 0 to 100 this coming from an exernal SDK like this for example:
window.addEventListener({
variable = 0;
})
Now when this variable change and goes to another value it's too sharp for me and I want to make this exponential, for example,
not 0 => 100 directly, but I want to sample the value of variable every x millisecond e make a smooth transition between the two value with the intermediate value
example: 0 => 20 => 40 => 60 => 80 => 100
how can I do?
This should do the trick:
var animationDuration = 500; //in miliseconds
var startValue = 0;
var endValue = 100;
function animateNextFrame(currentTime) {
if (!startTime) startTime = currentTime;
var elapsedTime = currentTime - startTime;
if (elapsedTime < animationDuration) {
currentValue = Math.floor((elapsedTime / animationDuration) * (endValue - startValue));
//set your field value to currentValue here with something like document.getElemenById...
//call the next animation frame
window.requestAnimationFrame(animateNextFrame);
} else {
//set your field value to endValue here with something like document.getElemenById...
}
}
//trigger the number animation
window.requestAnimationFrame(animateNextFrame);