知識
不管是網(wǎng)站,軟件還是小程序,都要直接或間接能為您產(chǎn)生價值,我們在追求其視覺表現(xiàn)的同時,更側(cè)重于功能的便捷,營銷的便利,運營的高效,讓網(wǎng)站成為營銷工具,讓軟件能切實提升企業(yè)內(nèi)部管理水平和效率。優(yōu)秀的程序為后期升級提供便捷的支持!
如何在微信小程序中使用多色icon
發(fā)表時間:2021-3-15
發(fā)布人:葵宇科技
瀏覽次數(shù):102
背景
在微信小程序開發(fā)過程中難免會遇到需要使用多色icon的場景,項目中的icon一般存放在iconfont上。
iconfont有三種引用方式(參考 https://www.iconfont.cn/help/detail?spm=a313x.7781069.1998910419.d8cf4382a&helptype=code )
- unicode引用:因為是字體,所以不支持多色
- font-class引用:本質(zhì)上還是使用的字體,所以多色圖標還是不支持的
- symbol引用:支持多色,使用svg渲染
但是微信小程序iconfont并不支持 標簽,只支持以background形式渲染.svg文件?;诖耍梢允褂肗ode編寫腳本,將iconfont項目里的多色icon下載到項目中,生成
.arrow-down--colorful {
background: url('./arrow-down.[hash].svg');
}
// 或者有CDN的可以
.arrow-down--colorful {
background: url('//[cdn]/imgs/arrow-down.[hash].svg');
}
步驟
步驟一、 上傳icon至iconfont
注意在上傳時,帶顏色的圖標需要有固定后綴來區(qū)分。例如普通icon為icon-name,則帶顏色的icon需要為icon-name--colorful
步驟二、腳本下載icon_**.css
使用Node下載項目對應的css腳本,格式為:
@font-face {font-family: "iconfont";
src: url('//at.alicdn.com/t/font_**.eot?t=1571134856668');
src: url('//at.alicdn.com/t/font_385238_**.eot?t=1571134856668#iefix') format('embedded-opentype'),
url('data:application/x-font-woff2;**') format('woff2'),
url('//at.alicdn.com/t/font_**.woff?t=**') format('woff'),
url('//at.alicdn.com/t/font_**.ttf?t=**') format('truetype'),
url('//at.alicdn.com/t/font_385238_**.svg?t=**#iconfont') format('svg');
}
.iconfont {
font-family: "iconfont" !important;
...
}
.icon-name:before {
content: "\e600";
}
.icon-name--colorful:before {
content: "\e653";
}
刪除其中無用的font格式,以及帶--colorful的css定義。使用腳本將其格式化為
@font-face {font-family: "iconfont";
src: url('data:application/x-font-woff2;**') format('woff2');
}
.iconfont {
font-family: "iconfont" !important;
...
}
.icon-name:before {
content: "\e600";
}
步驟三、腳本下載icon_**.js
使用Node下載項目對應的js腳本,格式為:
!function(o){var t,l='<svg><symbol id="icon-name” viewBox="0 0 1024 1024"><path …>…path>symbol>symbol id="icon-name—colorful” viewBox="0 0 1024 1024"><path …>…path>symbol>svg>’,…}(window);
提取出其中帶顏色(id以--colorful結(jié)尾)的
"..." fill="..." >path><path d="..." fill="..." >path>
注意:如果步驟一不能實現(xiàn)按照--colorful區(qū)分是否是多色icon,則需要分析各個path的顏色是否一致來區(qū)分是否是多色。
拼接上 標簽
function getHash(cont: string) {
return cryptoNode
.createHash('md5')
.update(cont)
.digest('hex')
.substr(0, 8);
}
步驟四、生成hash值及圖片文件
最終得到的svgStr的hash值
function getHash(cont: string) {
return cryptoNode
.createHash('md5')
.update(cont)
.digest('hex')
.substr(0, 8);
}
使用hash值是為了避免更換icon但是不換名字的場景
生成本地圖片文件
const hash = getHash(svgStr);
const fileName = `${iconId}.${hash}.svg`;
const filePath = `${stylePath}${fileName}`;
fs.writeFileSync(filePath, svgStr);
步驟五、將圖片上傳至CDN并刪除本地文件(可選)
如果有CDN資源可以將圖片上傳至CDN,可以節(jié)約打包出的項目體積
uploadFileToCDN(filePath);
/** 將pathWithHash文件上傳到CDN */
async function uploadFileToCDN(pathWithHash: string) {
return new Promise((resolve, reject) => {
exec(
`${此處為上傳至CDN的命令行}`,
(error: any, stdout: any, stderr: any) => {
if (error) {
console.error(`exec error: ${error}`);
reject(error);
return;
}
resolve('');
/** 刪除文件 */
fs.unlinkSync(pathWithHash);
}
);
});
}
步驟六、生成完整的css內(nèi)容并寫入本地
給步驟二的css文件拼接上帶顏色圖片的css內(nèi)容
@font-face {font-family: "iconfont";
src: url('data:application/x-font-woff2;**') format('woff2');
}
.iconfont {
font-family: "iconfont" !important;
...
}
.icon-name:before {
content: "\e600";
}
.icon-name--colorful:before {
background: url('cdnUrl');
}
并寫入本地
fs.writeFileSync(cssPath, fileContent.replace(/"/g, "'"), 'utf8');
完整的腳本文件示例
const http = require('http');
const cryptoNode = require('crypto');
const { exec } = require('child_process');
const xml2js = require('xml2js');
const fs = require('fs');
const config = {
url: '//at.alicdn.com/t/font_***.js'
};
// 上傳至CDN后的前綴
const cdnPath = '***';
/** 生成的css文件path */
const cssPath = 'src/styles/iconfont.scss';
const stylePath = 'src/styles/';
const { parseString } = xml2js;
// 替換iconfont.scss
const iconfontUrl = config.url.replace(/.*\/\//, 'http://');
const iconfontUrl_css = iconfontUrl.replace('.js', '.css');
let fileContent = '';
type IPath = {
$: {
[key: string]: string;
};
};
type ISymbol = {
$: {
id: string;
viewBox: string;
};
path: IPath[];
};
/** 讀取css文件,去掉遠程連接 */
async function generateFile() {
const cssData = http://www.wxapp-union.com/await readRemoteFile(iconfontUrl_css);
fileContent = cssData.replace(/[^,;]*at.alicdn.com.*\*\//g, '');
// 替換掉woff
fileContent = fileContent.replace(/[^)]*at.alicdn.com.*\),/g, ';');
// 替換掉colorful
fileContent = fileContent.replace(/[^}]*colorful[^}]*}/g, '');
// 替換src
fileContent = fileContent.replace('url(', 'src: url(');
// 加換行
fileContent = fileContent.replace('{font-family', '{\n font-family');
// 加換行
fileContent = fileContent.replace(') format(', ')\n format(');
// 去除最后一個換行
fileContent = fileContent.replace(/\n$/, '');
// 有顏色的圖標生成background: url('cdnUrl')
const fontXml = await fetchXml(iconfontUrl);
fontXml.svg.symbol.forEach((item: ISymbol) => {
const iconId = item.$.id;
if (/colorful/.test(iconId)) {
let svgStr = '';
item.path.forEach((path: IPath) => {
const keys = Object.keys(path.$);
let attrStr = '';
keys.forEach(k => {
attrStr += `${k}="${path.$[k]}" `;
});
svgStr = `${svgStr}${attrStr} >`;
});
svgStr = `${svgStr}`;
const hash = getHash(svgStr);
const fileName = `${iconId}.${hash}.svg`;
const filePath = `${stylePath}${fileName}`;
fs.writeFileSync(filePath, svgStr);
uploadFileToCDN(filePath);
svgStr = `\n.${iconId} {\n background: url('${cdnPath}${fileName}');\n}\n`;
fileContent += svgStr;
}
});
}
function getHash(cont: string) {
return cryptoNode
.createHash('md5')
.update(cont)
.digest('hex')
.substr(0, 8);
}
async function uploadAndUpdate() {
// 寫文件
fs.writeFileSync(cssPath, fileContent.replace(/"/g, "'"), 'utf8');
}
generateFile().then(() => {
uploadAndUpdate();
});
function readRemoteFile(remoteUrl: string): Promise<string> {
let _data = http://www.wxapp-union.com/'';
return new Promise(resolve => {
http.get(remoteUrl, (res: any) => {
//數(shù)據(jù)
res.on('data', function(chunk: string) {
_data += chunk;
});
res.on('end', function() {
resolve(_data);
});
});
});
}
async function fetchXml(
url: string
): Promise<{
svg: {
symbol: ISymbol[];
};
}> {
const data = http://www.wxapp-union.com/await readRemoteFile(url);
const matches = String(data).match(/');
return new Promise((resolve, reject) => {
parseString(`${matches ? matches[1] : ''}`, (err: any, result: any) => {
if (err) {
reject(err);
} else {
resolve(result);
}
});
});
}
/** 將pathWithHash文件上傳到CDN */
async function uploadFileToCDN(pathWithHash: string) {
return new Promise((resolve, reject) => {
exec(`${此處為上傳至CDN的命令行}`, (error: any, stdout: any, stderr: any) => {
if (error) {
console.error(`exec error: ${error}`);
reject(error);
return;
}
resolve('');
/** 刪除文件 */
fs.unlinkSync(pathWithHash);
console.log(`stdout: ${stdout}`);
console.error(`stderr: ${stderr}`);
});
});
}
再在 package.json
中的scripts中配置
"icon": "ts-node scripts/iconfont.ts"
則每次更新iconfont后,更新對應的url,再運行 npm run icon
即可
相關案例查看更多
相關閱讀
- 大理小程序開發(fā)
- 北京小程序開發(fā)
- 網(wǎng)站建設需要多少錢
- 正規(guī)網(wǎng)站建設公司
- 小程序定制
- 云南微信小程序開發(fā)
- 搜索引擎優(yōu)化
- 云南軟件公司
- 網(wǎng)站排名優(yōu)化
- 云南etc小程序
- 云南省住房建設廳網(wǎng)站
- 云南網(wǎng)站建設
- 小程序
- 網(wǎng)站建設服務公司
- 云南網(wǎng)站建設制作
- 云南小程序開發(fā)
- 云南小程序開發(fā)制作
- 前端技術
- 百度推廣
- 網(wǎng)站優(yōu)化公司
- 云南網(wǎng)站制作
- 云南省建設廳網(wǎng)站
- 紅河小程序開發(fā)
- asp網(wǎng)站
- 云南花農(nóng)小程序
- 云南建設廳網(wǎng)站
- 云南網(wǎng)站維護
- 云南網(wǎng)頁制作
- 百度小程序
- 網(wǎng)站建設哪家強