1. 程式人生 > 實用技巧 >使用SVG symbols建立圖示系統完整指南

使用SVG symbols建立圖示系統完整指南

從最開始的使用img圖片,到後來的使用csssprite來減少伺服器請求,再到流行的圖形字型化圖示Iconfont。現在,一種全新的圖示使用方式開始流行了起來——SVG symbols圖示。

工作原理

SVG symbols的工作原理:symbol元素用來定義一個圖形模板物件,它可以用一個use元素例項化。

symbol元素對圖形的作用是在同一文件中多次使用,symbol元素本身是不呈現的。只有symbol元素的例項(亦即,一個引用了symbol的use元素)才能呈現:

<svg>
  <symbol viewBox="0 0 24 24" id="heart">
    <path fill="#E86C60" d="M17,0c-1.9,0-3.7,0.8-5,2.1C10.7,0.8,8.9,0,7,0C3.1,0,0,3.1,0,7c0,6.4,10.9,15.4,11.4,15.8 c0.2,0.2,0.4,0.2,0.6,0.2s0.4-0.1,0.6-0.2C13.1,22.4,24,13.4,24,7C24,3.1,20.9,0,17,0z">
    </path>
  </symbol>
  <symbol viewBox="0 0 32 32" id="arrow">
    <path fill="#0f0f0f" d="M16,0C7.2,0,0,7.2,0,16s7.2,16,16,16s16-7.2,16-16S24.8,0,16,0z M22.8,13.6l-6,8C16.6,21.9,16.3,22,16,22 s-0.6-0.1-0.8-0.4l-6-8c-0.2-0.3-0.3-0.7-0.1-1S9.6,12,10,12h12c0.4,0,0.7,0.2,0.9,0.6S23,13.3,22.8,13.6z">
    </path>
  </symbol>
</svg>

這段程式碼使用SVG symbols定義了兩個圖示,每個symbol元素定義一個圖示,圖示id分別是heart和arrow,將其放在html檔案的body元素內。

通過以下程式碼引用id為heart的圖示:

<svg>
    <use xlink:href="#heart"/>
</svg>

xlink:href屬性值就是‘#’加symbol的id名稱,那麼只需改變這個屬性值就可以引用不同的圖示。

gulp自動化處理

如果你使用gulp構建專案,推薦使用一個專門用於處理SVG Symbols用的glup外掛gulp-svg-symbols,它不但能生成SVG Symbols檔案,還能生成一個demo檔案方便檢視圖示和複製程式碼。

安裝gulp-svg-symbols外掛,若沒有預先安裝gulp請先行安裝:

npm install gulp-svg-symbols  --save-dev

gulpfile.js寫入如下執行任務:

const gulp = require('gulp')
const svgSymbols = require('gulp-svg-symbols')

gulp.task(`sprites`, function() {
  return gulp
    .src(`assets/svg/*.svg`)
    .pipe(svgSymbols())
    .pipe(gulp.dest(`assets`))
})

現在生成SVG symbols檔案了,那怎麼將它引入到頁面呢?如果是多頁應用推薦使用svg4everybody.js為所有瀏覽器添加了SVG外部內容支援。這樣就能直接使用外部的SVG symbols檔案。

在文件中包含該指令碼:

<script src="/path/to/svg4everybody.js"></script>
<script>svg4everybody(); // run it now or whenever you are ready</script>

使用外部的SVG symbols檔案時,通過以下程式碼引用圖示(map.svg是外部的SVG symbols檔案,codepen是圖示id):

<svg>
  <use xlink:href="map.svg#codepen"/>
</svg>

如果是單頁應用,使用svg4everybody.js就感覺太繁瑣了,能不能一步搞定啊?當然可以,將將SVG symbols檔案轉成js檔案就好了,推薦使用gulp-svg-symbols2js將SVG symbols檔案轉成js檔案。

安裝gulp-svg-symbols2js外掛:

npm install gulp-svg-symbols2js --save-dev

修改gulpfile.js檔案:

const gulp = require('gulp')
const svgSymbols = require('gulp-svg-symbols')
const svgSymbols2js = require('gulp-svg-symbols2js');

gulp.task(`sprites`, function() {
  return gulp
    .src(`assets/svg/*.svg`)
    .pipe(svgSymbols())
    .pipe(svgSymbols2js())
    .pipe(gulp.dest(`assets`))
})

現在只要引入生成的js檔案,就可以在頁面中使用以下程式碼引用圖示:

<svg>
  <use xlink:href="#codepen"/>
</svg>

廣州品牌設計公司https://www.houdianzi.com

webpack自動化處理

如果你的專案使用webpack進行打包,可以考慮使用svg-sprite-loader外掛自動生成SVG symbols檔案。

安裝svg-sprite-loader:

npm install svg-sprite-loader --save-dev

將svg圖示放到src/icons目錄下,在webpack配置檔案中新增svg-sprite-loader的配置:

const path = require('path');

module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'dist')
  },
  module: {
    rules: [
      {
        test: /\.svg$/,
        loader: 'svg-sprite-loader',
        include: [path.resolve(__dirname, 'src/icons')], // 僅處理src/icons目錄下的svg檔案
        options: {
          symbolId: 'icon-[name]'
        }
      }
    ]
  }
}

在打包檔案(index.js)中引入單個圖示:

import cloud from './icons/cloud.svg'

這樣引入的好處是隻引入需要的圖示,沒引入的圖示不會被打包,缺點是當圖示很多時這樣引入會顯得很繁瑣,因為一般情況下,所有圖示都會被使用,所以有必要找到一種簡單的方式一次引入所有圖示。

使用一些程式碼將svg圖示全部引入:

const requireAll = requireContext => requireContext.keys().map(requireContext);
const req = require.context('./icons', true, /\.svg$/);
requireAll(req);

現在可以在html中使用圖示了:

<svg>
  <use xlink:href="#icon-cloud" />
</svg>

經驗總結和建議

  • 始終使用gulp構建,方便瀏覽的圖示demo在開發中很重要
  • 始終使用單色圖示,多色圖示只能通過id選擇器修改樣式
  • 始終在ie9+,及現代瀏覽器使用,傳統瀏覽器使用iconfont更好