双色图标

通常字体图标是单色的。如果需要多色图标,可以利用 svg 多个 path 的特性实现。

双色图标实现步骤

1、更改 svg 属性

svg 图标有多个 path。我们给一种颜色 A 对应的 path,手动添加 fill="currentColor",另一种颜色 B 对应的 path 不需要修改。

例如下面的 svg 有两个 path,分别表示不同路径,第一个不改,第二个改属性 fill="currentColor"



<?xml version="1.0" encoding="utf-8"?>
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
     viewBox="0 0 32 32" style="enable-background:new 0 0 32 32;" xml:space="preserve">
<g>
    <path fill="currentColor" id="path-1" class="st0" d="M26,29h-5v-6H11v6H6l0-14.8l10-10l10,10L26,29z M28.8,12.8L28.8,12.8L16,0L0,16l2.3,2.3L3,17.6V32
        h11v-6h4v6h11V17.6l0.7,0.7L32,16L28.8,12.8z"/>
</g>

<g id="app-home">
    <g id="home">
        <path fill="currentColor" id="path-1_1_" class="st1" d="M26,29h-5v-6H11v6H6l0-14.8l10-10l10,10L26,29z M28.8,12.8L28.8,12.8L16,0L0,16l2.3,2.3
            L3,17.6V32h11v-6h4v6h11V17.6l0.7,0.7L32,16L28.8,12.8z"/>
    </g>
</g>
</svg>
<?xml version="1.0" encoding="utf-8"?>
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
     viewBox="0 0 32 32" style="enable-background:new 0 0 32 32;" xml:space="preserve">
<g>
    <path fill="currentColor" id="path-1" class="st0" d="M26,29h-5v-6H11v6H6l0-14.8l10-10l10,10L26,29z M28.8,12.8L28.8,12.8L16,0L0,16l2.3,2.3L3,17.6V32
        h11v-6h4v6h11V17.6l0.7,0.7L32,16L28.8,12.8z"/>
</g>

<g id="app-home">
    <g id="home">
        <path fill="currentColor" id="path-1_1_" class="st1" d="M26,29h-5v-6H11v6H6l0-14.8l10-10l10,10L26,29z M28.8,12.8L28.8,12.8L16,0L0,16l2.3,2.3
            L3,17.6V32h11v-6h4v6h11V17.6l0.7,0.7L32,16L28.8,12.8z"/>
    </g>
</g>
</svg>



2、安装配置 loader

用于解析打包 svg 文件



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



  • svg-sprite-loader 一个用于创建 svg 雪碧图的 Webpack 加载器, svg-sprite-loader 会把你引入的 svg 塞到一个个 symbol 中,合成一个大的 svg,最后将这个大的 svg 放入 body 中(压缩多个svg到一个svg,减少网络请求,类似雪碧图的技术)。
  • svgo-loader 基于 SVG Optimizer 的一个加载器,基于node.js 的工具,用于优化 SVG 矢量图形文件(移除 title style ID 等属性,减小代码量)

更改配置,在 webpack.config.js 中配置这两个 loader



// use svg-sprite-loader and svgo-loader to generate svg icons
{
  test: /\.svg$/,
    use: [
      {
        loader: 'svg-sprite-loader', options: {}
      },
      {
        loader: 'svgo-loader', options: {
          plugins:[
            'removeTitle',
            'removeStyleElement',
            'cleanupIDs',
            'inlineStyles',
            'removeXMLProcInst',
          ]
        }
      }
    ]
},

// use svg-sprite-loader and svgo-loader to generate svg icons
{
  test: /\.svg$/,
    use: [
      {
        loader: 'svg-sprite-loader', options: {}
      },
      {
        loader: 'svgo-loader', options: {
          plugins:[
            'removeTitle',
            'removeStyleElement',
            'cleanupIDs',
            'inlineStyles',
            'removeXMLProcInst',
          ]
        }
      }
    ]
},



3、封装 svg 多色图标组件



// 这是多色图标的前景色和背景色
const ICON_COLOR_MATRIX = [
  ['FACF55', 'F6AB2F'],
  ['F652B6', 'E91E63'],
];

