├── index.html
├── script.js
└── style.css
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Theme Clock
8 |
9 |
10 |
11 |
12 |
13 |
14 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/script.js:
--------------------------------------------------------------------------------
1 | const hourEl = document.querySelector('.hour')
2 | const minuteEl = document.querySelector('.minute')
3 | const secondEl = document.querySelector('.second')
4 | const timeEl = document.querySelector('.time')
5 | const dateEl = document.querySelector('.date')
6 | const toggle = document.querySelector('.toggle')
7 |
8 | const days = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
9 | const months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
10 |
11 | toggle.addEventListener('click', (e) => {
12 | const html = document.querySelector('html')
13 | if (html.classList.contains('dark')) {
14 | html.classList.remove('dark')
15 | e.target.innerHTML = 'Dark mode'
16 | } else {
17 | html.classList.add('dark')
18 | e.target.innerHTML = 'Light mode'
19 | }
20 | })
21 |
22 | function setTime() {
23 | const time = new Date();
24 | const month = time.getMonth()
25 | const day = time.getDay()
26 | const date = time.getDate()
27 | const hours = time.getHours()
28 | const hoursForClock = hours >= 13 ? hours % 12 : hours;
29 | const minutes = time.getMinutes()
30 | const seconds = time.getSeconds()
31 | const ampm = hours >= 12 ? 'PM' : 'AM'
32 |
33 | hourEl.style.transform = `translate(-50%, -100%) rotate(${scale(hoursForClock, 0, 12, 0, 360)}deg)`
34 | minuteEl.style.transform = `translate(-50%, -100%) rotate(${scale(minutes, 0, 60, 0, 360)}deg)`
35 | secondEl.style.transform = `translate(-50%, -100%) rotate(${scale(seconds, 0, 60, 0, 360)}deg)`
36 |
37 | timeEl.innerHTML = `${hoursForClock}:${minutes < 10 ? `0${minutes}` : minutes} ${ampm}`
38 | dateEl.innerHTML = `${days[day]}, ${months[month]} ${date}`
39 | }
40 |
41 | // StackOverflow https://stackoverflow.com/questions/10756313/javascript-jquery-map-a-range-of-numbers-to-another-range-of-numbers
42 | const scale = (num, in_min, in_max, out_min, out_max) => {
43 | return (num - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
44 | }
45 |
46 | setTime()
47 |
48 | setInterval(setTime, 1000)
49 |
--------------------------------------------------------------------------------
/style.css:
--------------------------------------------------------------------------------
1 | @import url('https://fonts.googleapis.com/css?family=Heebo:300&display=swap');
2 |
3 | * {
4 | box-sizing: border-box;
5 | }
6 |
7 | :root {
8 | --primary-color: #000;
9 | --secondary-color: #fff;
10 | }
11 |
12 | html {
13 | transition: all 0.5s ease-in;
14 | }
15 |
16 | html.dark {
17 | --primary-color: #fff;
18 | --secondary-color: #333;
19 | }
20 |
21 | html.dark {
22 | background-color: #111;
23 | color: var(--primary-color);
24 | }
25 |
26 | body {
27 | font-family: 'Heebo', sans-serif;
28 | display: flex;
29 | align-items: center;
30 | justify-content: center;
31 | height: 100vh;
32 | overflow: hidden;
33 | margin: 0;
34 | }
35 |
36 | .toggle {
37 | cursor: pointer;
38 | background-color: var(--primary-color);
39 | color: var(--secondary-color);
40 | border: 0;
41 | border-radius: 4px;
42 | padding: 8px 12px;
43 | position: absolute;
44 | top: 100px;
45 | }
46 |
47 | .toggle:focus {
48 | outline: none;
49 | }
50 |
51 | .clock-container {
52 | display: flex;
53 | flex-direction: column;
54 | justify-content: space-between;
55 | align-items: center;
56 | }
57 |
58 | .clock {
59 | position: relative;
60 | width: 200px;
61 | height: 200px;
62 | }
63 |
64 | .needle {
65 | background-color: var(--primary-color);
66 | position: absolute;
67 | top: 50%;
68 | left: 50%;
69 | height: 65px;
70 | width: 3px;
71 | transform-origin: bottom center;
72 | transition: all 0.5s ease-in;
73 | }
74 |
75 | .needle.hour {
76 | transform: translate(-50%, -100%) rotate(0deg);
77 | }
78 |
79 | .needle.minute {
80 | transform: translate(-50%, -100%) rotate(0deg);
81 | height: 100px;
82 | }
83 |
84 | .needle.second {
85 | transform: translate(-50%, -100%) rotate(0deg);
86 | height: 100px;
87 | background-color: #e74c3c;
88 | }
89 |
90 | .center-point {
91 | background-color: #e74c3c;
92 | width: 10px;
93 | height: 10px;
94 | position: absolute;
95 | top: 50%;
96 | left: 50%;
97 | transform: translate(-50%, -50%);
98 | border-radius: 50%;
99 | }
100 |
101 | .center-point::after {
102 | content: '';
103 | background-color: var(--primary-color);
104 | width: 5px;
105 | height: 5px;
106 | position: absolute;
107 | top: 50%;
108 | left: 50%;
109 | transform: translate(-50%, -50%);
110 | border-radius: 50%;
111 | }
112 |
113 | .time {
114 | font-size: 60px;
115 | }
116 |
117 | .date {
118 | color: #aaa;
119 | font-size: 14px;
120 | letter-spacing: 0.3px;
121 | text-transform: uppercase;
122 | }
123 |
124 | .date .circle {
125 | background-color: var(--primary-color);
126 | color: var(--secondary-color);
127 | border-radius: 50%;
128 | height: 18px;
129 | width: 18px;
130 | display: inline-flex;
131 | align-items: center;
132 | justify-content: center;
133 | line-height: 18px;
134 | transition: all 0.5s ease-in;
135 | font-size: 12px;
136 | }
137 |
--------------------------------------------------------------------------------