[ลองเล่นเล่น]สร้างนาฬิกาอนาล๊อค ด้วย HTML, CSS และ Javascript

Poolsawat Apin
5 min readNov 6, 2023

วันหยุดว่าง ๆ เปิด Youtube ดูอะไรไปเรื่อยเปื่อย ด้วยความเบื่อกับ content ของ youtube ที่เน่นไปทางบรรเทิง ต่าง ๆ มี content นึงแทรกขึ้นมา How to Create Analog Clock using HTML CSS and JavaScript ลองเปิดเข้าไปดู มันเป็นการสร้าง นาฬิกาอนาล๊อค ด้วยความที่ไม่ค่อยถนัดงานโค๊ดทาง frontend เท่าไหร่ ตัดสินใจลองเข้าไปดูและกัน เลยได้เกิดเป็นบทความนี้

ทำไมถึงเลือกเอามาเขียนบทความนี้

ครั้งแรกเมื่อได้ดู youtube นี้ (ลิ้งด้านบน) ก็คิดว่าต้องเขียนโค๊ดเยอะแน่เลย มันจะสร้างได้ไง นาฬิกาแบบอนาล๊อคมันเป็นวงกลม จะทำได้เหรอ แต่พอเข้าไปดูตัวอย่างโค๊ดก็พอจะเข้าใจแนวทางของวิดีโอนี้ อีกอย่างมันดูไปแล้ว มันสนุก อยากจะลองที่จะมาลองเขียนโค๊ดตามดู ทำตามดูสักหน่อย และเลยถือโอกาสเอามาบันทึกไว้ในนี้ซะเลย

css มันมาไกลมา ทำแบบนี้ได้ด้วยเหรอ

ผมค่อนข้างแปลกใจกับความสามารถของ css เกี่ยวกับการทำ ตัวแปร ของ style (— var) ได้นะ เพราะในความคิดของผมสำหรับ วิดีโอ นี้ต้อง วนลูป กับโค๊ด javascript จนปวดหัวแน่นอน แต่มันไม่ใช่เลย

พูดเยอะเจ็บคอ มาดูโค๊ดกันเลย

โดยเนื้อหาเกี่ยวกับส่วนของโค๊ดดิ่ง ผมจะขออธิบายตามความเข้าใจของผม แบ่งเป็นโค๊ดกับรูปภาพผลลัพธ์ของโค๊ดในส่วนนั้นแล้วกัน (ถ้าอัดวิดีโอ มันก็ไม่ต้องทำแบบนี้)

เริ่มต้นสร้างไฟล์ index.html, style.css, script.js และเพิ่มโค๊ด html ก่อน

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Clock Analog Design</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="container">
<div class="clock">
<span style="--i:1;"><b>1</b></span>
<span style="--i:2;"><b>2</b></span>
<span style="--i:3;"><b>3</b></span>
<span style="--i:4;"><b>4</b></span>
<span style="--i:5;"><b>5</b></span>
<span style="--i:6;"><b>6</b></span>
<span style="--i:7;"><b>7</b></span>
<span style="--i:8;"><b>8</b></span>
<span style="--i:9;"><b>9</b></span>
<span style="--i:10;"><b>10</b></span>
<span style="--i:11;"><b>11</b></span>
<span style="--i:12;"><b>12</b></span>
</div>
</div>

<script src="./script.js"></script>
</body>
</html>
  • import css, js เข้ามาในไฟล์ html
  • tag span ส่วนของ style=” — i:1;” จะสร้างตัวแปรให้แต่ละ span ตั้งแต่ 1–12

ตั้งต้นวาดวงกลมและกำหนดรูปแบบของตัวเลข

* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: sans-serif;
color: #ffffff;
}

body {
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
background-color: #212121;
}

.container {
position: relative;
}

.clock {
width: 300px;
height: 300px;
border-radius: 50%;
background-color: rgb(255, 255, 255, 0.1);
border: 2px solid rgb(255, 255, 255, 0.25);
box-shadow: 0px 0px 30px rgb(0, 0, 0, 0.9);
display: flex;
justify-content: center;
align-items: center;
}
  • กำหนดพื้นหลัง สีดำ background-color: #212121;
  • สร้างวงกลม border-radius: 50%;
  • สีตัวอักษร color: #ffffff;
  • สีเส้นวงกลมชั้นนอก border: 2px solid rgb(255, 255, 255, 0.25);

ส่วนไฮไลท์ของคำสั่ง css ที่น่าสนใจเกี่ยวกับการคำนวน ขยับตำแหน่งตัวเลข และกำหนดตำแหน่งศูนย์กลางของเข็มนาฬิกา

.clock span {
position: absolute;
transform: rotate(calc(30deg * var(--i)));
inset: 12px;
text-align: center;
}
  • หมุนตัวเลข ด้วย rotate span ด้วย transform: rotate(calc(30deg * var( — i)));

แก้ไขหมุนตัวเลขให้สวยงาม

.clock span b {
transform: rotate(calc(-30deg * var(--i)));
display: inline-block;
font-size: 20px;
}

.clock::before {
content: '';
position: absolute;
width: 8px;
height: 8px;
border-radius: 50%;
background-color: #fff;
z-index: 2;
}

เพิ่มในส่วนของเข็มนาฬิกา ภายใต้ <div class=”clock”>

<div class="clock">
<!-- เพิ่มตรงนี้ -->
<div style="--clr:#ff3d58;--h: 74px" id="hour" class="hand"><i></i></div>
<div style="--clr:#00a6ff;--h: 84px" id="min" class="hand"><i></i></div>
<div style="--clr:#ffffff;--h: 94px" id="sec" class="hand"><i></i></div>

