使用SVG symbols建立图标系统完整指南
工作原理
SVG symbols的工作原理:symbol元素用来定义一个图形模板对象,它可以用一个use元素实例化。
symbol元素对图形的作用是在同一文档中多次使用,symbol元素本身是不呈现的。只有symbol元素的实例(亦即,一个引用了symbol的use元素)才能呈现:
这段代码使用SVG symbols定义了两个图标,每个symbol元素定义一个图标,图标id分别是heart和arrow,将其放在html文件的body元素内。
通过以下代码引用id为heart的图标:
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文件。
在文档中包含该脚本:
svg4everybody(); // run it now or whenever you are ready
使用外部的SVG symbols文件时,通过以下代码引用图标(map.svg是外部的SVG symbols文件,codepen是图标id):
如果是单页应用,使用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文件,就可以在页面中使用以下代码引用图标:
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中使用图标了:
经验总结和建议
- 始终使用gulp构建,方便浏览的图标demo在开发中很重要
- 始终使用单色图标,多色图标只能通过id选择器修改样式
- 始终在ie9+,及现代浏览器使用,传统浏览器使用iconfont更好