I am creating my function where I can manage pause and resume and reset the countdown.
I have read various threads but I don't know how I merge that code with my own function.
basically I am doing countdown, my default countdown is 15sec once I click start button that counter will start 15,14,13...
in this between If I click pause the counter will pause and same will resume on click resume and finally the time will reset as 15 sec on click reset
Please help, I create my own function with wonderful UI, how I add this above, pause, resume, reset function in my code.
// Credit: Mateusz Rybczonec
const FULL_DASH_ARRAY = 283;
const WARNING_THRESHOLD = 10;
const ALERT_THRESHOLD = 5;
const COLOR_CODES = {
info: {
color: "green"
},
warning: {
color: "orange",
threshold: WARNING_THRESHOLD
},
alert: {
color: "red",
threshold: ALERT_THRESHOLD
}
};
const TIME_LIMIT = 15;
let timePassed = 0;
let timeLeft = TIME_LIMIT;
let timerInterval = null;
let remainingPathColor = COLOR_CODES.info.color;
document.getElementById("app").innerHTML = `
<div >
<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<g >
<circle cx="50" cy="50" r="45"></circle>
<path
id="base-timer-path-remaining"
stroke-dasharray="283"
d="
M 50, 50
m -45, 0
a 45,45 0 1,0 90,0
a 45,45 0 1,0 -90,0
"
></path>
</g>
</svg>
<span id="base-timer-label" >${formatTime(
timeLeft
)}</span>
</div>
`;
function onTimesUp() {
clearInterval(timerInterval);
}
function startTimer() {
timerInterval = setInterval(() => {
timePassed = timePassed = 1;
timeLeft = TIME_LIMIT - timePassed;
document.getElementById("base-timer-label").innerHTML = formatTime(
timeLeft
);
setCircleDasharray();
setRemainingPathColor(timeLeft);
if (timeLeft === 0) {
onTimesUp();
alert("Time Up");
}
}, 1000);
}
function formatTime(time) {
const minutes = Math.floor(time / 60);
let seconds = time % 60;
if (seconds < 10) {
seconds = `0${seconds}`;
}
return `${minutes}:${seconds}`;
}
function setRemainingPathColor(timeLeft) {
const { alert, warning, info } = COLOR_CODES;
if (timeLeft <= alert.threshold) {
document
.getElementById("base-timer-path-remaining")
.classList.remove(warning.color);
document
.getElementById("base-timer-path-remaining")
.classList.add(alert.color);
} else if (timeLeft <= warning.threshold) {
document
.getElementById("base-timer-path-remaining")
.classList.remove(info.color);
document
.getElementById("base-timer-path-remaining")
.classList.add(warning.color);
}
}
function calculateTimeFraction() {
const rawTimeFraction = timeLeft / TIME_LIMIT;
return rawTimeFraction - (1 / TIME_LIMIT) * (1 - rawTimeFraction);
}
function setCircleDasharray() {
const circleDasharray = `${(
calculateTimeFraction() * FULL_DASH_ARRAY
).toFixed(0)} 283`;
document
.getElementById("base-timer-path-remaining")
.setAttribute("stroke-dasharray", circleDasharray);
}
function starTimer(){
startTimer();
}
function pauseTimer(){
//pause timer
}
function resumeTimer(){
//resume timer
}
function resetTimer(){
//reset time to 15sec by default;
}
body {
font-family: sans-serif;
display: grid;
height: 100vh;
place-items: center;
}
.base-timer {
position: relative;
width: 300px;
height: 300px;
}
.base-timer__svg {
transform: scaleX(-1);
}
.base-timer__circle {
fill: none;
stroke: none;
}
.base-timer__path-elapsed {
stroke-width: 7px;
stroke: grey;
}
.base-timer__path-remaining {
stroke-width: 7px;
stroke-linecap: round;
transform: rotate(90deg);
transform-origin: center;
transition: 1s linear all;
fill-rule: nonzero;
stroke: currentColor;
}
.base-timer__path-remaining.green {
color: rgb(65, 184, 131);
}
.base-timer__path-remaining.orange {
color: orange;
}
.base-timer__path-remaining.red {
color: red;
}
.base-timer__label {
position: absolute;
width: 300px;
height: 300px;
top: 0;
display: flex;
align-items: center;
justify-content: center;
font-size: 48px;
}
<div id="app"></div>
<input type="button" onclick="starTimer()" value="Start"/>
<input type="button" onclick="pauseTimer()" value="Pause"/>
<input type="button" onclick="resumeTimer()" value="Resume"/>
<input type="button" onclick="resetTimer()" value="Reset"/>
CodePudding user response:
function onTimesUp() {
clearInterval(timerInterval);
timerInterval = undefined;
}
All you have to do is clear the interval and save the state for pausing the timer, and on resume let the start value be the previous stopped value.
In case of resume, it's same as the start function you've written.
For resetting, clear the timer and just set everything to your initial value.
function starTimer() {
if (!timerInterval) startTimer();
}
function pauseTimer() {
onTimesUp();
}
function resumeTimer() {
if (!timerInterval) startTimer();
}
function resetTimer() {
if (timerInterval) {
onTimesUp();
}
timePassed = 0;
timeLeft = TIME_LIMIT;
timerInterval = null;
document.getElementById('base-timer-label').innerHTML = formatTime(timeLeft);
setCircleDasharray();
setRemainingPathColor(timeLeft);
}
Here is a link to working codepen
CodePudding user response:
To pause the timer, you need to clear the interval.
To resume, it is the same as starting.
To reset, you need to wrap the document.getElementById("app").innerHTML =
with a named function, so you can call it again. See init
below. Additionnally, you need to restore the initial variables.
// Credit: Mateusz Rybczonec
const FULL_DASH_ARRAY = 283;
const WARNING_THRESHOLD = 10;
const ALERT_THRESHOLD = 5;
const COLOR_CODES = {
info: {
color: "green"
},
warning: {
color: "orange",
threshold: WARNING_THRESHOLD
},
alert: {
color: "red",
threshold: ALERT_THRESHOLD
}
};
let TIME_LIMIT = 15;
let timePassed = 0;
let timeLeft = TIME_LIMIT;
let timerInterval = null;
let remainingPathColor = COLOR_CODES.info.color;
function init() {
document.getElementById("app").innerHTML = `
<div >
<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<g >
<circle cx="50" cy="50" r="45"></circle>
<path
id="base-timer-path-remaining"
stroke-dasharray="283"
d="
M 50, 50
m -45, 0
a 45,45 0 1,0 90,0
a 45,45 0 1,0 -90,0
"
></path>
</g>
</svg>
<span id="base-timer-label" >${formatTime(
timeLeft
)}</span>
</div>
`;
}
function onTimesUp() {
clearInterval(timerInterval);
resetTimer();
}
function startTimer() {
timerInterval = setInterval(() => {
timePassed = timePassed = 1;
timeLeft = TIME_LIMIT - timePassed;
document.getElementById("base-timer-label").innerHTML = formatTime(
timeLeft
);
setCircleDasharray();
setRemainingPathColor(timeLeft);
if (timeLeft === 0) {
onTimesUp();
alert("Time Up");
}
}, 1000);
}
function formatTime(time) {
const minutes = Math.floor(time / 60);
let seconds = time % 60;
if (seconds < 10) {
seconds = `0${seconds}`;
}
return `${minutes}:${seconds}`;
}
function setRemainingPathColor(timeLeft) {
const {
alert,
warning,
info
} = COLOR_CODES;
if (timeLeft <= alert.threshold) {
document
.getElementById("base-timer-path-remaining")
.classList.remove(warning.color);
document
.getElementById("base-timer-path-remaining")
.classList.add(alert.color);
} else if (timeLeft <= warning.threshold) {
document
.getElementById("base-timer-path-remaining")
.classList.remove(info.color);
document
.getElementById("base-timer-path-remaining")
.classList.add(warning.color);
}
}
function calculateTimeFraction() {
const rawTimeFraction = timeLeft / TIME_LIMIT;
return rawTimeFraction - (1 / TIME_LIMIT) * (1 - rawTimeFraction);
}
function setCircleDasharray() {
const circleDasharray = `${(
calculateTimeFraction() * FULL_DASH_ARRAY
).toFixed(0)} 283`;
document
.getElementById("base-timer-path-remaining")
.setAttribute("stroke-dasharray", circleDasharray);
}
function starTimer() {
startTimer();
}
function pauseTimer() {
//pause timer
clearInterval(timerInterval);
}
function resumeTimer() {
//resume timer
startTimer();
}
function resetTimer() {
TIME_LIMIT = 15;
timePassed = 0;
timeLeft = TIME_LIMIT;
init();
}
// On page load
init();
body {
font-family: sans-serif;
display: grid;
height: 100vh;
place-items: center;
}
.base-timer {
position: relative;
width: 300px;
height: 300px;
}
.base-timer__svg {
transform: scaleX(-1);
}
.base-timer__circle {
fill: none;
stroke: none;
}
.base-timer__path-elapsed {
stroke-width: 7px;
stroke: grey;
}
.base-timer__path-remaining {
stroke-width: 7px;
stroke-linecap: round;
transform: rotate(90deg);
transform-origin: center;
transition: 1s linear all;
fill-rule: nonzero;
stroke: currentColor;
}
.base-timer__path-remaining.green {
color: rgb(65, 184, 131);
}
.base-timer__path-remaining.orange {
color: orange;
}
.base-timer__path-remaining.red {
color: red;
}
.base-timer__label {
position: absolute;
width: 300px;
height: 300px;
top: 0;
display: flex;
align-items: center;
justify-content: center;
font-size: 48px;
}
<div id="app"></div>
<input type="button" onclick="starTimer()" value="Start" />
<input type="button" onclick="pauseTimer()" value="Pause" />
<input type="button" onclick="resumeTimer()" value="Resume" />
<input type="button" onclick="resetTimer()" value="Reset" />
Your next task will be to reuse the buttons. So after on click on "Start", the button will turn to "Pause". Once paused, the button will be "Resume"... And will be "Start" after a "reset" click (which has to be another button).