Skip to content

Commit f9d76ce

Browse files
authored
Merge pull request yannbf#22 from lohanidamodar/develop
Adds countdown-timer with circular progress bar
2 parents 4aada58 + bfcb828 commit f9d76ce

File tree

5 files changed

+216
-0
lines changed

5 files changed

+216
-0
lines changed

src/app/app.imports.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ import { SlidingDrawer } from '../components/sliding-drawer/sliding-drawer';
101101

102102
// Components
103103
import { Timer } from '../components/countdown-timer/timer';
104+
import { TimerProgress } from '../components/timer-progress/timer-progress';
104105
import { TypingEffect } from '../components/typing-effect/typing-effect';
105106
import { FlashCardComponent } from '../components/flash-card/flash-card';
106107

@@ -217,6 +218,7 @@ export const Providers = [
217218

218219
export const Components = [
219220
FlashCardComponent,
221+
TimerProgress
220222
]
221223

222224
export const Directives = [
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<ion-card *ngIf="timer">
2+
<ion-card-header>
3+
<div class="radial-progress" data-progress="0">
4+
<div class="circle">
5+
<div class="mask full" [style.transform]="transform">
6+
<div class="fill" [style.transform]="transform"></div>
7+
</div>
8+
<div class="mask half">
9+
<div class="fill" [style.transform]="transform"></div>
10+
<div class="fill fix" [style.transform]="fixTransform"></div>
11+
</div>
12+
<div class="shadow"></div>
13+
</div>
14+
<div class="inset">
15+
<div class="percentage">{{timer.displayTime}}</div>
16+
</div>
17+
</div>
18+
<button ion-button *ngIf="!timeInSeconds || timeInSeconds == 0" large block clear class="timer-button">Timer set up incorrectly</button>
19+
</ion-card-header>
20+
<ion-item *ngIf="timeInSeconds && timeInSeconds > 0">
21+
<button ion-button clear class="large" color="danger" (click)="initTimer()" item-left *ngIf="!timer.runTimer && (timer.hasStarted || timer.hasFinished) || timer.hasFinished">
22+
<ion-icon name="refresh"></ion-icon>
23+
Restart
24+
</button>
25+
<button ion-button clear class="large" (click)="pauseTimer()" item-right *ngIf="timer.runTimer && timer.hasStarted && !timer.hasFinished">
26+
<ion-icon name="pause"></ion-icon>
27+
Pause
28+
</button>
29+
<button ion-button clear class="large" (click)="resumeTimer()" item-right *ngIf="!timer.runTimer && timer.hasStarted && !timer.hasFinished">
30+
<ion-icon name="play"></ion-icon>
31+
Resume
32+
</button>
33+
<button ion-button clear class="large" (click)="startTimer()" item-right *ngIf="!timer.hasStarted">
34+
<ion-icon name="play"></ion-icon>
35+
Start
36+
</button>
37+
</ion-item>
38+
</ion-card>
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
.radial-progress {
2+
$circle-size: 150px;
3+
$circle-background: #d6dadc;
4+
$circle-color: tomato;
5+
$inset-size: 120px;
6+
$inset-color: #fbfbfb;
7+
$transition-length: 1s;
8+
$shadow: 6px 6px 10px rgba(0,0,0,0.2);
9+
$percentage-color: tomato;
10+
$percentage-font-size: 22px;
11+
12+
margin: 50px;
13+
width: $circle-size;
14+
height: $circle-size;
15+
background-color: $circle-background;
16+
border-radius: 50%;
17+
18+
.circle {
19+
.fill,
20+
.mask,
21+
.shadow {
22+
width: $circle-size;
23+
height: $circle-size;
24+
position: absolute;
25+
border-radius: 50%;
26+
}
27+
28+
.shadow {
29+
box-shadow: $shadow inset;
30+
}
31+
32+
.fill,
33+
.mask {
34+
-webkit-backface-visibility: hidden;
35+
transition: -webkit-transform $transition-length;
36+
transition: -ms-transform $transition-length;
37+
transition: transform $transition-length;
38+
border-radius: 50%;
39+
}
40+
41+
.mask {
42+
clip: rect(0px, $circle-size, $circle-size, $circle-size/2);
43+
44+
.fill {
45+
clip: rect(0px, $circle-size/2, $circle-size, 0px);
46+
background-color: $circle-color;
47+
}
48+
}
49+
}
50+
51+
.inset {
52+
width: $inset-size;
53+
height: $inset-size;
54+
position: absolute;
55+
margin-left: ($circle-size - $inset-size)/2;
56+
margin-top: ($circle-size - $inset-size)/2;
57+
background-color: $inset-color;
58+
border-radius: 50%;
59+
box-shadow: $shadow;
60+
61+
.percentage {
62+
width: 100%;
63+
position: absolute;
64+
top: ($inset-size - $percentage-font-size) / 2;
65+
line-height: 1;
66+
text-align: center;
67+
font-family: "Lato", "Helvetica Neue", Helvetica, Arial, sans-serif;
68+
color: $percentage-color;
69+
font-weight: 800;
70+
font-size: $percentage-font-size;
71+
}
72+
}
73+
}
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
import { Component, Input } from '@angular/core';
2+
import {DomSanitizer} from "@angular/platform-browser";
3+
4+
export interface CountdownTimer {
5+
seconds: number;
6+
secondsRemaining: number;
7+
runTimer: boolean;
8+
hasStarted: boolean;
9+
hasFinished: boolean;
10+
displayTime: string;
11+
}
12+
13+
@Component({
14+
selector: 'timer-progress',
15+
templateUrl: 'timer-progress.html'
16+
})
17+
export class TimerProgress {
18+
19+
@Input() timeInSeconds: number;
20+
timer: CountdownTimer;
21+
private increment;
22+
private transform;
23+
private percent;
24+
private fixTransform;
25+
constructor(private sanitizer: DomSanitizer) { }
26+
27+
ngOnInit() {
28+
this.initTimer();
29+
}
30+
31+
hasFinished() {
32+
return this.timer.hasFinished;
33+
}
34+
initProgressBar(){
35+
this.percent = 100;
36+
this.increment= 180 / 100;
37+
this.transform=this.sanitizer.bypassSecurityTrustStyle("rotate("+ this.increment * this.percent +"deg)");
38+
this.fixTransform=this.sanitizer.bypassSecurityTrustStyle("rotate("+ this.increment * this.percent +"deg)");
39+
}
40+
41+
initTimer() {
42+
this.initProgressBar();
43+
if (!this.timeInSeconds) { this.timeInSeconds = 0; }
44+
45+
this.timer = <CountdownTimer>{
46+
seconds: this.timeInSeconds,
47+
runTimer: false,
48+
hasStarted: false,
49+
hasFinished: false,
50+
secondsRemaining: this.timeInSeconds
51+
};
52+
53+
this.timer.displayTime = this.getSecondsAsDigitalClock(this.timer.secondsRemaining);
54+
}
55+
56+
startTimer() {
57+
this.timer.hasStarted = true;
58+
this.timer.runTimer = true;
59+
this.timerTick();
60+
}
61+
62+
pauseTimer() {
63+
this.timer.runTimer = false;
64+
}
65+
66+
resumeTimer() {
67+
this.startTimer();
68+
}
69+
70+
timerTick() {
71+
setTimeout(() => {
72+
if (!this.timer.runTimer) { return; }
73+
this.timer.secondsRemaining--;
74+
this.timer.displayTime = this.getSecondsAsDigitalClock(this.timer.secondsRemaining);
75+
this.percent = this.timer.secondsRemaining/this.timer.seconds * 100;
76+
this.increment= 180 / 100;
77+
this.transform=this.sanitizer.bypassSecurityTrustStyle("rotate("+ this.increment * this.percent +"deg)");
78+
this.fixTransform=this.sanitizer.bypassSecurityTrustStyle("rotate("+ this.increment * this.percent +"deg)");
79+
if (this.timer.secondsRemaining > 0) {
80+
this.timerTick();
81+
}
82+
else {
83+
this.timer.hasFinished = true;
84+
}
85+
}, 1000);
86+
}
87+
88+
getSecondsAsDigitalClock(inputSeconds: number) {
89+
var sec_num = parseInt(inputSeconds.toString(), 10); // don't forget the second param
90+
var hours = Math.floor(sec_num / 3600);
91+
var minutes = Math.floor((sec_num - (hours * 3600)) / 60);
92+
var seconds = sec_num - (hours * 3600) - (minutes * 60);
93+
var hoursString = '';
94+
var minutesString = '';
95+
var secondsString = '';
96+
hoursString = (hours < 10) ? "0" + hours : hours.toString();
97+
minutesString = (minutes < 10) ? "0" + minutes : minutes.toString();
98+
secondsString = (seconds < 10) ? "0" + seconds : seconds.toString();
99+
return hoursString + ':' + minutesString + ':' + secondsString;
100+
}
101+
102+
}

src/pages/miscellaneous/countdown/countdown.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,5 @@
77
<ion-content padding>
88
<h2>Countdown Timer</h2>
99
<timer #countdownTimer [timeInSeconds]="2700"></timer>
10+
<timer-progress #countdownTimerProgress [timeInSeconds]="2700"></timer-progress>
1011
</ion-content>

0 commit comments

Comments
 (0)