4-4 使用 emotion 完成「臺灣好天氣」 UI
本單元對應的專案分支為:create-ui。
單元核心#
這個單元的主要目標包含:
- 使用 emotion 完成「臺灣好天氣」的完整 UI
切版拆解#
在了解 emotion 的基本使用後,現在就可以實際使用 emotion 來完成臺灣好天氣的 UI !
這個單元最後會完成的畫面如下:

note
「臺灣好天氣」的設計畫面主要是參考 imgur 上的圖片 (https://imgur.com/ZLgiOyj),另外則會使用 IconFinder 上 The Weather is Nice Today 所提供的天氣圖示來完成(https://www.iconfinder.com/iconsets/the-weather-is-nice-today)。
這裡我們將根據下圖拆分成不同的 HTML 區塊:

Location 元件#
以 Location 這個區塊為例,我們預期它會是個 div 元素,因此要建立帶有樣式的元件,只需要:
定義好之後,它就是一個 React 元件,可以直接把 <Location /> 放入 JSX 中:
而它最後在 HTML 中呈現出來就會是帶有一個特殊 class name 的 <div>,這個 class name(即下圖中的 css-a7vwns)則會對應到剛剛針對 <Location> 所撰寫的 CSS 樣式:

完成其他區塊的 Styled Components#
接下來可以繼續根據本篇最上方的架構,完成其他的 styled components,因為 CSS 的內容並不是本書的重點,為了減少不必要的篇幅,大家可以直接到下方的連結將 styled components 的部分複製到 ./src/App.js 中即可:

建立好帶有樣式的元件後,就可以根據上一個段落中架構好的區塊,依序把這些元件放入 App 元件的 JSX 中:
此時應該可以看到如下的畫面:

到目前還未載入任何和天氣有關的圖示。
在 React 中載入 SVG 圖示的方法#
在前面的單元中,我們已經把天氣圖示放到 ./src/images 的資料夾中,由於這裡我們是使用 create-react-app 這個工具建立的 React 開發環境,多數的設定 create-react-app 都已經幫開發者設定好,所以要把 SVG 載入 React 中的方式很簡單,只需要使用 create-react-app 提供的 ReactComponent 這個元件即可。
實際來看應用的方式,這裡先以白天多雲的圖示(day-cloudy.svg)為例:
- STEP 1-1:透過
import {...} from ...將./images/day-cloudy.svg匯入 - STEP 1-2:在
{}中使用 create-react-app 提供的元件ReactComponent,透過as可以將這個元件名稱進行修改,這裡改成DayCloudy - STEP 2:最後就可以把載入的 SVG 圖示當成 React 元件(
<DayCloudy />)在 JSX 中使用
提醒
上述這種載入 SVG 圖檔的方式需要使用 create-react-app 來建立專案才可以使用,否則需要自行在 WebPack 中建立對應的設定才行。另外,SVG 圖檔除了可以透過這裡所說的方式,做為 React 元件載入使用外,也可以直接匯入 SVG 當成圖片使用,這個部分的說明可以參考本單元放置於 Github 上的專案說明頁(分支 create-ui)。
將 SVG 圖示套用到「臺灣好天氣」#
現在就可以透過這種方式實際將天氣圖示放入 App 元件中。
天氣圖示說明#
在 ./src/images 中已經放了許多天氣圖示,這些圖示共可會分成三類,第一類的圖示會在白天使用,檔名以 day 開頭,會以太陽作為基底;第二類的圖示則在晚上使用,檔名以 night 開頭,會以月亮作為基底;其他的圖示則沒有特別區分白天和晚上。
將需要使用的圖示載入#
現在就讓我們來把相關的圖片載入進來,這些圖示分別是「白天多雲」、「風速」、「降雨」、「重新整理」:
接下來就可以把這些圖示直接當成 Component 來使用,放入 JSX 中:

現在的畫面會像這樣子:

圖片帶進來後,因為沒有設定寬高,看起來會破版的有點嚴重。
調整 SVG 圖示的樣式#
直接使用 CSS 選擇器來調整樣式#
對於這些 SVG 的元件來說,最後轉譯到網頁的時候其實就是把 SVG 的程式碼放入 HTML 內,因此一樣可以透過 CSS 選擇器去選到對應的 SVG 後進行樣式的調整。這裡我們先調整一下 <AirFlow /> 和 <Rain /> 的部分。只須在當初定義 styled components 的地方去添加 CSS 修改 SVG 的樣式即可。
以 AirFlow 的元件來說,可以在裡面選到 svg 元素後進行樣式調整:
同樣的,以 Rain 元件來說:
重新整理的 Refresh 元件一樣可以透過這樣的方式加以調整:
現在可以看到在風速、雨量和重新整理的部分大小都已經調整好了:

看起來已經大致上完成了,最後還希望能調整一下天氣圖示(白天多雲)的部分,因為不同的天氣圖示可能寬高會不一樣,這裡希望能夠限制一下天氣圖示的寬度,以因應不同的氣候狀況。
根據某一元件進行樣式調整#
上面我們使用 Emotion 來「建立」帶有樣式的 styled components,並在裡面透過 CSS 選擇器選到 svg 標籤後進行調整。但 Emotion 不僅可以用來建立帶有樣式的元件,還可以將「原本就存在」的元件添加樣式。
什麼意思呢?
舉例來說,剛剛我們透過 import 載入的 SVG 是一個 React 元件,例如,<DayCloudyIcon /> ,現在如果我們想要為這個原本就存在的元件添加樣式時,可以使用 const 新元件 = styled(<原有元件>)這樣的寫法:
也就是說,除了原本是在 styled.<html-tag> 後面加上一個 HTML 標籤,現在則是放入一個 React 元件,然後就可以在裡面撰寫 CSS 樣式,並修改該元件的樣式。
以實際的樣式來說,這裡 DayCloudy 這個元件是根據 DayCloudyIcon 這個元件而來,並且可以對它添加 CSS 樣式:
最後在 JSX 的地方,就要把原本使用 DayCloudyIcon 改成用新的帶有樣式的元件 DayCloudy :

現在透過 npm start 後完成的畫面會像這樣:

換你了!完成「臺灣好天氣」 UI#
現在換你來完成「臺灣好天氣」的 UI,可以參考下面的順序:
- 了解「臺灣好天氣」切版時的區塊結構
- 使用 emotion 建立帶有樣式的 styled components(可於網址下載撰寫好的樣式)
- 載入 SVG 圖示到 React 元件中(包含
day-cloudy.svg,airFlow.svg,rain.svg和refresh.svg) - 使用 CSS 選擇器的方式修改 SVG 圖示的樣式
- 使用 emotion 修改原有 SVG 元件的樣式
提醒讀者們,關於本單元的程式碼都可以在專案的 create-ui 分支中檢視完整的程式碼,並可以點擊「時鐘」圖示即可檢視本單元程式碼有變更的部分。另外,若有補充的資訊同樣會放在該分支的專案說明頁的。
本單元使用到的連結、完整程式碼與變更部分(時鐘圖示)可於 create-ui 分支檢視:https://github.com/pjchender/learn-react-from-hook-realtime-weather-app/tree/create-ui
