Advertisement
Today you will learn to create a progress clock using JavaScript, HTML, and CSS. Basically, there are 3 info: Date, Day, Time, and 4 circular
Previously I have shared some clock programs using JavaScript, but this is a little bit different and advanced. Basically, This is a fully functional clock, it will show Date, Month use Day, Time all things. Also, there are some circular progress indicators to show the values of time in hours, minutes, and seconds. It is completely based on pure JavaScript, with no library and plugin used..
Progression Donut bars.. These circle bars are for showing the progression of seconds, minutes, hours, and the whole day. The program is with good UI design and colorful elements. You should place this on your website if you want to show the date and time.
So, I am sharing this pure Javascript, HTML, CSS clock program, it will help you to create a clock and learn JS better. I have HTML to create the structure and added some JS values using inline commands. Used CSS for styling and UI design. And JavaSript for the whole functioning. You can see all the codes for creating and learning to make this type of clock program easily.
JAVASCRIPT PROGRESS CLOCK SOURCE CODE
Before sharing the source code, let’s talk a little bit about the program. First, using HTML I have created some button and span to show values, and some SVG elements to show the progression. Mostly used <svg> command to create all the elements, and later using CSS gave style and js to change values dynamically.
Now using CSS I have placed all the elements in the right place, as you can see on the preview. For color, I used HSL values and added in HTML and CSS. HSL for dynamic color change by changing its percent values. Added Data-* command to store color and hover values. Also used Media query to change theme on dark background.
JavaScript handling here the time, date values, progression bar values, and animation. There using JS command got the date and time values from the system/device and create the whole changing and progressing event. Also used case and return commands for changing month and day names..
Left all other things you will understand after getting the codes, I can’t explain all in writing. For creating this program you have to create 3 files. First file for HTML, second for CSS, and the third file for JavaScript. Follow the steps to creating this program without any error
<!DOCTYPE html>
<html lang="en" >
<head>
<meta charset="UTF-8">
<title>JavaScript Progress Clock | Watu X Team</title>
<link rel="stylesheet" href="./style.css">
</head>
<body>
<div id="clock" class="progClock">
<button class="progClock__time-date" data-group="d" type="button">
<small data-unit="w">Sunday</small><br>
<span data-unit="mo">January</span>
<span data-unit="d">1</span>
</button>
<button class="progClock__time-digit" data-unit="h" data-group="h" type="button">12</button><span class="progClock__time-colon">:</span><button class="progClock__time-digit" data-unit="m" data-group="m" type="button">00</button><span class="progClock__time-colon">:</span><button class="progClock__time-digit" data-unit="s" data-group="s" type="button">00</button>
<span class="progClock__time-ampm" data-unit="ap">AM</span>
<svg class="progClock__rings" width="256" height="256" viewBox="0 0 256 256">
<defs>
<linearGradient id="clock-red" x1="1" y1="0.5" x2="0" y2="0.5">
<stop offset="0%" stop-color="rgb(253,41,20)" />
<stop offset="100%" stop-color="rgb(253,41,20)" />
</linearGradient>
<linearGradient id="clock-yellow" x1="1" y1="0.5" x2="0" y2="0.5">
<stop offset="0%" stop-color="rgb(51,53,65)" />
<stop offset="100%" stop-color="rgb(51,53,65)" />
</linearGradient>
<linearGradient id="clock-blue" x1="1" y1="0.5" x2="0" y2="0.5">
<stop offset="0%" stop-color="rgb(92,184,92)" />
<stop offset="100%" stop-color="rgb(92,184,92)" />
</linearGradient>
<linearGradient id="clock-purple" x1="1" y1="0.5" x2="0" y2="0.5">
<stop offset="0%" stop-color="rgb(249,187,4)" />
<stop offset="100%" stop-color="rgb(249,187,4)" />
</linearGradient>
</defs>
<!-- Days -->
<g data-units="d">
<circle class="progClock__ring" cx="128" cy="128" r="74" fill="none" opacity="0.1" stroke="url(#clock-red)" stroke-width="12" />
<circle class="progClock__ring-fill" data-ring="mo" cx="128" cy="128" r="74" fill="none" stroke="url(#clock-red)" stroke-width="12" stroke-dasharray="465 465" stroke-dashoffset="465" stroke-linecap="round" transform="rotate(-90,128,128)" />
</g>
<!-- Hours -->
<g data-units="h">
<circle class="progClock__ring" cx="128" cy="128" r="90" fill="none" opacity="0.1" stroke="url(#clock-yellow)" stroke-width="12" />
<circle class="progClock__ring-fill" data-ring="d" cx="128" cy="128" r="90" fill="none" stroke="url(#clock-yellow)" stroke-width="12" stroke-dasharray="565.5 565.5" stroke-dashoffset="565.5" stroke-linecap="round" transform="rotate(-90,128,128)" />
</g>
<!-- Minutes -->
<g data-units="m">
<circle class="progClock__ring" cx="128" cy="128" r="106" fill="none" opacity="0.1" stroke="url(#clock-blue)" stroke-width="12" />
<circle class="progClock__ring-fill" data-ring="h" cx="128" cy="128" r="106" fill="none" stroke="url(#clock-blue)" stroke-width="12" stroke-dasharray="666 666" stroke-dashoffset="666" stroke-linecap="round" transform="rotate(-90,128,128)" />
</g>
<!-- Seconds -->
<g data-units="s">
<circle class="progClock__ring" cx="128" cy="128" r="122" fill="none" opacity="0.1" stroke="url(#clock-purple)" stroke-width="12" />
<circle class="progClock__ring-fill" data-ring="m" cx="128" cy="128" r="122" fill="none" stroke="url(#clock-purple)" stroke-width="12" stroke-dasharray="766.5 766.5" stroke-dashoffset="766.5" stroke-linecap="round" transform="rotate(-90,128,128)" />
</g>
</svg>
</div>
<script src="./function.js"></script>
</body>
</html
* {border: 0;
box-sizing: border-box;
margin: 0;
padding: 0;
}
:root {--hue: 223;
--bg: hsl(var(--hue),10%,90%);
--fg: hsl(var(--hue),10%,10%);
font-size: calc(16px + (24 - 16) * (100vw - 320px) / (1280 - 320));
}
body, button {color: var(--fg);
font: 1em/1.5 "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
}
body {background-color: var(--bg);
height: 100vh;
display: grid;
place-items: center;
}
.progClock {display: grid;
justify-content: center;
align-content: center;
position: relative;
text-align: center;
width: 16em;
height: 16em;
}
.progClock__time-date,
.progClock__time-digit,
.progClock__time-colon,
.progClock__time-ampm {transition: color 0.2s linear;
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
}
.progClock__time-date,
.progClock__time-digit {background: transparent;
}
.progClock__time-date,
.progClock__time-ampm {grid-column: 1 / 6;
}
.progClock__time-date {font-size: 0.75em;
line-height: 1.33;
}
.progClock__time-digit,
.progClock__time-colon {font-size: 2em;
font-weight: 400;
grid-row: 2;
}
.progClock__time-colon {line-height: 1.275;
}
.progClock__time-ampm {cursor: default;
grid-row: 3;
}
.progClock__rings {display: block;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: -1;
}
.progClock__ring {opacity: 0.1;
}
.progClock__ring-fill {transition:
opacity 0s 0.3s linear,
stroke-dashoffset 0.3s ease-in-out;
}
.progClock__ring-fill--360 {opacity: 0;
stroke-dashoffset: 0;
transition-duration: 0.3s;
}
[data-group]:focus {outline: transparent;
}
[data-units] {transition: opacity 0.2s linear;
}
[data-group="d"]:focus,
[data-group="d"]:hover {color: rgb(253,41,20);
}
[data-group="h"]:focus,
[data-group="h"]:hover {color: rgb(51,53,65);
}
[data-group="m"]:focus,
[data-group="m"]:hover {color: rgb(92,184,92);
}
[data-group="s"]:focus,
[data-group="s"]:hover {color: rgb(249,187,4);
}
[data-group]:focus ~ .progClock__rings [data-units],
[data-group]:hover ~ .progClock__rings [data-units] {opacity: 0.2;
}
[data-group="d"]:focus ~ .progClock__rings [data-units="d"],
[data-group="d"]:hover ~ .progClock__rings [data-units="d"],
[data-group="h"]:focus ~ .progClock__rings [data-units="h"],
[data-group="h"]:hover ~ .progClock__rings [data-units="h"],
[data-group="m"]:focus ~ .progClock__rings [data-units="m"],
[data-group="m"]:hover ~ .progClock__rings [data-units="m"],
[data-group="s"]:focus ~ .progClock__rings [data-units="s"],
[data-group="s"]:hover ~ .progClock__rings [data-units="s"] {opacity: 1;
}
/* Dark theme */
@media (prefers-color-scheme: dark) { :root {--bg: hsl(var(--hue),10%,10%);
--fg: hsl(var(--hue),10%,90%);
}
.progClock__ring {opacity: 0.2;
}
}
window.addEventListener("DOMContentLoaded",() => { const clock = new ProgClock("#clock");});
class ProgClock { constructor(qs) {this.el = document.querySelector(qs);
this.time = 0;
this.updateTimeout = null;
this.ringTimeouts = [];
this.update();
}
getDayOfWeek(day) { switch (day) {case 1:
return "Monday";
case 2:
return "Tuesday";
case 3:
return "Wednesday";
case 4:
return "Thursday";
case 5:
return "Friday";
case 6:
return "Saturday";
default:
return "Sunday";
}
}
getMonthInfo(mo,yr) { switch (mo) {case 1:
return { name: "February", days: yr % 4 === 0 ? 29 : 28 };case 2:
return { name: "March", days: 31 };case 3:
return { name: "April", days: 30 };case 4:
return { name: "May", days: 31 };case 5:
return { name: "June", days: 30 };case 6:
return { name: "July", days: 31 };case 7:
return { name: "August", days: 31 };case 8:
return { name: "September", days: 30 };case 9:
return { name: "October", days: 31 };case 10:
return { name: "November", days: 30 };case 11:
return { name: "December", days: 31 };default:
return { name: "January", days: 31 };}
}
update() {this.time = new Date();
if (this.el) {// date and time
const dayOfWeek = this.time.getDay();
const year = this.time.getFullYear();
const month = this.time.getMonth();
const day = this.time.getDate();
const hr = this.time.getHours();
const min = this.time.getMinutes();
const sec = this.time.getSeconds();
const dayOfWeekName = this.getDayOfWeek(dayOfWeek);
const monthInfo = this.getMonthInfo(month,year);
const m_progress = sec / 60;
const h_progress = (min + m_progress) / 60;
const d_progress = (hr + h_progress) / 24;
const mo_progress = ((day - 1) + d_progress) / monthInfo.days;
const units = [
{label: "w",
value: dayOfWeekName
},
{label: "mo",
value: monthInfo.name,
progress: mo_progress
},
{label: "d",
value: day,
progress: d_progress
},
{label: "h",
value: hr > 12 ? hr - 12 : hr,
progress: h_progress
},
{label: "m",
value: min < 10 ? "0" + min : min,
progress: m_progress
},
{label: "s",
value: sec < 10 ? "0" + sec : sec
},
{label: "ap",
value: hr > 12 ? "PM" : "AM"
}
];
// flush out the timeouts
this.ringTimeouts.forEach(t => {clearTimeout(t);
});
this.ringTimeouts = [];
// update the display
units.forEach(u => {// rings
const ring = this.el.querySelector(`[data-ring="${u.label}"]`); if (ring) { const strokeDashArray = ring.getAttribute("stroke-dasharray");const fill360 = "progClock__ring-fill--360";
if (strokeDashArray) {// calculate the stroke
const circumference = +strokeDashArray.split(" ")[0];const strokeDashOffsetclockt = 1 - u.progress;
ring.setAttribute(
"stroke-dashoffset",
strokeDashOffsetclockt * circumference
);
// add the fade-out transition, then remove it
if (strokeDashOffsetclockt === 1) {ring.classList.add(fill360);
this.ringTimeouts.push(
setTimeout(() => {ring.classList.remove(fill360);
}, 600)
);
}
}
}
// digits
const unit = this.el.querySelector(`[data-unit="${u.label}"]`);if (unit)
unit.innerText = u.value;
});
}
clearTimeout(this.updateTimeout);
this.updateTimeout = setTimeout(this.update.bind(this),1e3);
}
}
Now you have successfully created JavaScript Progress Clock with good UI design and animation.
