Demo
簡介
從 「180 websites in 180 days」 看到的,這是裡面的 Day 11 作品。
這個網頁每過一秒會更新時間,同時漸進式改變背景的顏色,並且將背景顏色的 16 進位代碼 (Hex 色碼) 呈現在畫面上。
想法
- 使用 JavaScript 的
setInterval()
讓時間跟顏色每一秒改變一次。 - 原始作品是用 Hex 色碼表示顏色,我改用 RGB 色碼表示。
- 原始作品的時間跟顏色之間有關聯,所以重新載入網頁後,顏色不會隨機改變,而是按照原有的設定進行。我的作法是讓網頁每次載入時,都隨機產生顏色。
使用工具或技術
全部用 JavaScript 進行操作,其中幾個重要的方法如下:
- 時間函數:
new Date()
getHours()
getMinutes()
getSeconds()
- 排程設定:
setInterval()
過程
先在 HTML 架構好標題 (h5
) ,利用空的 div
提供時間以及顏色色碼要顯示的地方。
分別給 div
對應的 id
, 方便後續 JavaScript 取得並操作這些物件以顯示資訊。
接著處理 CSS 的部分。這個網頁的結構單純,需要調整的地方不多。幾個要點如下:
- 要讓畫面滿版,避免有留白的地方,所以設定全域的
padding
跟marging
為0
。 - 透過 “Google Fonts” 改字型。
- 用
text-align: center
讓位於.container
中的內容水平置中。 - 用
transiton: .5s
讓網頁的背景顏色切換時,能平滑漸進地轉換,而不是很突兀地跳了一個顏色。 - 運用一點 RWD,讓網頁在小螢幕時,字變小一點。
再來,用 JavaScript 處理動態效果。首先,當頁面載入成功時,就要呈現當下的時間以及顏色。因此我在 body
的起始標籤中加上 onload="start();"
,偵測頁面載入完成時執行動作。要執行的動作主要有三個部分:
- 取得目前時間:取得頁面載入完成當下的時間並顯示出來。
- 隨機產生顏色:隨機產生一組 RGB 色碼顯示於畫面上,也同時成為網頁的背景顏色。
- 每秒自動更新:每過一秒,就更新時間和顏色的值,同時渲染網頁的背景顏色。
1. 取得目前時間
使用 JavaScript 內建的 new Date()
取得當下的時間,再分別抓出裡面的時、分與秒。接著用 innerHTML
將這些取得的資料放到 id
為 time
的位置內。
但是,完成後會發現,如果任一時間的值小於 10 ,則只會顯示一位數字,例如會顯示 “7” 而不是 “07”。因此,我用條件判斷,如果數字小於 10, 就在前面強制加上 “0”,確保出來的結果皆為兩位數字。
1 | // 抓出時間要顯示的位置 |
2. 隨機產生顏色
宣告一個空陣列 rgbNum
,存放代表 RGB 的三個數字。以及 startNum
作為隨機產生的 RGB 初始數字 。
使用 Math.random()
產生亂數,再用 Math.floor()
取得範圍在 0~255 的整數。透過 for
迴圈一個個產生亂數的同時,也逐項放到陣列裡面,最後得到一個裡面有三個亂數的陣列。
將這三個數字組成符合 RGB 色碼格式的字串 rgb
,顯示到畫面上並且渲染畫面的背景顏色。
1 | // 抓出色碼要顯示的位置 |
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,則隨機產生顏色。
1 | // 每秒更新時間跟顏色 |
實際操作幾次後觀察發現,當 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
之後,就能正常執行了。
後記
完成這個作品之後,我去看了原作的程式碼,除了我在上面的想法中提到的不同之處,幾點主要差異整理如下:
- 原作是用 jQuery 進行撰寫,我是使用 JavaScript
- 時間的取得方式一樣,但我是以 24 小時制顯示,原作是以 12 小時制顯示。
- 原作的顏色透過時間轉換的方式為:
red = Math.round(255 * (hour / 23)).toString(16);
當初會做這個主要是因為覺得好看,加上想練習時間函數,心裡也明白這不會有什麼很厲害的用途。不過後來,有時候參加一些幾點就能幹嘛的活動時,會想到開這個來看時間。看著顏色變來變去的,就覺得等待的時間好像也沒那麼無聊了。
另外就是,有時候練習寫 code 時,只是單純想選一個自己看得順眼的顏色,我也會開這個作品,讓它隨機換顏色,換到喜歡的顏色就把 RGB 值記下來用。這麼想想,這個小作品對我來說還是很有幫助的呢。
只是背景顏色深或淺的時候,跟字的顏色如何配合,目前的處理方式我還是不太滿意,但有透明度的淺色背板也是我到目前能想到比較好的方法了,如果之後還有更好的方法再來改一改吧。