在 React Create-React-App 引入 SVG 圖檔的方法,並使用 Styled-Components 來調整 SVG Icon 在不同狀態下的色彩改變

Angel
Its Ok to Make Mistakes
9 min readJan 29, 2019

Create React App 在第二版中增添了svgr,這個 Webpack Loader 可以將 React 中的 SVG 包裝為 Component 的形式。

過去想要使用大量 SVG Icons 在 React 專案中,大部分的設計師選擇將 Icon 丟入 Icomoon 當中轉為 Font 檔,可以快速地利用 CSS 將整組 Icon Font 換色、調整尺寸等。

不過在 2017 年年底時,曾發生過 icomoon 網站修改 IconFont 產出設定的慘案,導致重新匯出時既有的 Icon 全部跑位,但我手上又沒有原本的圖檔,連全部重新匯入都無法。至從那之後,開始認真尋找替代方案,SVG Sprites 是選項之一,而使用 svgr 將一顆一顆的 SVG Icon 包裝為 Component 的形式,是我自己目前選擇的作法。

第一步:將 SVG 以 Component 的形式匯入 React

Create React App 提供的 Logo Sample 使用 Image Source 匯入,即便是 SVG 圖檔也無法編輯 fill、stroke 來動態改變外觀。

import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
class App extends Component {
render() {
return (
<div className="App">
<img src={logo} className="App-logo" alt="logo" />
</div>
);
}
}
export default App;

需要將 SVG 圖檔包裝為 Component

import { ReactComponent as Logo } from './logo.svg'

以 Component 的方式匯入至 Template,可以保留 SVG 的特性,直接使用 stroke 來改變圖形外觀

import React, { Component } from 'react';
import logo from './logo.svg'
import { ReactComponent as Logo } from './logo.svg'
import './App.css'
class App extends Component {
render() {
return (
<div className="App">
<img src={logo} className="App-logo" alt="logo" />
<Logo className="App-logo" alt="logo" stroke="#DB7290" strokeWidth="1rem"/>
</div>
);
}
}
export default App;

在瀏覽器就會呈現出這樣的效果:

第二步:使用 CSS 來調整 SVG Component

在 App.css 檔案中添加動畫及其他 Style 樣式, 在 Template 中 引用 ClassName 即完成。

.App {
text-align: center;
}
.App-logo {
animation: App-logo-spin infinite 20s linear;
}
.App-logo g {
fill: #DB7290;;
}
.App-logo path {
stroke: #DB7290;;
stroke-width: 10px;
fill: #FFD0DD;
stroke-dasharray: 35px 15px;
animation: orbit 1s infinite linear;
}
@keyframes orbit { to { stroke-dashoffset: 50px; } }@keyframes App-logo-spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}

在瀏覽器呈現的效果:

第三步:使用 Styled-Component 來調整 SVG Icon 在不同狀態下的色彩改變

添加數個 SVG Icon 在 img 檔案夾中

在 Components 檔案夾中加入一個 icons.js 的檔案,並在裡面引入所需要的 SVG Icon 後匯出

import { ReactComponent as Facebook } from '../img/facebook.svg';
import { ReactComponent as Instagram } from '../img/instagram.svg';
import { ReactComponent as Spotify } from '../img/spotify.svg';
import { ReactComponent as Telegram } from '../img/telegram.svg';
import { ReactComponent as Twitter } from '../img/twitter.svg';
export default {
Facebook, Instagram, Spotify, Telegram, Twitter
};

回到 App.js 檔案,使用 Styled Component 加入 Styles(補充:Styled Component 的設定 >> 使用 Create React App 創建 React Styled Component 及 Sass 開發環境

import React, { Component } from 'react';
import SocialMedia from './components/icons';
import styled from 'styled-components';
const SocialMediaWrapper = styled.div`
& path {
fill: #DB7290;
}
`
class App extends Component {
render() {
return (
<div className="App">
<SocialMediaWrapper >
<SocialMedia.Facebook />
<SocialMedia.Instagram />
<SocialMedia.Spotify />
<SocialMedia.Telegram />
<SocialMedia.Twitter />
</SocialMediaWrapper>
</div>
);
}
}
export default App;

在瀏覽器呈現的效果:

使用 React 搭配 Styled Component 設定 SVG 的 fill 來動態改變 Icon 顏色,可以快速設定 Icon 的 Hover / Clicked / Normal /Active / Disabled 在不同狀態下換色,並避免過往 CSS Class 造成的全域污染問題。

import React, { Component } from 'react'
import SocialMedia from './components/icons'
import styled from 'styled-components'
const Wrapper = styled.div`
text-align: center;
margin: 20px;
`;
const SocialMediaWrapper = styled.div`
display: inline-block;
padding: 1rem;
& path {
fill: ${props => (props.disabled ? '#dfdfdf' : (props.active ? '#DB7290' : '#FFD0DD'))};
&:hover{
fill: ${props => (props.disabled ? 'none' : '#f3a333')};
}
&:active{
fill: ${props => (props.disabled ? 'none' : '#930077')};
}
}
`
class App extends Component {
render() {
return (
<div className="App">
<Wrapper>
<SocialMediaWrapper active>
<SocialMedia.Facebook/>
<div>Active</div>
</SocialMediaWrapper>
<SocialMediaWrapper>
<SocialMedia.Instagram/>
<div>Normal</div>
</SocialMediaWrapper>
<SocialMediaWrapper>
<SocialMedia.Spotify/>
<div>Hover</div>
</SocialMediaWrapper>
<SocialMediaWrapper>
<SocialMedia.Telegram />
<div>Clicked</div>
</SocialMediaWrapper>
<SocialMediaWrapper disabled>
<SocialMedia.Twitter/>
<div>Disabled</div>
</SocialMediaWrapper>
</Wrapper>

</div>
);
}
}
export default App;

在瀏覽器呈現的效果:

參考資料:Add SVGs as React Components with Create React App 2.0

Say hello! 我是 Angel,這裏的內容如果有幫到你,希望能獲得一些拍手作為鼓勵 
工作上的合作歡迎隨時透過 Mail 聯繫我 contact@aneglho.design

Thanks for watching!

--

--

Angel
Its Ok to Make Mistakes

A web / UIUX designer, in digital entertainment industry, Taipei Taiwan.