本文是 基于Vite+AntDesignVue打造业务组件库 专栏第 4 篇文章【Web 中的字体和 SVG 图标,你了解多少?】,我们接着上篇的字体图标组件实战,继续探索图标的另一个展现形式 —— SVG 。在开发 SVG 图标组件之前,还有一些问题我们必须搞清楚!
不能盲目地开发组件,我们可以先问问自己:既然有了字体图标,为什么还需要 SVG 图标呢?
在回答这个问题之前,我们还需要了解字体的一些基础知识,免得在具体应用时一知半解。
我们首先来看一下计算机字体有哪几种大的分类:
引自维基百科 Computer_font:
There are three basic kinds of computer font file data formats:
- Bitmap fonts consist of a matrix of dots or pixels[1] representing the image of each glyph in each face and size.
- Vector fonts (including, and sometimes used as a synonym for, outline fonts) use Bézier curves[2], drawing instructions and mathematical formulae to describe each glyph, which make the character outlines scalable to any size.
- Stroke fonts use a series of specified lines and additional information to define the size and shape of the line in a specific typeface, which together determine the appearance of the glyph.
image.png
Type 1, Type 3 都是 Adobe 搞的;TrueType 是苹果搞出来对抗 Adobe 的,后面又许可微软加入一起用;最后微软又联合 Adobe 搞了 OpenType(可以理解为 Type 1 和 TrueType 的超集),纯纯的都是商业竞争啊!
.ttf 扩展名表示常规 TrueType 字体或具有 TrueType 轮廓的 OpenType 字体。
.woff 是 OpenType 字体或者 TrueType 字体,由于是 web 专用字体,采用了 zlib 压缩。woff 由 Mozilla 基金会、Opera Software和微软于 2010年4月向万维网联盟(W3C)提交, 在2012年12月13日成为了 W3C 推荐标准,woff2 由谷歌负责推进,改进了压缩方案,于2018年3月成为了 W3C 推荐标准,是未来 web 字体的发展方向。
下图引用了发明专利《一种笔划矢量字库的存取方法》的附图,侵删!
左边是笔画字体,右边是轮廓字体。
image.png
位图字体的优点在于它相对于其他字体在制作、渲染等方面更简单,速度也更快;其最大的缺陷是不能自适应各种分辨率的显示设备,同时在展示是否粗体、是否斜体、不同字号时都需要一套单独的字形光栅图像,这是乘法级的存储冗余,比较浪费存储空间(虽然也可以通过算法调整变换出字体变体,但是比较耗费性能)。虽然有这些缺陷在,但是在早期计算机性能较弱的情况下,位图字体显得非常合时宜,有着不可替代的地位。
image.png
随着计算机性能(算力、渲染等)的提升,位图字体的地位开始受到矢量字体的挑战,在需要任意弹性伸缩展示字形的场景下,矢量字体成了绝佳的选择;而位图字体则活跃在一些需要考虑速度、简单程度、硬件性能等因素的场景下,例如嵌入式设备、操作系统终端控制台、点阵打印机等。
了解了这些字体知识后,问题来了,Web 网页中我们常用的的字体都是什么类型的字体?
直觉告诉我们,好像是矢量字体,因为伸缩网页时,字还是很清晰,没有出现锯齿。
事实确实如此,点阵字体是计算机早期采用的字体,80年代开始,矢量字体就慢慢流行了起来,我们现在在网页中看到的基本上都是矢量字体。
字体有很多种,但是能直接用在 Web 中的不多,因为不能保证用户的电脑中安装了指定的字体。所以指定font-family
时通常考虑使用 Web 安全字体,保证各个操作系统、新旧版本、英文中文、emoji 等都能兼顾。
font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Ubuntu, Cantarell, "Helvetica Neue", Arial, "Noto Sans", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
既然 Web 字体基本上都是矢量字体,字体图标基本上用的也是.ttf
, .woff
, .woff2
等矢量字体,看起来没什么缺点,那么为什么 SVG 图标慢慢成为了各大网站的首选呢?
首先,字体是一种资源,如果字体加载失败,字体图标也就会渲染失败,可能会出现“小方格”。并且,如果由于网络等原因导致字体加载较慢,可能会出现占位抖动的情况(采用Base64内联字体会解决这个问题)。
image.png
而 SVG 是 HTML 文档内联的内容,渲染上会更可靠一点。
其次,字体图标并不支持彩色图标,即便现在彩色字体在 Web 中慢慢有了一些声音(iconfont 平台也支持了彩色字体图标),但是兼容性还有一些欠缺,在生产使用时还需要慎重考虑。而 SVG 本身是通过 XML 描述绘图指令,在绘图细节上控制力更强,天然支持彩色!不过随着未来 Web 彩色字体的普及,这方面也将不再是字体图标的劣势。
SVG 图标可以支持更丰富的表现能力,比如滤镜、动画等,同时也支持 DOM 操作,这些是字体图标比不了的。
字体图标的可访问性并不友好。字体图标是通过伪元素实现,比 SVG 的可访问性要差一些,SVG 内部可以使用title
和desc
标签描述信息,这无论对 SEO 还是无障碍阅读来说都显得更合适。
在图标数量很多时,SVG 图标的优势更为明显,SVG 支持按需使用。而字体图标的图标和图标之间耦合在一个字体文件中,这会导致最终的字体文件很大。
但也不是说字体图标就一无是处,字体图标在浏览器兼容性方面要更胜一筹,不过在“IE 已死”的局面下似乎也无关痛痒(老系统例外)。
总的来说,字体图标和 SVG 图标都有各自的优势,并不是说哪个一定比另一个优秀,我们可以结合实际场景来考虑选用。
@ant-design/icons-vue
提供的图标单组件。我们先尝试一下 SVG Sprite 的方式。
SVG Sprite 是先有 symbol,再通过 use 去引用。
The
<symbol>
element is used to define graphical template objects which can be instantiated by a<use>
element.
symbol 标签是用来定义图形模板对象的,但是不会直接渲染,需要通过 use 标签去实例化。
image.png
上图就是 SVG symbol 的大致结构,可以发现最外层的 svg 下面是一个 defs 标签。
The
<defs>
element is used to store graphical objects that will be used at a later time. Objects created inside a<defs>
element are not rendered directly。
在SVG 中,可复用的内容定义在 defs 下面,并不局限于 symbol。
image.png
symbol 也不强制放在 defs 下面,直接放在 svg 标签下也可以,因为它本身就是模板的含义,不会直接渲染。
我们还可以发现,每个 symbol 上都有一个属性 id,而这个 id 将成为 use 标签引用的依据,xlink:href
通过#
加 id 的方式就可以引用对应的 symbol。
image.png
了解这些知识后,我们应该清楚,要实现 SVG Sprite 组件,第一步是要生产出 symbol 内容。
UI 交付给前端的一般是一个个独立的 SVG 文件,那么怎么把这些独立的 SVG 文件变成我们想要的 symbol 呢?
这涉及到文件操作,如果用 nodejs 实现,必然离不开 fs 模块相关的 api,基本的原理就是读文件的字符串内容,然后做拼接处理,输出一个字符串,这个字符串最终可以通过 innerHTML 方式插入到 HTML 文档流中。
如果你的图标类的 SVG 文件都是放在项目工程中的,那么可以选用svg-sprite-loader(webpack 体系)和直接把这部分工作做好,剩下的事情就是封装组件。
Vite 中也可以实现类似的插件,大家按 vite svg sprite 等关键词去搜一搜就能找到很多。
如果我们使用的是 iconfont,也可以直接用 iconfont 提供的脚本。通过script
标签引入这个 js 文件后,会自动创建相关的 SVG symbol。
image.png
剩下的工作就是把 use 的使用封装到组件中,让业务调用变得简单。
基本逻辑捋清楚了,我们来编码实现一下。
为了和字体图标组件区分开,我们把上节中实现的字体图标组件
Icon
重新命名为IconFont
,而本次要实现的 SVG 图标组件就叫做IconSvg
。
首先在业务项目中引入 iconfont 图标项目中的这个在线 js 文件。
image.png
按照上文所述,我们可以暂时把playground
包看作是业务项目,所以直接在playground
包中的index.html
中引入这个 js 就可以了。
image.png
引入 js 后,我们可以看到 SVG symbol 已经生成好了。
image.png
注意:如果您担忧 cdn 的稳定性,可以考虑把 iconfont 项目中的相关资源下载到项目中直接引用,这样就不用担心哪天线上业务由于 cdn 问题受到影响。
image.png
接着就是在组件中把 use 的逻辑处理好。
<template>
<svg :style="{ width: `${size}px`, height: `${size}px`, fill: color }">
<use :xlink:href="`#${iconPrefix}${icon}`"></use>
</svg>
</template>
<script lang="ts" setup>
import { props } from './props'
defineProps(props)
</script>
属性定义基本上与IconFont
组件一致,但是具体用法有一点区别。
image.png
组件的尺寸还是交给属性size
控制,但是对应到 style 上是由width
和height
控制(因为font-size
对 svg 无效)。
组件的颜色是通过 style 的fill
控制的(因为color
也对 svg 无效)。
我们看看目前的使用效果。
image.png
image.png
基本效果出来了,但是我们发现一个问题,如果不绑定size
和color
属性,SVG 图标的表现不符合我们的预期。
image.png
默认的尺寸太大了,预期应该是和同一个块中的文字差不多大。
默认的颜色也不符合预期,我们希望它能跟随父级元素的字体颜色,这样才显得协调。
所以,还需要再做一些优化。我们把组件的外层包裹一个span
标签,让svg
的尺寸继承span
的字体大小,让svg
的颜色继承span
的颜色。
svg
的宽高都为1em
,这样就可以与文本的字体大小保持一致。svg
的fill
属性值为currentColor,currentColor 是一个 css 变量,它能取到当前元素的color
属性值,这样就可以与文本颜色保持一致了。代码改造如下:
image.png
再次查看效果,发现不传任何属性时,SVG 图标也能与文本效果协调。
image.png
image.png
至此,SVG 图标组件已经能应付大部分场景了。
在本节中,我们首先了解了一些字体相关的基础知识,以及使用 SVG 图标的一些优点,接着学习了实现 SVG 图标组件的基本思路和编码过程。本文写作过程中,我有感觉到字体是个很复杂的知识领域,若文中相关知识点叙述有误,还请指出!在实际项目中,对图标组件还会有一些拓展的需求,我们在下篇文章中会具体展开聊聊。如果您对我的专栏感兴趣,欢迎您订阅关注本专栏[6],接下来可以一同探讨和交流组件库开发过程中遇到的问题。
本文由哈喽比特于1年以前收录,如有侵权请联系我们。
文章来源:https://mp.weixin.qq.com/s/56geOgVpeYJTLcKTfrgARA
京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。
日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。
据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。
今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。
日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。
近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。
据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。
9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...
9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。
据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。
特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。
据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。
近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。
据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。
9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。
《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。
近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。
社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”
2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。
罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。