# 矢量图标编辑器 **Repository Path**: vfb/vector-icon-editor ## Basic Information - **Project Name**: 矢量图标编辑器 - **Description**: 勇芳_矢量图标编辑器(可视化代码绘画编辑器),用尽量简短的字符串描述图标绘画,方便直接写入代码中,显示出漂亮的图标来。矢量图标无惧放大,软件中使用图标的上上选择。 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 4 - **Forks**: 0 - **Created**: 2025-06-23 - **Last Updated**: 2025-08-02 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 矢量图标编辑器 #### 介绍 矢量图标编辑器(可视化代码绘画编辑器),用尽量简短的字符串描述图标绘画,方便直接写入代码中,显示出漂亮的图标来。矢量图标无惧放大,软件中使用图标的上上选择。 ![输入图片说明](20250627211915.png) 视频演示 [https://v.douyin.com/jxLRBzbsl3o/](https://v.douyin.com/jxLRBzbsl3o/) #### 软件 - 一个简单原始的图像编辑软件,基本上实现了,参数输入调节,和 PS 一样 鼠标拖动节点调节。当然很多地方还需要改进,才能和 Illustrator 、Photoshop 等大牌软件操作上一致。尽量模仿它们的操作习惯。 - 需要安装 VisualFreeBasic 编程软件,最新的版本。就可以使用本软件源码。而且 VisualFreeBasic 中有图标显示的控件,都已经支持使用 矢量图标。 #### 用途 现在每个软件上都有图标,比方工具栏、菜单、按钮、标签等。传统的做法是制作或下载 ICO 图标,但是该图标,缩放后显示效果差,无法随时改变颜色显示,还要带很多图标文件,文件也比较大。很多缺点,于是“矢量图标”是更好的选择。 可是找遍全球,都没寻找到此类解决方案,只有“SVG”的矢量图形,我写过“SVG”解析,并使用 GDI 绘画出来,但因为“SVG”过于繁琐,计算量大,而且和 GDI无法对应,很多需要大量计算和翻译,而且每个图的字符数量非常大,作为图形是非常优秀的,而对于我们简单的图标来说,过于庞大,解析繁琐,代码执行效率低下,因为一个软件同屏可能显示 几十,也可能达到 几百个图标显示,那么SVG无法满足图标的需求。 需求实实在在,苦苦寻求几年,最后使用最字体作为图标,比方阿里那里的有大量的图标,找到图标,生成字体,然后软件中加载字体,最后显示文字方式显示出图标。但最大的缺点就是 过程麻烦,显示是单色的,无法使用多色。实在没办法,就自己创作专用的“矢量图标”。 ### 矢量图标优点和缺点 **优点** 很短的字符,就能表示一个图标,可以直接嵌入代码中使用。 直接和GDI对应,代码解析速度快,可以直接调用 GDI 的API 完成绘画。 **缺点** 刚开始缺少现成的图标,需要自己编辑。虽然我自己绘画了 100多个常用图标,熟练后,几分钟就能描绘一个,看到一个图标,点击截图,然后就可以在截图上面照着描,非常快。 ### 矢量图标字符串规范 - 绘画描述字符串结构,标记区分大小写,结构为:(颜色表)绘图元素+绘图元素+绘图元素+... - 颜色表 (FFFF0000,FF00E500,...) 16进制,GDI+ 的颜色 ARGB 值列表(最多16个颜色),可以没列表,就按照下面默认:主色黑FF000000,副色红FFFF0000,次色绿FF00FF00,蓝FF0000FF,黄FFFFFF00,青FF00FFFF,紫FFFF00FF,白FFFFFFFF - 绘图元素,用 "+"分隔,从左到右绘画,第1条画在最底面,最后1条最上面。 - 下面用到的:粗细、尺寸、坐标等数值都是相对于“WH”的千分比值,坐标从负1000到正2000,其它从0到2000, - “绘图元素” 结构为:第1字符是 abcdef..表示绘图类型,从第2个字符开始是绘图参数 - 参数结构为:,填充色,填充模式,闭合路径,折线拐角,线框色,线粗,x,y ............. - 由于直接使用10进制参数,造成字符个数比较长,为了压缩字符,使用了一下方法 - 参数都是数字,数字分为短数字和长数字 - 短数字: 从 0 到 16 ,用 字符 0123...@ ASCII 字符代码 48到64 表示 0 -16 - 长数字: -1000 到 2000 ,换成55进制,共3000,用2个字符表示,55*55=3025 ,字符“ABC...x” ASCII 字符代码 65到120 表示 0-55 - 编码:Chr(Int((a+1000) / 55), (a+1000) mod 55) ) - 解码: (asc(A,1)-65)*55+(asc(A,2)-65) - 1000 - 为了进一步压缩字符串,就对上面产生的进一步处理(不处理也不影响正常使用) - 处理1:对 重复 0 字符合成2个字符,如:00000 5个0 处理成 .5 代码:Chr(46, 个数 + 48) - 处理2:和上一个元素有相同,比方相同 5个, 处理成 *4 代码:Chr(42, 相同数 + 47) - 处理3:是上一个元素克隆,只是坐标偏移,那么最后坐标 %??? 代码:Chr(37,坐标数 + 48) & 偏移XY - 描绘线条 - 例题:"a00001@0000000[`XM`T]e" - 描绘矩形 - 例题:"b10000?XOWLYTYK" - 描绘椭圆 - 例题:"c100XOWLYTYK" - 描绘圆弧 (一个假想的圆位置和宽度高度) - 例题:"d00001@0000000[`XM`T]e09" - 描绘多边形 - 例题:"e10000050XOWLYTYK" - 描绘贝塞尔曲线 - 贝塞尔曲线 全部由贝塞尔组成,坐标最小4个,就是一个贝塞尔,后面一组是3个坐标,贝塞尔是4个参数,缺少的是第一个是前一组的最后一个参数。 - 例题:"f10000050XOWLYTYK" - 描绘曲线 - 例题:"g00101@0000000QUZ_Xb[^]MWO\[" - 描绘路径 - 例题:"h00001@0000000TdT[0VtWI" - 描绘文字 描绘文字 - 字体名和文字,由“&”开头,前一个数字参数为长度 - 例题:"i12TF2UA0000UkXG7&,中国" ### 矢量图标字符串解码算法 解码思路: 1. 先解出索引颜色列表,如果有的话,没有就用默认的,16进制GDI+颜色值,直接获取,没说明好说的 2. 本身参数全是数字,因此使用了一个数组变量,获取参数(文字特殊,也只是数字,后面会有解析) `Dim Cm() As Long` - 每个绘图是用 “+”字符分隔,我们先是用 VicoFt = InStr(VicoF, VIco, "+") 来分得到单独的绘图元素。 - 绘图元素,就是把字符串还原成数字的数组,用循环很简单的就可以了,以下简单的代码就解出来了。 ``` ReDim Cm(100) Cm(0) = Asc(vs, 1) '是绘画元素编号 '提取参数 ci = 1 vu = Len(vs) -1 For i = 1 To vu Select Case vs[i] Case 46 '. 包括多个0 If i + 1 < Len(vs) Then ci += vs[i + 1] -48 If ci > UBound(Cm) Then ReDim Preserve Cm(ci + 30) i += 1 End If Case 38 ' & 文字 If ci > UBound(Cm) Then ReDim Preserve Cm(ci + 30) Cm(ci) = i + 2 '表示文字开始位置,从1开始 i += Cm(ci -1) + 1 'Cm(ci-1) 是文字长度 Case 48 To 64 '短数值,从 0 -- 16 If ci > UBound(Cm) Then ReDim Preserve Cm(ci + 30) Cm(ci) = vs[i] -48 ci += 1 Case 65 To 120 '长数值,从 0 -- 55 需要2个字符组成 aa = vs[i] - 65 i += 1 If i <= vu AndAlso vs[i] >= 65 AndAlso vs[i] <= 120 Then bb = vs[i] - 65 Else bb = 0 End If If ci > UBound(Cm) Then ReDim Preserve Cm(ci + 30) Cm(ci) = aa * 55 + bb - 1000 '合成数值,55进制 ci += 1 End Select Next ``` 然后去对应参数调用 GDI 去绘画即可。 ### 矢量图标字符串编码算法 1. 每个绘图元素的参数,通过以下函数,把数字组成字符,拼贴成字符串,就可以了 ``` Function 整数转V数(nn As Long) As String '把数值转为 VICO 的55进制数字符串 If nn >= 0 And nn <= 16 Then '短数字 ,直接就是 0 -- 16 Return Chr(nn + 48) Else '长数字,55进制,有2个字符组成,可以表示 0--3000 。实际表示 -1000 到 2000 ,因此需要 +1000 处理。 Dim a As Long, b As Long a = nn + 1000 If a < 0 Then a = 0 If a > 3000 Then a = 3000 b = a Mod 55 a = Int(a / 55) Return Chr(a + 65, b + 65) End If End Function ``` 具体做法,参考源码。 我们的目标是简单,快速,虽然生成的字符串象是加密的。 第一代采用纯数字列表,但发现字符太长,比方 ``` ``` 第二代采用压缩方式,只用可显示字符, ``` "h00001@0000000TdT[0VtWI" ``` 假如使用全字符压缩,会得到更短的,预计可以比第二代减少 50% 的字符长度。但是嵌入我们的代码中不方便,于是就选择第二代的折中方案。