<!-- iconfont使用 -->
<i class="iconfont icon-user" style="color: #f00;font-size: 64px;"></i>

<!-- VS -->

<!-- 封装svg使用 -->
<svg-icon icon="user" color="#f00" :size="64" />

同时,在 flex 布局大行其道的今天,icons 与文字的对其,已经不存在任何问题。

SVG 还有一个 iconfont 做不到的特性:多颜色图标。这足以满足一些对特殊图标显示的场景。

平滑过度指南

  • Vite + Vue 3

首先,在 src 目录下创建 icons 目录,用以放置收集的单体 SVG 文件。

接着,安装 vite-plugin-svg-icons 这个依赖:

$ pnpm add vite-plugin-svg-icons -D

改一点 Vite 的配置:

// vite.config.js
import { defineConfig } from 'vite'
import { resolve } from 'path'
import { createSvgIconsPlugin } from 'vite-plugin-svg-icons'

export default defineConfig({
  ...,
  plugins:[
    ...,
    createSvgIconsPlugin({
      iconDirs: [resolve(process.cwd(), 'src/icons')],
      symbolId: 'i-[name]',
      customDomId: '__svg__icons__dom__',
    })
  ]
})

main.js 中注入生成 svg symbols 的方法:

// src/main.js
import 'virtual:svg-icons-register'

在做完以上各个步骤之后,body 中就会多出一个 svg 元素,里面就是 icons 目录下单体文件所对应的 symbols 。

然后,我们就可以创建 SvgIcon 组件了:

<!-- src/components/SvgIcon.vue -->
<template>
  <svg class="icon" :width="size" :height="size" aria-hidden="true">
    <use :xlink:href="`#i-${icon}`" :fill="color" />
  </svg>
</template>

<script setup>
defineProps({
  icon: {
    type: String,
    required: true
  },
  color: {
    type: String,
    default: '#fff'
  },
  size: {
    type: Number,
    default: 32
  }
})
</script>

可以在 main.js 中进行全局注册:

// src/main.js
import {createApp} form 'vue'
import App from '@/App.vue'
import SvgIcon from '@components/SvgIcon.vue'

const app = createApp(App)
app.component('SvgIcon', SvgIcon)

组件的使用:

<svg-icon icon="user" color="#f00" :size="64" />
<!-- icon 属性对应 icons 目录下 svg 文件名:例如,上述例子中 user 对应 icons/user.svg -->

后续如果 icons 需要扩充,只需要把新增的 svg 文件直接添加进 icons 目录即可。

  • 小程序

因为小程序的 wxml 不支持 SVG 直接渲染,只能通过 image 的 src 进行显示。此种显示的方式,最大的问题是如何更改 icon 的颜色不可以更改,所以需要对文件进行处理。

实现思路:svg 文件 => binary 字符串 => 替换 fill 属性

具体的实现方式:

<!-- components/SvgIcon/index.wxml -->
<view class="icon-wrapper" style="width:{{size}}rpx;height:{{size}}rpx;">
    <image class="icon" src="{{iconPath}}" mode="aspectFit"/>
</view>
/* components/SvIcon/index.wxss */
.icon-wrapper {
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
}

.icon {
    width: 100%;
    height: 100%;
}
// components/SvIcon/index.js
Component({
  properties: {
    icon: {
      type: String,
      required: true
    },
    color: {
      type: String,
      value: '#f00'
    },
    size: {
      type: Number,
      value: 32
    }
  },
  data: {
    base: 'icons/',
    iconPath: ''
  },
  lifetimes: {
    attached() {
      const { base } = this.data
      const { icon, color } = this.properties
      const filePath = `${base}${icon}.svg`
      const svgBinary = wx.getFileSystemManager().readFileSync(filePath, 'binary')
      const svgBase64 = `data:image/svg+xml,${encodeURIComponent(svgBinary.replace(/(#[a-fA-F0-9]{6})|(#[a-fA-F0-9]{3})/g, color))}`
      this.setData({
        iconPath: svgBase64
      })
    }
  }
})

然后,在 app.json 进行全局注册:

{
  ...,
  "usingComponents": {
    "svg-icon": "./components/SvgIcon/index"
  }
}

组件使用:

<svg-icon icon="user" color="#f00" size="{{64}}" />

(本文完)

本文由博客一文多发平台 OpenWrite 发布!

xiaofuyesnew
58 声望1 粉丝

coder一枚