// 辅助函数:导入全部
const importAll = (requireContext) => {
  requireContext.keys().forEach(requireContext);
};

// 导入全部 svg 文件(这里需要换成实际的路径,如果路径不存在会报错,所以 try-catch)
try {
  importAll(require.context('../assets/icons', true, /\.svg$/));
} catch (error) {
  console.log(error);
}




// 核心使用:多色图标类(传参 custom-page-wide 即可)
const Icon = (props) => {
  const { symbol } = props;
  return (
    <svg className={`multicolor-icon multicolor-icon-${symbol}`}>
      <use xlinkHref={`#${symbol}`} />
    </svg>
  );
};

DefaultIcon.propTypes = {
  symbol: PropTypes.string.isRequired,
};

<DefaultIcon symbol="custom-page-wide"/>
// 这是多色图标的前景色和背景色
const ICON_COLOR_MATRIX = [
  ['FACF55', 'F6AB2F'],
  ['F652B6', 'E91E63'],
];

// 辅助函数:导入全部
const importAll = (requireContext) => {
  requireContext.keys().forEach(requireContext);
};

// 导入全部 svg 文件(这里需要换成实际的路径,如果路径不存在会报错,所以 try-catch)
try {
  importAll(require.context('../assets/icons', true, /\.svg$/));
} catch (error) {
  console.log(error);
}




// 核心使用:多色图标类(传参 custom-page-wide 即可)
const Icon = (props) => {
  const { symbol } = props;
  return (
    <svg className={`multicolor-icon multicolor-icon-${symbol}`}>
      <use xlinkHref={`#${symbol}`} />
    </svg>
  );
};

DefaultIcon.propTypes = {
  symbol: PropTypes.string.isRequired,
};

<DefaultIcon symbol="custom-page-wide"/>



对应的样式,设置多色



/* 整体尺寸 */
.multicolor-icon {
  width: 1em;
  height: 1em;
  fill: currentColor; /* 重要 */
  overflow: hidden;
}

/* 每一个图标单独设置字号,前景色,背景色 */
.multicolor-icon-customer {
  font-size: 30px;
  fill: #fff; /* back ground color */
  color: #fff; /* icon color */
}

/* 整体尺寸 */
.multicolor-icon {
  width: 1em;
  height: 1em;
  fill: currentColor; /* 重要 */
  overflow: hidden;
}

/* 每一个图标单独设置字号,前景色,背景色 */
.multicolor-icon-customer {
  font-size: 30px;
  fill: #fff; /* back ground color */
  color: #fff; /* icon color */
}



如果需要 UI 交互(点击回调函数,鼠标经过变色,在上面基础上改动即可)

单色图标注意事项

如果按照上面的配置,渲染一个单色图标,边缘可能出现锯齿

因为一个 path 有颜色,另一个 path 没有颜色

方法1:更改 svg 属性,给全部 path 添加 fill="currentColor" 属性



<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 32 32" style="enable-background:new 0 0 32 32;" xml:space="preserve">
<title>autonumber-sync</title>

<g id="autonumber-sync">
    <path id="autonumber" fill="currentColor" class="st0" d="M108,1H11.8z"/>
    <path id="sync" fill="currentColor" class="st1" d="M22.2,25.1.5,2.3,2.4.4,19z"/>
</g>
</svg>

<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 32 32" style="enable-background:new 0 0 32 32;" xml:space="preserve">
<title>autonumber-sync</title>

<g id="autonumber-sync">
    <path id="autonumber" fill="currentColor" class="st0" d="M108,1H11.8z"/>
    <path id="sync" fill="currentColor" class="st1" d="M22.2,25.1.5,2.3,2.4.4,19z"/>
</g>
</svg>



方法2:更改 css 样式,设置图标的 fill 和 color 是相同的颜色(推荐使用)



.single-color-icon {
  fill: #aaa;
  color: #aaa;
}

.single-color-icon {
  fill: #aaa;
  color: #aaa;
}



参考资料