avatar

目錄
Project - Colorful Clock

Colorful Clock

Demo

簡介

從 「180 websites in 180 days」 看到的,這是裡面的 Day 11 作品。

這個網頁每過一秒會更新時間,同時漸進式改變背景的顏色,並且將背景顏色的 16 進位代碼 (Hex 色碼) 呈現在畫面上。

原始作品

想法

  1. 使用 JavaScript 的 setInterval() 讓時間跟顏色每一秒改變一次。
  2. 原始作品是用 Hex 色碼表示顏色,我改用 RGB 色碼表示。
  3. 原始作品的時間跟顏色之間有關聯,所以重新載入網頁後,顏色不會隨機改變,而是按照原有的設定進行。我的作法是讓網頁每次載入時,都隨機產生顏色。

使用工具或技術

全部用 JavaScript 進行操作,其中幾個重要的方法如下:

  • 時間函數:
    • new Date()
    • getHours()
    • getMinutes()
    • getSeconds()
  • 排程設定:
    • setInterval()

過程

先在 HTML 架構好標題 (h5) ,利用空的 div 提供時間以及顏色色碼要顯示的地方。
分別給 div 對應的 id, 方便後續 JavaScript 取得並操作這些物件以顯示資訊。

接著處理 CSS 的部分。這個網頁的結構單純,需要調整的地方不多。幾個要點如下:

  • 要讓畫面滿版,避免有留白的地方,所以設定全域的 paddingmarging0
  • 透過 “Google Fonts” 改字型。
  • text-align: center 讓位於 .container 中的內容水平置中。
  • transiton: .5s 讓網頁的背景顏色切換時,能平滑漸進地轉換,而不是很突兀地跳了一個顏色。
  • 運用一點 RWD,讓網頁在小螢幕時,字變小一點。

再來,用 JavaScript 處理動態效果。首先,當頁面載入成功時,就要呈現當下的時間以及顏色。因此我在 body 的起始標籤中加上 onload="start();" ,偵測頁面載入完成時執行動作。要執行的動作主要有三個部分:

  1. 取得目前時間:取得頁面載入完成當下的時間並顯示出來。
  2. 隨機產生顏色:隨機產生一組 RGB 色碼顯示於畫面上,也同時成為網頁的背景顏色。
  3. 每秒自動更新:每過一秒,就更新時間和顏色的值,同時渲染網頁的背景顏色。

1. 取得目前時間

使用 JavaScript 內建的 new Date() 取得當下的時間,再分別抓出裡面的時、分與秒。接著用 innerHTML 將這些取得的資料放到 idtime 的位置內。

但是,完成後會發現,如果任一時間的值小於 10 ,則只會顯示一位數字,例如會顯示 “7” 而不是 “07”。因此,我用條件判斷,如果數字小於 10, 就在前面強制加上 “0”,確保出來的結果皆為兩位數字。

javascript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 抓出時間要顯示的位置
var timeStr = document.getElementById("time");

// 頁面載入時,取得目前時間
function currentTime() {
var nowTime = new Date();
var nowHours = nowTime.getHours();
var nowMinus = nowTime.getMinutes();
var nowSeconds = nowTime.getSeconds();
// 讓取得的時間用 appendZero() 確保以兩位數呈現,顯示到畫面上。
timeStr.innerHTML = appendZero(nowHours) + " : " + appendZero(nowMinus) + " : " + appendZero(nowSeconds);
}
currentTime();


// 當數字是個位數時,前面加 0
function appendZero(num) {
if (num < 10) {
return "0" + num;
} else {
return num;
}
}

2. 隨機產生顏色

宣告一個空陣列 rgbNum ,存放代表 RGB 的三個數字。以及 startNum 作為隨機產生的 RGB 初始數字 。

使用 Math.random() 產生亂數,再用 Math.floor() 取得範圍在 0~255 的整數。透過 for 迴圈一個個產生亂數的同時,也逐項放到陣列裡面,最後得到一個裡面有三個亂數的陣列。

將這三個數字組成符合 RGB 色碼格式的字串 rgb ,顯示到畫面上並且渲染畫面的背景顏色。

javascript
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
// 抓出色碼要顯示的位置
var colorStr = document.getElementById("color");
// 宣告一個空陣列,用來存放 RGB 色碼的三個數字。
var rgbNum = [];
// 用來存放產生的 RGB 色碼字串。
var rgb;

function currentColor() {
// 要隨機產生的 RGB 初始數字
var startNum;

// 產生三個隨機數字,並指派到 rgbNum 陣列中儲存。
for (i = 0; i <= 2; i++) {
// 無條件捨去,取得 0~255 的隨機數字。
startNum = Math.floor(Math.random() * 256);
rgbNum[i] = startNum;
}

// 將 RGB 色碼字串指派到變數 rgb 中,讓後面的程式碼簡潔。
rgb = "rgb(" + rgbNum[0] + "," + rgbNum[1] + "," + rgbNum[2] + ")";
// 更改背景顏色,並將 RGB 色碼呈現到畫面上。
document.body.style.backgroundColor = rgb;
colorStr.innerHTML = rgb;
}
currentColor();

3. 每秒自動更新

使用 setInterval 設定每 1000 毫秒 (1 秒) 更新一次時間以及顏色。時間的部分,我讓程式碼每秒重新抓一次時間,也就是每秒執行一次函式 currentTime()。至於顏色,是我認為這個作品中較有難度的部分。