<span style="--i:1;"><b>1</b></span>
<span style="--i:2;"><b>2</b></span>
<span style="--i:3;"><b>3</b></span>
<span style="--i:4;"><b>4</b></span>
<span style="--i:5;"><b>5</b></span>
<span style="--i:6;"><b>6</b></span>
<span style="--i:7;"><b>7</b></span>
<span style="--i:8;"><b>8</b></span>
<span style="--i:9;"><b>9</b></span>
<span style="--i:10;"><b>10</b></span>
<span style="--i:11;"><b>11</b></span>
<span style="--i:12;"><b>12</b></span>
</div>
.hand {
position: absolute;
display: flex;
justify-content: center;
align-items: flex-end;
}

.hand i {
position: absolute;
background-color: var(--clr);
width: 4px;
height: var(--h);
border-radius: 8px;
}
  • เพิ่ม 3 div สำหรับเข็ม ชั่วโมง, นาที, วินาที
  • กำหนด style ให้ class hand

สุดท้ายเพิ่มโค๊ด javascript เพื่อให้เข็มขยับทุกวินาที

let hr = document.getElementById('hour')
let min = document.getElementById('min')
let sec = document.getElementById('sec')

function displayTime() {
let date = new Date();
// Getting hour, mins, secs from date
let hh = date.getHours();
let mm = date.getMinutes();
let ss = date.getSeconds();

let hRotation = 30*hh + mm/2;
let mRotation = 6*mm ;
let sRotation = 6*ss;


hr.style.transform = `rotate(${hRotation}deg)`;
min.style.transform = `rotate(${mRotation}deg)`;
sec.style.transform = `rotate(${sRotation}deg)`;
}

setInterval(displayTime, 1000)
  • ค้นหา element ด้วย id document.getElementById
  • กำหนด function displayTime โดยเพิ่มโค๊ชดึงเวลาปัจจุบัน ชั่วโมง, นาที, วินาที
  • แก้ไขเปลี่ยน element โดยการ hr.style.transform = `rotate(${hRotation}deg)` แก้ไขทั้ง 3 เข็ม
  • กำหนด interval โดยกำหนดทำงานทุก 1 วินาที (1000 millisec) setInterval(displayTime, 1000)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Clock Analog Design</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="container">
<div class="clock">
<div style="--clr:#ff3d58;--h: 74px" id="hour" class="hand"><i></i></div>
<div style="--clr:#00a6ff;--h: 84px" id="min" class="hand"><i></i></div>
<div style="--clr:#ffffff;--h: 94px" id="sec" class="hand"><i></i></div>
<span style="--i:1;"><b>1</b></span>
<span style="--i:2;"><b>2</b></span>
<span style="--i:3;"><b>3</b></span>
<span style="--i:4;"><b>4</b></span>
<span style="--i:5;"><b>5</b></span>
<span style="--i:6;"><b>6</b></span>
<span style="--i:7;"><b>7</b></span>
<span style="--i:8;"><b>8</b></span>
<span style="--i:9;"><b>9</b></span>
<span style="--i:10;"><b>10</b></span>
<span style="--i:11;"><b>11</b></span>
<span style="--i:12;"><b>12</b></span>
</div>
</div>

<script src="./script.js"></script>
</body>
</html>
 * {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: sans-serif;
color: #ffffff;
}

body {
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
background-color: #212121;
}

.container {
position: relative;
}

.clock {
width: 300px;
height: 300px;
border-radius: 50%;
background-color: rgb(255, 255, 255, 0.1);
border: 2px solid rgb(255, 255, 255, 0.25);
box-shadow: 0px 0px 30px rgb(0, 0, 0, 0.9);
display: flex;
justify-content: center;
align-items: center;
}

.clock span {
position: absolute;
transform: rotate(calc(30deg * var(--i)));
inset: 12px;
text-align: center;
}

.clock span b {
transform: rotate(calc(-30deg * var(--i)));
display: inline-block;
font-size: 20px;
}

.clock::before {
content: '';
position: absolute;
width: 8px;
height: 8px;
border-radius: 50%;
background-color: #fff;
z-index: 2;
}

.hand {
position: absolute;
display: flex;
justify-content: center;
align-items: flex-end;
}

.hand i {
position: absolute;
background-color: var(--clr);
width: 4px;
height: var(--h);
border-radius: 8px;
}
let hr = document.getElementById('hour')
let min = document.getElementById('min')
let sec = document.getElementById('sec')

function displayTime() {
let date = new Date();
// Getting hour, mins, secs from date
let hh = date.getHours();
let mm = date.getMinutes();
let ss = date.getSeconds();

let hRotation = 30*hh + mm/2;
let mRotation = 6*mm ;
let sRotation = 6*ss;


hr.style.transform = `rotate(${hRotation}deg)`;
min.style.transform = `rotate(${mRotation}deg)`;
sec.style.transform = `rotate(${sRotation}deg)`;
}

setInterval(displayTime, 1000)

สรุปท้ายบทความ

สำหรับตัวผู้เขียนเอง มีความรู้สึกว่าบทความนี้เป็นเหมือนแรงบันดาลใจให้อยากกลับมาศึกษา css ในขั้นพื้นฐาน รวมถึงขั้นสูง การทำ animation ต่าง ๆ ถ้าในอนาคตถ้ามีเทคนิคดี ๆ แบบนี้จะมาเขียนลงอีกเรื่อย ๆ ครับ ขอบคุณที่ติดตาม

--

--

Poolsawat Apin

Senior Engineering, Full Stack Developer [Subscribe Me @poolsawat.com]