在 React 中使用 SVG 圖示元件

Jarvis42發表於2019-01-23

SVG 很酷,它們能放大放小。

那麼 SVG 的優點是什麼?

SVG 或可縮放向量圖形是基於 XML 的格式影像格式,可以在保持影像質量的同時縮放到任何大小。因此,當你需要根據需要調整大小的影像時,SVG 是可行的方法。它們基本上是 XML 文件,因此與其他影像格式相比,它們的檔案大小也很小。

它們也是有效的 XML 元素,可以使用 CSS 進行操作。所以在 SVG 上改變顏色和筆畫都可以透過 CSS 完成。

聽起來不錯。不好的地方呢?

在影像方面,SVG 非常適合簡單的形狀,充滿基本的筆觸和顏色。雖然比圖示更復雜但它們不值得麻煩。(除非你正在進行資料視覺化,否則請使用 D3.js

自己構建 SVG 也更復雜。由於它們是以 XML 格式構建的,因此構建一個可能比儲存畫素資料的等效光柵影像更難。

file

怎樣在 React 中引入?

在 web 文件中使用 SVG 時,你有兩種選擇。按原樣呈現 SVG 文件,或將其用作 img 標籤中的 src 屬性。優選的選項是按原樣使用它,因為影像標記中的 SVG 呈現為影像,並且不能在 img 標籤的 css 樣式之外進行操作。

因此,在決定在 React 專案中使用 SVG 時,最好構建一個元件,而不是將 SVG 渲染到文件中。

const SVG = () => 
  <svg
    width="100%"
    height="100%"
    viewBox="0 0 32 32"
    xmlns="http://www.w3.org/2000/svg"
    xmlnsXlink="http://www.w3.org/1999/xlink"
  >
      <path d="some path here" file="#000" />
  </svg>

這會將靜態 SVG 呈現到 html 文件中。讓我們新增一些道具。

const SVG = ({
  style = {},
  fill = '#fff',
  width = '100%',
  className = '',
  height = '100%',
  viewBox = '0 0 32 32',
}) =>
  <svg
    width={width}
    style={style}
    height={height}
    viewBox={viewBox}
    className={className}
    xmlns="http://www.w3.org/2000/svg"
    xmlnsXlink="htpp://www.w3.org/1999/xlink"
  >
      <path d="some path here" fill={fill} />
  </svg>

我們現在可以使用此元件來呈現不同顏色,類名和樣式的 SVG。

演示 https://codesandbox.io/embed/q79o54pxmj

當我們有多個圖示來處理時怎麼辦?

好的,我們現在大致瞭解如何為 SVG 圖示建立 React 元件。那麼我們如何處理大量的圖示,這在大型專案中很常見?在這裡,我們有多種選擇。我們可以有一個巨大的元件,它返回所需的 SVG 圖示或建立一個對映器元件,它接收一個 prop 並將其對映到等效的 SVG 元件。

讓我們來看看它們是如何實現的。

途徑 #1

演示:https://codesandbox.io/embed/ryy418r5km

TL:DR:我們建立一個 SVG 元件並將名稱 prop 傳遞給它。該元件解析與該圖示關聯的 viewBox 和路徑值,並返回 SVG 元素。

讓我們首先將名稱 prop 新增到我們的 SVG 元件並解析該名稱 prop 的路徑。

const getPath = (name, props) => {
  switch(name) {
    case 'icon-1':
      return <path {...props} d="icon-1-path" />;
    case 'icon-2':
      return <path {...props} d="icon-2-path" />;
    default:
      return <path />
  }
}

const SVG = ({
  name = '',
  style = {},
  fill = '#000',
  width= '100%',
  className = '',
  height = '100%',
  viewBox = '0 0 32 32',
}) =>
  <svg
    width={width}
    style={style}
    height={height}
    viewBox={viewBox}
    className={className}
    xmlns="http://www.w3.org/2000/svg"
    xmlnsXlink="http://www.w3.org/1999/xlink"
  >
    {getPath(name, { fill })}
  </svg>;

效果很好。但我們沒有考慮過每個 SVG 圖示都有自己的 viewBox 值。所以我們還需要根據名稱 prop 解析 viewBox。

const getViewBox = name => {
  switch(name) {
    case 'icon-1':
      return 'icon-1-view-box';  // Eg. 0 0 32 32
    default:
      return '';
  }
}

<svg
  width={width}
  style={style}
  height={height}
  className={className}
  viewBox={getViewBox(name)}
  xmlns="http://www.w3.org/2000/svg"
  xmlnsXlink="http://www.w3.org/1999/xlink"
>
    {getPath(name, { fill })}
</svg>;

就是這樣。我們可以向此元件新增更多路徑和檢視框,並透過為我們需要的圖示新增名稱 prop 來使用它。

<SVG fill="#49c" width={100} name="icon-1" />

途徑 #2

演示:https://codesandbox.io/embed/vvzkzwvp10

TR;DR:我們為每個 SVG 圖示建立單獨的檔案,並建立一個索引檔案,該檔案根據名稱 prop 返回 SVG 元件。

我們為每個我們想要的 SVG 圖示建立單獨的元件。

./icons
--/Phone.js
--/Trash.js
--/Messages.js
--/Envelope.js
--/Wifi.js

每個元件彼此獨立,可以單獨使用。

import Phone from './icons/Phone'

<Phone width={100} />

然後,我們建立一個索引檔案,該檔案根據名稱 prop 返回元件本身。

./icons
--/Phone.js
--/Trash.js
--/Message.js
--/Envelope.js
--/Wifi.js
--/...
--/index.js

索引檔案看起來像這樣。

import React from 'react';

import Phone from './Phone';
import Messages from './Messages';

const Icon = props => {
  swtich(props.name) {
    case "phone":
      return <Phone {...props} />;
    case "messages":
      return <Messages {...props} />;
    default:
      return <div />;
  }
}

export default Icon;

因此,只要我們需要在混合中新增新圖示,我們就會建立新元件並將它們包含在索引檔案中。我們透過匯入單個 Icon 元件並將名稱 prop 傳送到其中來使用此元件。

import Icon from './icons';

<Icon fill="#49c" width={100} name="phone" />

就是這樣。我詳細介紹來一些建立 React 元件來操作 SVG 影像的方法。當然,這些並不是 React 應用程式中處理 SVG 的唯一方法,也不是最好的方法。就像 Javascript 世界中的任何東西一樣,我們總能提供其他選擇。

替代選項

Webpack SVG Loader —— 用於將 SVG 檔案作為元件匯入的 webpack 載入程式

React Inline SVG —— 一個 React 元件,它將 SVG 檔案路徑作為 prop 在文件上呈現它們。

原文:https://blog.lftechnology.com/using-svg-ic...
圖示資源:https://iconstore.co/

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章