我希望顏色能夠小幅度變化,但又能感受到不同,而不是每秒就隨機換一個顏色,因此我不打算每秒執行一次 currentColor() 。經過幾次嘗試之後,我讓 RGB 色碼中的 B 值每秒加 10,讓顏色往藍色偏移、越來越亮,也越來越淺。但因為 RGB 色碼的範圍在 0~255 ,因此要設定條件讓數值往上增加的同時不會超過 255,並且思考,當數值到了 255 的時候,下一步我希望程式執行什麼動作。

如果 B 值到了 255,我讓前面的 G 值加 1,同時 B 的值歸零,重新往上加。同樣地,如果 G 值也到了 255,那就讓前面的 R 值加 1。若是 RGB 三個值都滿 255,則隨機產生顏色。

javascript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 每秒更新時間跟顏色
setInterval(function () {
// 更新時間
currentTime();

// 更新顏色的條件與動作
if (rgbNum[2] <= 245) {
rgbNum[2] += 10;
} else if (rgbNum[1] <= 254) {
rgbNum[1]++;
rgbNum[2] = 0;
} else if (rgbNum[0] <= 254) {
rgbNum[0]++;
rgbNum[1] = 0;
} else {
currentColor();
}
rgb = "rgb(" + rgbNum[0] + "," + rgbNum[1] + "," + rgbNum[2] + ")";
document.body.style.backgroundColor = rgb;
colorStr.innerHTML = rgb;
}, 1000);

實際操作幾次後觀察發現,當 RGB 值中,三個都較小的時候,背景顏色太暗,字會看不清楚。因此原本打算在此條件下,讓畫面上的文字改為淺色,但該以多少 RGB 值為分界實在很難斷定,故多次嘗試之後決定將 .container 作為有透明度的淺色背板,讓背景色較暗時能凸顯出字來。

另外,由於一開始,我將色碼顯示位置的變數宣告為 color,顯示 RGB 色碼到畫面上時沒問題,可是要修改字的顏色時,因為變數跟字的顏色屬性 color 一樣,所以出現問題。把色碼顯示位置的變數名稱改為 colorStr 之後,就能正常執行了。

問題與解決

製作這個作品時,我遇到的問題及解決方式整理如下:

問題 1:小於 10 的時候,只顯示一位數。

if 判斷,當數字小於 10 的時候,強制在前面補上 0,其餘不變。確保輸出的時間數值都會是兩位數字。

參考: JavaScript 的獲取日期代碼不足兩位數補 0

問題 2: RGB 數值的範圍是 0~255,因此當 setInterval() 對 rgb 數值進行改變時,要進行範圍的控制與處理。

if 控制讓這些數值不超過 255,並思考數值達到 255 時,希望程式接下來進行什麼動作。

經過幾次嘗試之後,我讓 RGB 色碼中的 B 值每秒加 10,讓顏色往藍色偏移、越來越亮,也越來越淺。如果 B 值到了 255,則前面的 G 值加 1,同時 B 的值歸零,重新往上加。同樣地,如果 G 值也到了 255,那就讓前面的 R 值加 1。若是 RGB 三個值都滿 255,則隨機產生顏色。

問題 3: 背景顏色深的時候,字的顏色想改淺一點,但範圍怎麼抓?

根據觀察結果,當 RGB 值中,三個都較小的時候,背景顏色太暗,字相對會看不清楚。所以將 .container 作為有透明度的淺色背板,讓背景色較暗時能凸顯出字來。

問題 4: 無法改變字的顏色。

原先我打算在背景色為深色時,將字的顏色改為淺色。操作過程中發現當背景色變深時,字的顏色無法變淺。

檢查發現,是因為我一開始將色碼顯示位置的變數宣告為 color,顯示 RGB 色碼到畫面上時沒問題,可是要修改字的顏色時,因為變數跟字的顏色屬性 color 一樣,所以出現問題。把色碼顯示位置的變數名稱改為 colorStr 之後,就能正常執行了。

後記

完成這個作品之後,我去看了原作的程式碼,除了我在上面的想法中提到的不同之處,幾點主要差異整理如下:

  1. 原作是用 jQuery 進行撰寫,我是使用 JavaScript
  2. 時間的取得方式一樣,但我是以 24 小時制顯示,原作是以 12 小時制顯示。
  3. 原作的顏色透過時間轉換的方式為:red = Math.round(255 * (hour / 23)).toString(16);

當初會做這個主要是因為覺得好看,加上想練習時間函數,心裡也明白這不會有什麼很厲害的用途。不過後來,有時候參加一些幾點就能幹嘛的活動時,會想到開這個來看時間。看著顏色變來變去的,就覺得等待的時間好像也沒那麼無聊了。

另外就是,有時候練習寫 code 時,只是單純想選一個自己看得順眼的顏色,我也會開這個作品,讓它隨機換顏色,換到喜歡的顏色就把 RGB 值記下來用。這麼想想,這個小作品對我來說還是很有幫助的呢。

只是背景顏色深或淺的時候,跟字的顏色如何配合,目前的處理方式我還是不太滿意,但有透明度的淺色背板也是我到目前能想到比較好的方法了,如果之後還有更好的方法再來改一改吧。

文章作者: Jane Lin
文章鏈接: http://yoursite.com/2020/02/13/1581539433/
版權聲明: 本博客所有文章除特別聲明外,均採用 CC BY-NC-SA 4.0 許可協議。轉載請註明來自 JL's Coding Notes

評論