新手村02 - JS and CSS Clock

02 - JS and CSS Clock

俗話說的好,一天一蘋果,醫生遠離我
一天一 JS,What the f*ck JavaScript?
small steps every day - 記錄著新手村日記

CSS+JS Clock 完成目標

時鐘一開始就提供了一個鐘面,也寫好了三支指針

  • 功能
    • 顯示目前的時間並可以更新時針、分針、秒針
  • 畫面
    • 讀得到目前的時間
    • 指針要能分辨長短
    • 分針、時針的特性

index_START.html

html 的整體結構如下所示, class="clock" 包住 class="clock-face",內部又有 hand hour-hand hand min-handhand second-hand 三個 div ,分別代表秒針、分針、時針

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>JS + CSS Clock</title>
</head>
<body>
<div class="clock">
<div class="clock-face">
<div class="hand hour-hand"></div>
<div class="hand min-hand"></div>
<div class="hand second-hand"></div>
</div>
</div>
<style>
html {
background: #018DED url(http://unsplash.it/1500/1000?image=881&blur=5);
background-size: cover;
font-family: 'helvetica neue';
text-align: center;
font-size: 10px;
}
body {
margin: 0;
font-size: 2rem;
display: flex;
flex: 1;
min-height: 100vh;
align-items: center;
}
.clock {
width: 30rem;
height: 30rem;
border: 20px solid white;
border-radius: 50%;
margin: 50px auto;
position: relative;
padding: 2rem;
box-shadow:
0 0 0 4px rgba(0,0,0,0.1),
inset 0 0 0 3px #EFEFEF,
inset 0 0 10px black,
0 0 10px rgba(0,0,0,0.2);
}
.clock-face {
position: relative;
width: 100%;
height: 100%;
transform: translateY(-3px); /* account for the height of the clock hands */
}
.hand {
width: 50%;
height: 6px;
background: black;
position: absolute;
top: 50%;
}
</style>

<script>
</script>
</body>
</html>

CSS

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
<style>
html {
background: #018DED url(http://unsplash.it/1500/1000?image=881&blur=5);
background-size: cover;
font-family: 'helvetica neue';
text-align: center;
font-size: 10px;
}

body {
margin: 0;
font-size: 2rem;
display: flex;
flex: 1;
min-height: 100vh;
align-items: center;
}

.clock {
width: 30rem;
height: 30rem;
border: 20px solid white;
border-radius: 50%;
margin: 50px auto;
position: relative;
padding: 2rem;
box-shadow:
0 0 0 4px rgba(0,0,0,0.1),
inset 0 0 0 3px #EFEFEF,
inset 0 0 10px black,
0 0 10px rgba(0,0,0,0.2);
}

.clock-face {
position: relative;
width: 100%;
height: 100%;
transform: translateY(-3px); /* account for the height of the clock hands */
}

.clock-face:after {
content: '';
display: block;
width: 30px;
height: 30px;
position: absolute;
background-color: #fff;
border-radius: 100%;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}

.hand {
position: absolute;
width: 100%;
height: 100%;
}

.second-hand:after {
content: '';
position: absolute;
display: block;
width: 5px;
height: 50%;
background-color: #f00;
left: 50%;
bottom: 50%;
transform: translate(-50%, 0%);
}

.min-hand:after {
content: '';
position: absolute;
display: block;
width: 10px;
height: 40%;
background-color: white;
left: 50%;
bottom: 50%;
transform: translate(-50%, 0%);
}

.hour-hand:after {
content: '';
position: absolute;
display: block;
width: 15px;
height: 25%;
background-color: white;
left: 50%;
bottom: 50%;
transform: translate(-50%, 0%);
}
</style>

JS - step by step

首先,先分別抓到秒針、分針、時針的 class 指定給變數 second、min、hour,在後方的計算時間時需要將三個針旋轉角度,達到時鐘的效果

1
2
3
4
5
<script>
const second = document.querySelector('.second-hand')
const min = document.querySelector('.min-hand')
const hour = document.querySelector('.hour-hand')
</script>

可以使用 new Date() 來抓到現在的時間

Date():https://ubin.io/WvAtZC

1
2
3
4
5
6
7
8
9
10
11
12
13
<script>
const second = document.querySelector('.second-hand')
const min = document.querySelector('.min-hand')
const hour = document.querySelector('.hour-hand')

function setClock(){
let data = new Date()
console.log(data)
// Sat Sep 14 2019 23:28:44 GMT+0800 (台北標準時間)
}

