react中優雅使用svg矢量圖

icon圖標能夠有不少形式.好比說CSS Sprite、引用字體圖標、純css(簡單的icon)等等。 優缺點這裏不在贅述,自行google之。下面就進入正題說說今天的主角svg。css

一、svg的發展歷史

  • 2001年9月4日,發佈SVG 1.0
  • 2003年1月4日,發佈SVG 1.1
  • 2003年1月14日,推出SVG移動子版本:SVG Tiny和SVG Basic
  • 2008年12月22日,發布SVG Tiny 1.2
  • 2011年8月16日,發布SVG 1.1(第2版),成爲W3C目前推薦的標準
  • W3C目前仍正在研究制定SVG 2

他在2001年就已經被加入到W3C的標準中去了,歷時這麼久終於到了該翻身的時候了。react

二、通常頁面中如何使用svg

SVG 是一種基於 XML 語法的圖像格式,全稱是可縮放矢量圖(Scalable Vector Graphics)。其餘圖像格式都是基於像素處理的,SVG 則是屬於對圖像的形狀描述,因此它本質上是文本文件,體積較小,且無論放大多少倍都不會失真。SVG 文件能夠直接插入網頁,成爲 DOM 的一部分,而後用 JavaScript 和 CSS 進行操做。webpack

  • 下面是 SVG 代碼直接插入網頁的例子。
<svg width="100" height="100" version="1.1" xmlns="http://www.w3.org/2000/svg">
    <rect width="100%" height="100%" style="fill:blue;stroke-width:2;stroke:rgb(0,0,0)"/>
</svg>
複製代碼

效果以下: git

能夠看到svg的簡單實用,和展現效果。那麼react中如何使用svg呢。重複使用的svg是否能夠做爲模塊引入呢。答案下面揭曉。github

三、react中如何使用svg

其實也能夠像上面那樣去使用svg,可是問題來啦。重複的svg要代碼拷貝粘貼?後期維護和修改就有無盡的麻煩。因而就想到了組件化。如何組件話呢。svg結合use標籤就登上了舞臺。不直接在主頁面中編寫繪製svg圖標的代碼,而是把這一大段的代碼放到另外的文件中,而後使用 use引用這段繪製圖標的代碼便可(好像github就是這樣作的)。web

先囉嗦一下,實現的原理吧。 看代碼npm

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="position: absolute; width: 0; height: 0" id="__SVG_SPRITE_NODE__">
    <symbol xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="icon" viewBox="0 0 1024 1024" id="bank">
    <defs><style type="text/css"></style></defs>
    <rect width="100%" height="100%" style="fill:rgb(153, 238, 172);stroke-width:2;stroke:rgb(0,0,0)"></rect>    
    </symbol>
</svg>
複製代碼

如何使用bash

<svg><use xlink:href="#bank"></use></svg>
複製代碼

symbol中的id和use中的href要對應才行babel

這樣就能顯示上面的svgsvg

因此總結一下:

  1. react 項目中單獨存放svg文件
  2. 能夠提早加載,也能夠按需加載
  3. 使用的使用和上面同樣

雖說可使用可是若是直接引用可能打包報錯或者不顯示,常見緣由:

  1. webpack配置文件處理圖片或者字體的loader中含有svg的處理。
  2. svg使用姿式不正確 處理方法:我認爲svg-sprite-loader比較好用,固然處理svg的loader還有react-svg,react-svg-loader。如需瞭解google一下就知道

webpack.config.js

{
      test: /\.(eot|woff2?|ttf|svg)$/,
      exclude: path.resolve(__dirname, '../src/static/icons'), //不處理指定svg的文件
      use: [
        {
          loader: "url-loader",
          options: {
            name: "[name]-[hash:5].min.[ext]",
            limit: 5000, // fonts file size <= 5KB, use 'base64'; else, output svg file
            outputPath: "font",
            publicPath:'font'
          }
        }
      ]
}

{
      test: /\.svg$/,
      loader: 'svg-sprite-loader',
      include: path.resolve(__dirname, '../src/static/icons'), // //只處理指定svg的文件
      // options: {
      //   symbolId: '[name]'
      // }
}

複製代碼

前方高能

上面配置之後直接能夠在組件中

import '../../static/icons/bank'; //引入對應的bank.svg文件
...
//下面使用  須要把xlink:href 替換xlinkHref
 <svg><use xlinkHref="#bank"></use></svg>
複製代碼

若是icon不少每次都須要import ,對於一個懶人來講有點煩躁,不過下面的方式能夠幫你一次所有引入 在對應的icons文件下建index.js

let requireAll = requireContext => requireContext.keys().map(requireContext)
let svgs = require.context('./', false, /\.svg$/)
requireAll(svgs)
複製代碼

直接引入index.js以後全部組件都能開心的使用全部svg。固然默認id是文件名。

注意:

若是你不想一次性所有引入全部svg,懶加載一樣可行

npm install @babel/plugin-syntax-dynamic-import --save-dev
...
//在.babelrc中plugins加上
"plugins": [
        "@babel/plugin-syntax-dynamic-import",
    ]
複製代碼

便可實現。文筆粗淺,若有不懂,歡迎留言!!!

相關文章
相關標籤/搜索