搭建自己的iconfont 字体图标库
使用到的技术
- nodejs
- node-egg
- mysql
- oss
最终支持className、unicode、Symbol 彩色图标类型
需求整理
- ui自主设计
- 图标上传
- 图标存储
- 图标库的下载引用
思考如何将svg 转成字体图标呢
- 经过font-carrier包,把svg图标转成字体,生成字体图标库(https://www.npmjs.com/package/font-carrier)
const initValue = 0xe000 // 相当于iconfont的Unicode
const font = fontCarrier.create()
const char = String.fromCharCode(initValue)
font.setSvg(char,res)
font.output({
path: '输出地址'
})
- 创建class 伪类图标
// iconfont 模板
let content = `
@font-face {
font-family: 'iconfont';
src: url('iconfonts.eot'); /* IE9*/
src: url('iconfonts.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
url('iconfonts.woff') format('woff'), /* chrome、firefox */
url('iconfonts.ttf') format('truetype'), /* chrome、firefox、opera、Safari, Android, iOS 4.2+*/
url('iconfonts.svg#uxiconfont') format('svg'); /* iOS 4.1- */
}
.iconfont {
font-family: "iconfont";
font-size: 16px;
font-style: normal;
}
`
const value = '\\' + initValue.toString(16).toUpperCase()
const name = className // icon的className
content += `
.icon-${name}::before {
content:'${value}'
}
3.彩色图标(其实就是把svg 放到了html中,利用id取值)
cheerio包nodejs中的JQ
const $ = cheerio.load('<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="0" height="0" style="display:none;"></svg>');
const file = item.icon
const svgNode = $(file);
const symbolNode = $("<symbol></symbol>");
symbolNode.attr("viewBox", svgNode.attr("viewBox"));
symbolNode.attr("id", item.className);
symbolNode.append(svgNode.html());
$('svg').append(symbolNode+'\n');
createjs($.html("svg"))
const createjs = (symbol) =>{
const js = `(function (win){
let listenerDOM = null;
const insertBefore = function (a, l) {
l.parentNode.insertBefore(a, l)
}
const complete = function () {
Loaded()
}
const Loaded = ()=>{
let contnet = document.createElement('div')
contnet.innerHTML =` + '`'+`${symbol}`+'`' + '\n' +
`symbol = null
contnet = contnet.getElementsByTagName('svg')[0]
contnet.setAttribute('aria-hidden', 'true')
contnet.style.position = 'absolute'
contnet.style.width = 0
contnet.style.height = 0
contnet.style.overflow = 'hidden'
contnet = contnet
const firstChild = document.body.firstChild
if(firstChild){
insertBefore(contnet, document.body.firstChild)
}else{
document.body.appendChild(contnet)
}
}
document.addEventListener
?
~ ["complete", "loaded", "interactive"].indexOf(document.readyState)
?
setTimeout(Loaded, 0)
:
(
listenerDOM = function() {
document.removeEventListener("DOMContentLoaded", listenerDOM, !1),
Loaded()
},
document.addEventListener("DOMContentLoaded", listenerDOM, !1)
)
:
document.attachEvent && (window.document.onreadystatechange = function() {
"complete" == window.document.readyState && (window.document.onreadystatechange = null, complete())
})
})(window)`
fs.writeFileSync(path.join(outputPath,'/iconfonts/iconfont.js'),js)
}
- 图标上传
4.1 数据库设计
4.1.1 为了每一个项目有单独自己的iconfont,所以需要设计一个项目的表
4.1.2 设计icons表,存储所有icon ,给每一个icon上设计一个项目id 的字段
4.2 需要兼容之前在阿里平台的iconfont (后面统一处理)
project_id: 属性那么项目,传项目id,
name: 需要在前端界面中展示图标的名称,
className: 用户使用className, 使用的iconfont,
unicode: 为了迁移之前的iconfont做准备
icon: icon字符串svg
- 下载
下载其实就上把上面所说的大包成zip,同事就可以使用了 - 兼容https://www.iconfont.cn中的icon
6.1 打开控制面板找到icon
6.2 找到相关icon容器,右击设置全局变量,然后map处理成想要的数据结构,跑数据上传