在开发过程中,我们免不了会使用图片等素材来引导用户操作,或优化我们产品的体验。我们常用的图片格式有 SVG/PNG/JPG/JPEG/WebP 等,但由于资源加载、图片大小、缩放是否失真以及使用便捷性, SVG 已经成为了当下前端开发的宠儿?
“沉舟侧畔千帆过,病树前头万木春”,前端发展到现在,IconFont 似乎成为了一个当下还算不错的解决方案,我们可以像操作字体一样使用 color/font-size
等样式来控制我们想要的 icon 颜色及大小,同时缩放不会失真的矢量图特性以及较小的文件大小也为其锦上添fā?
但我们平时的 SVG 素材都是 UX 给我们导出,或者直接从各种 UI 库中导入的,这当然能满足我们大部分的需求,要知道 Zeplin/Figma 这些工具导出的 icon 实现都是固定的,比如我们要一个矩形 icon,实现方式可能有很多种,但这些工具导出的内容有且只有一种,这就难免会遇到一些尴尬的场景。
不得不手撸?♀️
在我们小程序的个人中心页面中有一个发票的 icon,在开发者工具上正常显示的它,在真机上却“伤心地模糊”了,并且只在 iOS 上才会模糊(就NM离谱),如下:
因为截图原因,所以第一个订单 icon 显得有些模糊,但相比之下大家应该可以发现第二个发票 icon 中间的两个横杠模糊地更加明显!原本以为是切图原因的我又反复切了好次,发现并没什么卵用,于是乎~不得不看一眼 SVG 实现,然后发现了一个神奇的东西 <mask>
?♀️自己没有深究其原理,猜测可能是因为小程序对 SVG 的 mask element
支持不太好,所以才导致这个问题,当把 mask
删掉之后,我终于“看清了它的脸”!虽然“脸”看清了,可 icon 的样式都变了,但从 Figma 上导出的 icon 就是这样,所以我只能选择手撸了!
撸前热身?♂️
这个小小的 icon 主要由一个圆角矩形,两个半圆和两条横杠组成(原谅我如此苍白的描述,因为我确实描绘不出它的美)?
在 SVG 中,我们经常看到一个元素 <g>
,这个元素理解起来很简单:g
下的所有子元素都会继承 g
上的属性。比如我们绘制两个圆:
<svg height="24" width="24" xmlns="http://www.w3.org/2000/svg">
<g fill="cyan" stroke="yellow" stroke-width="1">
<circle cx="1" cy="1" r="10" />
<circle cx="12" cy="12" r="6" />
</g>
</svg>
复制代码
效果如下:
两个圆形都继承了 g
的 fill/stroke/stroke-width
属性(灰色边框是手动给 img
元素添加的),是不是很简单?
除了 <g>
,我们还常见一个元素就是 <path>
,path
中有个属性叫做 d
(draw 的缩写),d
中的内容看了更是头大!不要慌,让我来带你梳理一下?
path
元素很好理解,就是绘制我们定义的制定路径的图形(这个路径可以类比 PhotoShop 中的路径);而 d
就是绘制路径的指令,d
属性中经常看到 m/l/h/M/L/H
等各种字母并且大小写还不相同,首先你需要知道的是 每个字母都是一个指令,其后跟的就是要绘制的位置,小写的字母都是相对位置(relative),大写的字母都是绝对位置(absolute)。下面我们通过一个例子来理解:
<path
fill="none"
stroke="cyan"
stroke-width="1"
d="M 1 1
L 10 10
V 1
H 6"
/>
复制代码
<path
fill="none"
stroke="cyan"
stroke-width="1"
d="M 1 1
l 9 9
v -9
h -4"
/>
复制代码
上面我分别使用 相对指令 和 绝对指令 绘制了两个一样的图形,绝对指令我们可以理解为 “移动到”,相对指令则可以理解为 向哪儿移动多少。
那么用这种理解我们来映射到上面的两个例子中:
?1⃣️:画笔移动到 ,绘制一条从 到 的线段,绘制一条从 到 的线段,绘制一条从 到 的线段;
?2⃣️:画笔移动到 ,绘制一条从 沿 和 方向各增加 的线段(即 ),沿 轴负方向移动 并绘制相应线段(即 ),沿 轴负方向移动 并绘制相应线段(即 )。
怎么样,这样一看是不是很简单?下面简单介绍一下 d
的常用指令:
指令 | 参数 | 含义(, 分别代表当前画笔位置) |
---|---|---|
m | 根据当前画笔位置沿 轴移动 个单位,沿 轴移动 个单位, | |
M | 将画笔移动到 | |
l | 绘制一条从 到 的线段 | |
L | 绘制一条从 到 的线段 | |
h | 绘制一条从 到 的线段 | |
H | 绘制一条从 到 的线段 | |
v | 绘制一条从 到 的线段 | |
V | 绘制一条从 到 的线段 |
当然,d
中还有其它指令比如绘制 贝塞尔曲线 等,更多请了解:developer.mozilla.org/en-US/docs/…
不撸了,直接结束?
说了上面的内容,再来绘制发票 icon 就迎刃而解了,就讲怎么了直接贴代码:
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<g fill="#fff" stroke="#000" stroke-width="1.5">
<rect
x="3"
y="5"
rx="1"
ry="1"
width="20"
height="14"
fill="none"
/>
<path d="M8.5 10.5h7m-7 3.5h5"/>
<path d="M2.7 9a.5.5 0 1 1-.1 6m20.9-6a.5.5 0 1 0 0 6" />
<path stroke="none" d="M0 9.5h3v5H0zm23 0h3v5h-3z"/>
</g>
</svg>
复制代码
看下效果如何:
删去了 mask
在小程序中也能正常显示了:
细心的读者可能发现上面多了一个 viewBox
属性,该属性允许指定一个给定的一组图形伸展以适应特定的容器元素,也就是当我们设置 icon 大小时,svg
也会跟随我们设置的尺寸相应伸缩不会被裁减。各位可以试一下删去这个属性,然后使用 CSS 将 icon 的尺寸缩小,该 icon 会被裁掉。
到现在,我们的 icon 就已经画好了,但还没结束~我们想使用 CSS 的 color
来设置 icon 的颜色,这个问题很简单,CSS 中有个 currentColor
我们把 SVG 的 stroke
值设为 currentColor
然后在父元素设置 color
即可;而使用 font-size
来控制 icon
大小也只需要将 svg
的 width
和 height
的值设为 1em
即可:
.container {
color: red;
font-size: 48px;
}
复制代码
<div class="container">
<svg width="1em" height="1em" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<g fill="#fff" stroke="currentColor" stroke-width="1.5">
<rect
x="3"
y="5"
rx="1"
ry="1"
width="20"
height="14"
fill="none"
/>
<path d="M8.5 10.5h7m-7 3.5h5"/>
<path d="M2.7 9a.5.5 0 1 1-.1 6m20.9-6a.5.5 0 1 0 0 6" />
<path stroke="none" d="M0 9.5h3v5H0zm23 0h3v5h-3z"/>
</g>
</svg>
</div>
复制代码
看下效果:
不过如此,索然无味!
—- 到此结束,这次还是不闲扯,我要做一个沉稳的 Boy —-