setClock()
</script>

算出一秒鐘、一分鐘、一小時中秒針、分針、時針需要轉動多少角度,一圈轉360度時,秒針、分針動一秒為6度、時針為30度,知道這件事情後,我們才能將三者指定為變數(但有小瑕疵稍後會解決)

Date.prototype.getSeconds():https://ubin.io/Uw21Ep
Date.prototype.Minutes():https://ubin.io/L6mcH5
Date.prototype.getHours():https://ubin.io/2DvLNS

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<script>
const second = document.querySelector('.second-hand')
const min = document.querySelector('.min-hand')
const hour = document.querySelector('.hour-hand')

function setClock(){
let data = new Date()

let secondDeg = data.getSeconds() * 6 // (deg = 360/60)
let minDeg = data.getMinutes() * 6 // (deg = 360/60)
let hourDeg = data.getHours() * 30 // (deg = 360/12)
}

setClock()
</script>

透過 event.style.transform 更動秒針、分針、時針的 CSS,要它們轉動個字的角度

Style transform Property:https://ubin.io/1LyRPt

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<script>
const second = document.querySelector('.second-hand')
const min = document.querySelector('.min-hand')
const hour = document.querySelector('.hour-hand')

function setClock(){
let data = new Date()

let secondDeg = data.getSeconds() * 6 // (deg = 360/60)
let minDeg = data.getMinutes() * 6 // (deg = 360/60)
let hourDeg = data.getHours() * 30 // (deg = 360/12)

second.style.transform = `rotate(${secondDeg}deg)`
min.style.transform = `rotate(${minDeg}deg)`
hour.style.transform = `rotate(${hourDeg}deg)`

}
setClock()
</script>

透過 setInterval() 不斷在間隔固定的時間重複執行:程式碼中的 1000 代表每隔一秒就會呼叫一次函式 setClock

setTimeout() / setInterval():https://reurl.cc/Qp76ab

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<script>
const second = document.querySelector('.second-hand')
const min = document.querySelector('.min-hand')
const hour = document.querySelector('.hour-hand')

function setClock(){
let data = new Date()

let secondDeg = data.getSeconds() * 6 // (deg = 360/60)
let minDeg = data.getMinutes() * 6 // (deg = 360/60)
let hourDeg = data.getHours() * 30 // (deg = 360/12)

second.style.transform = `rotate(${secondDeg}deg)`
min.style.transform = `rotate(${minDeg}deg)`
hour.style.transform = `rotate(${hourDeg}deg)`

}
setClock()
setInterval(setClock,1000)
</script>

還有一點小瑕疵…你會發現分針、時針不太符合常態,會真正到等分針、秒針轉完一圈才進位一大格,但應該是會慢慢的趨向於進一格,因此在抓角度的算式必須更動一下,可以試著畫圖想想看…

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<script>
// 上略
function setClock(){
let data = new Date()

let secondDeg = data.getSeconds() * 6
let minDeg = data.getMinutes() * 6 + data.getSeconds() * 6 / 60
// 1min = 6deg / 60sec * secondDeg
let hourDeg = data.getHours() * 30 + data.getMinutes() * 30 / 60
// 1hr = 30deg / 60min * minDeg

second.style.transform = `rotate(${secondDeg}deg)`
min.style.transform = `rotate(${minDeg}deg)`
hour.style.transform = `rotate(${hourDeg}deg)`

}
setClock()
setInterval(setClock,1000)

</script>

就大功告成啦!

JS - Final

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<script>
const secondHand = document.querySelector('.second-hand');
const minsHand = document.querySelector('.min-hand');
const hourHand = document.querySelector('.hour-hand');

function setDate() {
const now = new Date();

const seconds = now.getSeconds();
const secondsDegrees = ((seconds / 60) * 360) + 90;
secondHand.style.transform = `rotate(${secondsDegrees}deg)`;

const mins = now.getMinutes();
const minsDegrees = ((mins / 60) * 360) + ((seconds/60)*6) + 90;
minsHand.style.transform = `rotate(${minsDegrees}deg)`;

const hour = now.getHours();
const hourDegrees = ((hour / 12) * 360) + ((mins/60)*30) + 90;
hourHand.style.transform = `rotate(${hourDegrees}deg)`;
}

setInterval(setDate, 1000);

setDate();

</script>

本次範例程式碼原作者來源:https://reurl.cc/zybW5k