原本只是想给useragent插件换一些更清晰的设备图标,SVG自然成了首选。结果折腾着折腾着,就从纯色SVG一路研究到了渐变、高光,甚至开始琢磨那些只能“靠感觉硬调”的渐变坐标。很多以前以为只能在PS里完成的效果,后来发现其实直接写SVG代码也能实现,而且还挺有意思。文章目录纯色 SVG 图标渐变 SVG 图标Windows 11的图标QQ邮箱的图标IE的图标联想的图标

最近折腾了一下 useragent 插件里的设备图标,把常见设备的 PNG 基本都替换成了 SVG。最大的感受就是:在手机、Retina 屏这类高 DPI 设备上,SVG 的显示效果确实会清晰很多,边缘不会再有明显发虚的问题。

很多图标我都是直接在 iconfont上找的,毕竟现成资源比较多。不过也有不少设备品牌根本找不到合适的图标。

本着“没有就自己造”的原则,我发挥了一下主观能动性,并把这些图标的制作和优化分成了两个方向。

纯色 SVG 图标

像荣耀(HONOR)、OPPO、vivo、三星(SAMSUNG)这类品牌,如果直接使用完整的字母 Logo,在 useragent 这种小尺寸场景下实际显示会特别小,可读性并不好。后来我换了个思路:直接参考它们官网favicon来重绘图标。这样既能保留品牌辨识度,小尺寸下看起来也更加清晰。

先把图标保存为透明 PNG再通过 PNG 转 SVG 工具进行矢量化,比如 PNG to SVG 、 PNG转SVG

虽然这种方式生成的 SVG 精度会比手工绘制稍差一点,但用在 useragent 这种尺寸很小的设备信息展示里,其实已经完全够用了。

渐变 SVG 图标

真正比较麻烦的,其实是带渐变色的图标。iconfont 也不支持上传有渐变代码的SVG图标。

很多在 iconfont 上看起来像“渐变”的图标,本质上其实是多个纯色色块拼接出来的。尺寸小的时候还好,但放大之后会发现过渡并不自然,有些甚至会出现明显的断层感。

后来想着,既然 SVG 本身支持渐变,那不如直接用代码实现。

AI 很快给了答案:使用 defs 配合 linearGradient 定义渐变。

例如:

defs linearGradient stop / stop / stop / /linearGradient /defs

这里的 defs 用来存储可复用的图形元素、样式、滤镜、渐变等内容,而 linearGradient 则定义线性渐变。

其中:x1 y1 :渐变起点;x2 y2 :渐变终点

本质上,它们定义的是“渐变线”的方向。

常见方向大概如下:

然后通过 来引用对应的渐变。

其中 gradient 就是前面定义的 id,当然也可以定义多套渐变,分别用于不同路径。

Windows 11的图标 svg defs linearGradient stop / stop / stop / /linearGradient /defs path /path /svg QQ邮箱的图标

它的图标则更有意思,渐变层次很明显,而且由 3 段路径组成,中间两块区域相对更小。所以我最后定义了两套渐变色:

外层使用跨度较大的渐变中间区域使用颜色跨度更短的渐变

这样缩小之后,整体的颜色过渡会自然很多,不会出现“中间突然变色”的情况。

svg defs linearGradient stop / stop / stop / /linearGradient linearGradient stop / stop / stop / /linearGradient /defs path /path path /path path /path /svg IE的图标 svg defs radialGradient stop / stop / stop / /radialGradient /defs path /path path /path /svg

IE8的图标,他的扩展不是从中心发散的,有一些偏下,类似椭圆。椭圆渐变在 SVG 中没有直接的 ellipseGradient 标签,需要用 radialGradient + 配合不同的 rx/ry 来实现,或者通过 gradientTransform 拉伸。

svg defs radialGradient stop / stop / stop / stop / /radialGradient /defs path /path path /path /svg 联想的图标

它是一个比较典型的案例,favicon 本身带有高光效果,而这个高光并不是简单的“左上到右下”线性渐变。

一开始我直接用:x1="0%"

虽然方向对了,但高光位置始终不自然。后来才发现,需要配合 来使用真实坐标系控制渐变位置。

当时我的 SVG 视窗定义是。在实际调试中,我靠着感觉硬调出了一组参数:x1="0%"。视觉效果虽然完美对齐了,但具体怎么计算出来的,当时我脑子里也没什么头绪。

svg defs linearGradient stop / stop / stop / stop / /linearGradient /defs path /path /svg

理论上来说,x2 和 y2 似乎应该和 viewBox 有一定关系,但实际调的时候我发现并没有一个特别固定的公式。

尤其是一些带高光、拟物感或者品牌特殊视觉风格的 Logo,很难单纯通过数学计算直接得出“正确答案”,最后往往还是需要靠肉眼慢慢调整。

不过也正因为这样,SVG 渐变其实比想象中灵活很多。

以前总觉得 SVG 只是“矢量图”,真正折腾之后才发现,它更像是一套完整的绘图语言。很多过去只能在 PS 里做的效果,现在直接写代码也能实现,而且还能无限缩放、不失真。

对于 useragent 这种本身图标尺寸很小、但显示场景又特别多的插件来说,SVG 确实是个很合适的方案。