12月19, 2017

SVG ICON小试

对近期项目中尝试采用svg图片替代普通png图片的一个小总结。

使用SVG Icon的好与坏

优势:

  1. 矢量的,在不同屏幕分辨率下都能保真,高清。不用再采用background-image设置1倍和2倍图,但目前移动端设备像素比越来越高,2倍图就也显得不太够用。另外提供多倍图,也给设计师增加了工作量。

  2. 方便改变图标颜色,其中一个适用场景就是,与导航栏处的字体颜色一起改变。不需要像使用CSS Sprite那样,再通过控制background-position来进行处理。

  3. 图标支持多色,就是一个图标中不同部分可以有不同的颜色。

劣势:

  1. 不可缓存,不能够充分利用浏览器缓存。但也可存在localStorage中。

  2. 兼容性,IE8-不支持svg;移动端不同设备支持度也不一样。总有一些奇怪的设备出现奇怪的问题。

  3. 目前这种方式还不太普及,对设计师也有一定的要求,需要导出符合一定规范的svg图标。否则,无法做到通过一次改变fill和stroke改变整个icon颜色。这里推荐阿里iconfont的规范和标准。

这里也暂且先不讨论使用字体的形式,因为实际场景下业务中使用这种形式的并不多;因为它本质上还是font,所以只能支持单色,不支持多色;另外根据页面关键渲染路径讲到,字体的加载也会阻塞整个页面的渲染;再有,字体的渲染,在不同的渲染机制下,可能会出现锯齿的情况。

使用SVG Icon的几种方式

  1. 作为img的src引入

    • 不能动态改变图标的颜色,比如hover

    • 其路径是相对于nginx配置的静态资源路径

    <img src="img/038747a5402cc040810c028602515b65.svg" alt="" class="header-icon-wrap" />
    
  2. 作为元素的background引入

    • 同样不能动态改变图标的颜色,比如hover

    • 引入路径与webpack中的配置相关

    span:before{
    display: inline-block;
    content: '';
    width: 25px;
    height: 25px;
    margin-right: 10px;
    background: url('../../img/header/aqi.svg');
    background-size: 25px;
    }
    
  3. 直接在页面里引入图标 缺点是需要将用到的每一个图标都用手动添加进来,增加使用成本。

<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<symbol id="home"><g stroke="#001A29" stroke-width="2" fill="none" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round"><path d="M7.00723901,17.0080067 L5.50324521,17.0080067 C4.67481809,17.0080067 4.00324521,16.3364339 4.00324521,15.5080067 C4.00324521,15.1233894 4.15098755,14.7534673 4.41594666,14.4746714 L13.9204884,4.47377973 C14.4911837,3.87328132 15.4406238,3.84912115 16.0411222,4.41981648 C16.0688009,4.44657585 16.0688009,4.44657585 16.0955479,4.4742665 L25.5915739,14.4751582 C26.1620004,15.075912 26.1374153,16.0253412 25.5366615,16.5957677 C25.2579153,16.8604422 24.8881982,17.0080067 24.503813,17.0080067 L23.0270155,17.0080067 L23.0270155,26.0073411 L18.0014038,26.0073411 L18.0014038,21.0111608 C18.0014038,19.3522335 16.6565775,18.0074071 14.9976501,18.0074071 C13.3387228,18.0074071 11.9938965,19.3522335 11.9938965,21.0111608 L11.9938965,26.0073411 L7.00723901,26.0073411 L7.00723901,17.0080067 Z" /></g></symbol>
</svg>

<svg class="header-icon"><use xlink:href="#{%$key%}" /></svg>
  1. SVG Defs/Symbols

    着重介绍下基于webpack采用这种方式的做法,webpack rules的配置如下。

    {
    test: /\.(png|jpe?g|gif)(\?.*)?$/,
    exclude: [path.resolve(__dirname, "tpls/img/icons")],
    loader: 'url-loader',
    options: {
     limit: 512,
     outputPath: 'img/'
    },
    },
    {
    test: /\.svg$/,
    include: [path.resolve(__dirname, "tpls/img/icons")],
    use: [
     {
       loader: 'svg-sprite-loader',
       options: {
         name: '[name]'
       }
     },
     {
       loader: 'svgo-loader',
       options: {
         plugins: [
           {removeTitle: true},
           {removeUnknownsAndDefaults: false}
         ]
       }
     }
    ]
    },
    {
    test: /\.(eot|svg|ttf|woff|woff2)(\?\S*)?$/,
    loader: 'file-loader',
    exclude: [path.resolve(__dirname, "tpls/img/icons")],
    options: {
     outputPath: 'img/'
    }
    }
    

    其他部分的代码分为3块:

基于webpack使用了2个插件,分别是svg-sprite-loadersvgo-loader。前者主要是为了引入svg并在模板中直接通过xlink的方式使用;后者是去除svg文件中一些无用的信息,起到精简代码的效果。

另外svgo的配置很多,可能需要根据实际情况进行具体配置的选择。

使用svgo之后,从下面的前后svg文件内容对比可以看出,代码精简了非常多,去掉了很多无关图标的信息,比如注释,titile,desc等等。

上面的图中requireALL那段js的主要作用是,为了自动导入指定文件夹../../img/icons(这个路径是相对于js文件自身的)下的所有svg文件。

这样再需要添加新svg时,就不用挨个手动写import,而可以直接使用xlink就可以了。

参考

本文链接:https://imjiaolong.cn/post/svg-icon.html

-- EOF --

Comments

评论加载中...

注:如果长时间无法加载,请针对 disq.us | disquscdn.com | disqus.com 启用代理。