简介
最近在进行微信小程序开发的时候使用到了iconfont的彩色图标,彩色图标是SVG格式的。在小程序中使用SVG的问题就不做过多说明了,网上亦有多种方案,下面分享下个人实现的方案。
思路
- 在
image标签的src属性使用data类型URL - 从iconfont中获取图标转换成dataUrl,并以js的方式存放
- 创建一个自定义组件,在组件中使用图标
实现
1. 如何获取图标
因为iconfont中支持按项目的方式将图标整体打包,在网页中提供了体验用的cdn地址,我们需要下载图标时可直接从该地址中下载。
方法: 在项目中选中 Symbol,点击查看在线图标 即可获取在线链接,复制下面的cdn地址,用于后续下载。
2. 下载并生成图标js文件
为了方便以后每次操作,我们编写一个node程序,用于下载并生js文件,下面提供程序代码:
//从命令行参数中读取url,保存目录信息
let [, , url, saveDir] = process.argv
const https = require('https')
const fs = require('fs')
const path = require('path')
saveDir = saveDir || './'
//下载
function download(url) {
return new Promise((resolve, reject) => {
https.get(`https:${url}`, res => {
const data = []
console.log("开始下载...");
res.on('data', chunk => {
data.push(chunk)
})
res.on('end', chunk => {
console.log("下载完成...");
const content = Buffer.concat(data).toString()
resolve(content);
})
}).on('error', (e) => {
reject(e);
});
})
}
//生成js文件
function createData(icons) {
const file = [];
const iconList = [];
icons.forEach(icon => {
iconList.push(`"${icon.name}":"${icon.url}"`)
})
file.push("const icons = { \n", iconList.join(",\n"), "\n}\n")
file.push("export default icons")
return file.join('')
}
//保存文件
function save(data, name, dir) {
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir, { recursive: true })
}
const d = new Uint8Array(Buffer.from(data, 'utf-8'));
const fullPath = path.resolve(dir, name)
fs.writeFile(fullPath, d, (err) => {
if (err) throw err;
console.log('保存成功!');
console.log('保存路径:' + path.resolve(fullPath));
});
}
async function main() {
const content = await download(url)
//分析js内容,根据内容,获取里面svg图标部分数据
const [, symbolsContent] = content.match(/<svg>(.*)<\/svg>/)
//将多个symbol 拆分
const symbols = symbolsContent.match(/<symbol (.*?)<\/symbol>/g)
const icons = []
symbols.forEach(sym => {
//获取图标id
const [, id] = sym.match(/ id="(.*?)" /)
//使用base64 存放图标数据,此处选用了base64,若是使用原生svg保存,请注意对内容进行 urlencode,若有需要,可自行修改代码
const svg = 'data:image/svg+xml;base64,' + Buffer.from(sym.replaceAll('symbol', 'svg ').replace(/^<svg/, '<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"'), 'utf-8').toString('base64')
icons.push({
name: id,
url: svg
})
});
//生成js文件
const data = createData(icons)
//创建 assets下的资源目录
save(data, path.basename(url), saveDir)
}
main()
代码主要提供了一种用于下载图标并生成对应js的简单方法,若有其他需求或其他思路可自行修改。
将上面代码保存为 loadIconFont.js 存放于自己喜欢的路径。
执行 node loadIconFont.js //at.alicdn.com/t/c/font_test.js ./ 等待片刻即可在当前目录中获得一份生成好的js文件。
参数分别为 node loadIconFont.js [图标在线连接地址] [保存目录]若使用npm,亦可将该命令写入 package.json 中,此处不做介绍。
node ./loadIconFont.js //at.alicdn.com/t/c/font_test.js ./assets/iconfont
开始下载...
下载完成...
保存成功!
保存路径:F:\miniprogram\assets\iconfont\font_test.js
生成后的font_test.js内容格式为:
const icons = {
"icon-ppt":"data:image/svg+xml;base64,PHN2ZyAgeG1sb...",
"icon-video":"data:image/svg+xml;base64,PHN2ZyAgeG1sbnM9Imh0d...",
"icon-unknown":"data:image/svg+xml;base64,PHN2ZyAgeG1sbnM9I..."
}
export default icons
对应格式为: 图标名称 : svg,其中图标名称根据 iconfont项目中的id生成,即:
此时已经完成了图标的下载生成工作,将下载下来的文件保存到自己喜欢的资源目录中,此处保存的目录为项目下的 ./assets/iconfont/font_test.js。
3. 创建一个组件,在组件中使用图标
为了更简单地使用图标,可以选择创建一个组件,在组件中使用它,而图标数据,这里选择将其存入到全局数据app.globalData.iconfonts属性中,下面为参考代码
在小程序项目中创建一个叫 svg-icon 的组件,wxml,js 内容如下
components/svg-icon.wxml
<!--components/svg-icon.wxml-->
<view>
<image src="{{useSrc?src:projects[project][name]}}" style="width:{{width}};height: {{height}};" />
</view>
components/svg-icon.js
// components/svg-icon.js
const app = getApp()
Component({
/**
* 组件的属性列表
*/
properties: {
name:{
type: String
},
project: String,
width:{type:String,value:"1rem"},
height:{type:String,value:"1rem"},
src: String,
useSrc: Boolean //让其适应不使用全局图标文件的控制
},
/**
* 组件的初始数据
*/
data: {
//图标以不同project的形式进行划分
projects:app.globalData.iconfonts
},
/**
* 组件的方法列表
*/
methods: { }
})
定义完成组件后,还需要在app.js中导入图标文件,代码如下:
app.js
//import 图标文件
import {default as font_test } from './assets/iconfont/font_test'
App({
globalData:{
iconfonts:{
"icon-project-1":font_test //图标文件作为一个项目存放于iconfonts属性中,使用 "icon-project-1" 作为项目名称
},
},
})
4. 如何使用
- 在page中添加组件
{
"usingComponents": {
"svg-icon":"/components/svg-icon"
}
}
- 使用组件
<svg-icon name="icon-ppt" project="icon-project-1" width="1.5rem" height="1.5rem" />
组件属性:
| 属性名称 | 是否必须 | 说明 |
|---|---|---|
name | 是 | 图标名称 |
project | 是 | 图标项目名称 |
width | 否 | 宽 |
height | 否 | 高 |
src | 否 | 组件使用自定义 src ,仅 use-src 为 true 时有效 |
use-src | 否 | 是否使用src属性 |
5. 效果
总结
到此,实现了在微信小程序中使用iconfont的彩色svg图标的目的,上述代码由于具体情况不尽相同,所以仅作参考,有需要的朋友可以自行进行修改,适应自己的项目。