[譯] 為你的 React 應用製作 SVG 圖示庫

土豆呼叫番薯發表於2019-02-17

為你的 React 應用製作 SVG 圖示庫

目前來說,使用 SVG 是為應用建立圖示庫的最好方法。通過 SVG 製作出來的圖示是可縮放且可調整的,同時也是離散的,這意味著它們可以進行增量載入或更新。而與之相反,使用字型進行構建的圖示是不能進行增量載入/更新的。僅這一點就使 SVG 圖示成為了那些依賴於程式碼分離和增量部署的高效能應用的更佳選擇。

這篇文章描述瞭如何從一個 SVG 圖示庫中建立一個由 React 元件構成的包。儘管我會著重於 React 框架,然而製作任何其他型別的包也是同理的。在 Twitter 的專案中我使用了這篇文章介紹的幾種不同方式來打包公司內部的 SVG 圖示庫,包括:優化過後的 SVG ,純 JavaScript 模組,React Dom 元件,和 React Native 元件。

使用圖示

最終,我們得到的是一個能像任何其他 JavaScript 包一樣被安裝並使用的 JavaScript 包。

yarnpkg add @acme/react-icons
複製程式碼

每一個圖示都可以將其看作一個可用的,被獨立匯出的 React 元件。

import IconCamera from `@acme/react-icons/camera`;
複製程式碼

上面這行程式碼允許你的模組打包工具只打包需要的圖示。當使用程式碼分割功能時,圖示們能通過塊來進行高效地分離。相比於那些引入字型並將所有圖示打包入一個單一元件中的圖示庫來說,這是一個重大的優勢。

// 整個圖示庫都被打包進了你的應用
import Icon from `@acme/react-icons`;
const IconCamera = <Icon name=`camera` />;
複製程式碼

每一個圖示都能很簡單地根據使用情況來進行自定義(例如,顏色和大小等)。

import IconCamera from `@twitter/react-icons/camera`;
const Icon = (
  <IconCamera
    style={{ color: `white`, height: `2em` }}
  />
);
複製程式碼

然而圖示最終是渲染成 SVG 的,這是一個不為元件使用者們所知的實現細節。

建立元件

每個 React 元件都利用從 SVG 原始檔裡提取出的路徑和維度資料渲染出了一個行內 SVG 影像。使用 createIconComponent 助手函式,我們只需寥寥幾行模板程式碼便可從 SVG 資料中建立一個元件。

import createIconComponent from `./utils/createIconComponent`;
import React from `react`;
const IconCamera = createIconComponent({
  content: <g><path d=`...`></g>,
  height: 24,
  width: 24
});
IconCamera.displayName = `IconCamera`;
export default IconCamera;
複製程式碼

這是一個使用 createIconComponent 函式在搭建像 Twitter Lite 這樣的 web 應用(使用 React Native for Web 搭建)時的一個例子。

// createIconComponent.js
import { createElement, StyleSheet } from `react-native-web`;
import React from `react`;

const createIconComponent = ({ content, height, width }) =>
  (initialProps) => {
    const props = {
      ...initialProps,
      style: StyleSheet.compose(styles.root, initialProps.style),
      viewBox: `0 0 ${width} ${height}`
    };

    return createElement(`svg`, props, content);
  };

const styles = StyleSheet.create({
  root: {
    display: `inline-block`,
    fill: `currentcolor`,
    height: `1.25em`,
    maxWidth: `100%`,
    position: `relative`,
    userSelect: `none`,
    textAlignVertical: `text-bottom`
  }
});
複製程式碼

fill 這個樣式設定為 currentcolor 可以讓你通過 color 樣式屬性來控制 SVG 的顏色。

現在我們需要做的只剩下使用指令碼來處理 SVG 並生成對應的 React 元件了。

建立圖示包

你可以在 GitHub 上的一個叫做 icon-builder-example 的倉庫裡找到完成這一步工作的其中一種方式的完整示例程式碼。

整個示例工具的專案結構大概長這樣:

.
├── README.md
├── package.json
├── scripts/
    ├── build.js
    ├── createReactPackage.js
    └── svgOptimize.js
└── src/
    ├── alerts.svg
    ├── camera.svg
    ├── circle.svg
    └── ...
複製程式碼

構建指令碼使用了 SVGO 來優化 SVG,提取 SVG 路徑資訊和後設資料。之後例子中的 React 打包工具 使用了模板來建立 package.json 檔案和那些需要首屏展示的 React 圖示。

import createIconComponent from `./utils/createIconComponent`;
import React from `react`;
const ${componentName} = createIconComponent({
  height: ${height},
  width: ${width},
  content: <g>${paths}</g>
});
${componentName}.displayName = `${componentName}`;
export default ${componentName};
複製程式碼

為了從相同的 SVG 源編譯其他型別的包,也可以引入額外的打包工具。當底層的圖示庫改變時,只需要幾條命令就可以重新編譯數以百計的圖示併為每個包釋出新版本。


掘金翻譯計劃 是一個翻譯優質網際網路技術文章的社群,文章來源為 掘金 上的英文分享文章。內容覆蓋 AndroidiOS前端後端區塊鏈產品設計人工智慧等領域,想要檢視更多優質譯文請持續關注 掘金翻譯計劃官方微博知乎專欄

相關文章