Web 中的字体和 SVG 图标,你了解多少?

发表于 1年以前  | 总阅读数:598 次

前言

本文是 基于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.
  • 位图字体(同义词:点阵字体)本质上是点或像素组成的矩阵(也就是点阵)。像素化的内容在较高分辨率的设备上会有比较糟糕的表现(失真、模糊等),因为把低像素的内容放在高分辨率的设备上显示时,计算机会不知道如何展示(具体表现为不知道内容像素和设备像素的对应关系),这就需要根据 Nearest-neighbor interpolation 算法进行最近邻插值,最终计算出来的位置不一定理想,同时也可能出现锯齿,这种展示是有损的,需要结合抗锯齿算法来做优化。

image.png

  • 矢量字体(同义词:轮廓字体)是像素无关的,它使用贝塞尔曲线、绘图指令、数学公式等描述字形,它不像位图字体预先处理好像素,而是实时计算渲染,相对来说速度更慢。但是这样的字体理论上就可以适应各种大小的分辨率,但是最终效果也取决于渲染引擎的具体实现,可能也会出现锯齿,因为矢量在理论上是完美的,但是对应到显示设备上还是要落到具体像素上的,最终还是要结合抗锯齿、字体微调、亚像素渲染、DirectWrite 等技术手段优化。矢量字体主要包括 PostScript Type 1 and Type 3 fonts[3], TrueType[4], OpenType[5] 等几类。

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 字体是矢量字体吗?

了解了这些字体知识后,问题来了,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";

字体图标 VS SVG 图标

既然 Web 字体基本上都是矢量字体,字体图标基本上用的也是.ttf, .woff, .woff2等矢量字体,看起来没什么缺点,那么为什么 SVG 图标慢慢成为了各大网站的首选呢?

首先,字体是一种资源,如果字体加载失败,字体图标也就会渲染失败,可能会出现“小方格”。并且,如果由于网络等原因导致字体加载较慢,可能会出现占位抖动的情况(采用Base64内联字体会解决这个问题)。

image.png

而 SVG 是 HTML 文档内联的内容,渲染上会更可靠一点。

其次,字体图标并不支持彩色图标,即便现在彩色字体在 Web 中慢慢有了一些声音(iconfont 平台也支持了彩色字体图标),但是兼容性还有一些欠缺,在生产使用时还需要慎重考虑。而 SVG 本身是通过 XML 描述绘图指令,在绘图细节上控制力更强,天然支持彩色!不过随着未来 Web 彩色字体的普及,这方面也将不再是字体图标的劣势。

SVG 图标可以支持更丰富的表现能力,比如滤镜、动画等,同时也支持 DOM 操作,这些是字体图标比不了的。

字体图标的可访问性并不友好。字体图标是通过伪元素实现,比 SVG 的可访问性要差一些,SVG 内部可以使用titledesc标签描述信息,这无论对 SEO 还是无障碍阅读来说都显得更合适。

在图标数量很多时,SVG 图标的优势更为明显,SVG 支持按需使用。而字体图标的图标和图标之间耦合在一个字体文件中,这会导致最终的字体文件很大。

但也不是说字体图标就一无是处,字体图标在浏览器兼容性方面要更胜一筹,不过在“IE 已死”的局面下似乎也无关痛痒(老系统例外)。

总的来说,字体图标和 SVG 图标都有各自的优势,并不是说哪个一定比另一个优秀,我们可以结合实际场景来考虑选用。

SVG 图标的使用方式

  • 直接使用 SVG:内联 SVG,图片,背景图等形式,缺点是使用起来不是很方便,通用性不够。
  • SVG Sprite:基于 symbol + use 实现,是 SVG 版本的雪碧图,可以封装成组件使用。
  • SVG 独立组件:把每个 SVG 图标做成按需加载的组件,这样就可以按需使用,同时兼具组件化的优点,类似于@ant-design/icons-vue提供的图标单组件。

SVG 图标组件实现思路

我们先尝试一下 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 的使用封装到组件中,让业务调用变得简单。

编码实现 SVG 图标组件

基本逻辑捋清楚了,我们来编码实现一下。

为了和字体图标组件区分开,我们把上节中实现的字体图标组件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 上是由widthheight控制(因为font-size对 svg 无效)。

组件的颜色是通过 style 的fill控制的(因为color也对 svg 无效)。

我们看看目前的使用效果。

image.png

image.png

基本效果出来了,但是我们发现一个问题,如果不绑定sizecolor属性,SVG 图标的表现不符合我们的预期。

image.png

默认的尺寸太大了,预期应该是和同一个块中的文字差不多大。

默认的颜色也不符合预期,我们希望它能跟随父级元素的字体颜色,这样才显得协调。

所以,还需要再做一些优化。我们把组件的外层包裹一个span标签,让svg的尺寸继承span的字体大小,让svg的颜色继承span的颜色。

  • 尺寸上的继承:可以设置svg的宽高都为1em,这样就可以与文本的字体大小保持一致。
  • 颜色上的继承:可以设置svgfill属性值为currentColor,currentColor 是一个 css 变量,它能取到当前元素的color属性值,这样就可以与文本颜色保持一致了。

代码改造如下:

image.png

再次查看效果,发现不传任何属性时,SVG 图标也能与文本效果协调。

image.png

image.png

至此,SVG 图标组件已经能应付大部分场景了。

参考文献

  • Computer font
  • 一种笔划矢量字库的存取方法

结语

在本节中,我们首先了解了一些字体相关的基础知识,以及使用 SVG 图标的一些优点,接着学习了实现 SVG 图标组件的基本思路和编码过程。本文写作过程中,我有感觉到字体是个很复杂的知识领域,若文中相关知识点叙述有误,还请指出!在实际项目中,对图标组件还会有一些拓展的需求,我们在下篇文章中会具体展开聊聊。如果您对我的专栏感兴趣,欢迎您订阅关注本专栏[6],接下来可以一同探讨和交流组件库开发过程中遇到的问题。

本文由哈喽比特于1年以前收录,如有侵权请联系我们。
文章来源:https://mp.weixin.qq.com/s/56geOgVpeYJTLcKTfrgARA

 相关推荐

刘强东夫妇:“移民美国”传言被驳斥

京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。

发布于:8月以前  |  808次阅读  |  详细内容 »

博主曝三大运营商,将集体采购百万台华为Mate60系列

日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。

发布于:8月以前  |  770次阅读  |  详细内容 »

ASML CEO警告:出口管制不是可行做法,不要“逼迫中国大陆创新”

据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。

发布于:8月以前  |  756次阅读  |  详细内容 »

抖音中长视频App青桃更名抖音精选,字节再发力对抗B站

今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。

发布于:8月以前  |  648次阅读  |  详细内容 »

威马CDO:中国每百户家庭仅17户有车

日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。

发布于:8月以前  |  589次阅读  |  详细内容 »

研究发现维生素 C 等抗氧化剂会刺激癌症生长和转移

近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。

发布于:8月以前  |  449次阅读  |  详细内容 »

苹果据称正引入3D打印技术,用以生产智能手表的钢质底盘

据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。

发布于:8月以前  |  446次阅读  |  详细内容 »

千万级抖音网红秀才账号被封禁

9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...

发布于:8月以前  |  445次阅读  |  详细内容 »

亚马逊股东起诉公司和贝索斯,称其在购买卫星发射服务时忽视了 SpaceX

9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。

发布于:8月以前  |  444次阅读  |  详细内容 »

苹果上线AppsbyApple网站,以推广自家应用程序

据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。

发布于:8月以前  |  442次阅读  |  详细内容 »

特斯拉美国降价引发投资者不满:“这是短期麻醉剂”

特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。

发布于:8月以前  |  441次阅读  |  详细内容 »

光刻机巨头阿斯麦:拿到许可,继续对华出口

据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。

发布于:8月以前  |  437次阅读  |  详细内容 »

马斯克与库克首次隔空合作:为苹果提供卫星服务

近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。

发布于:8月以前  |  430次阅读  |  详细内容 »

𝕏(推特)调整隐私政策,可拿用户发布的信息训练 AI 模型

据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。

发布于:8月以前  |  428次阅读  |  详细内容 »

荣耀CEO谈华为手机回归:替老同事们高兴,对行业也是好事

9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。

发布于:8月以前  |  423次阅读  |  详细内容 »

AI操控无人机能力超越人类冠军

《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。

发布于:8月以前  |  423次阅读  |  详细内容 »

AI生成的蘑菇科普书存在可致命错误

近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。

发布于:8月以前  |  420次阅读  |  详细内容 »

社交媒体平台𝕏计划收集用户生物识别数据与工作教育经历

社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”

发布于:8月以前  |  411次阅读  |  详细内容 »

国产扫地机器人热销欧洲,国产割草机器人抢占欧洲草坪

2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。

发布于:8月以前  |  406次阅读  |  详细内容 »

罗永浩吐槽iPhone15和14不会有区别,除了序列号变了

罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。

发布于:8月以前  |  398次阅读  |  详细内容 »
 相关文章
Android插件化方案 5年以前  |  236913次阅读
vscode超好用的代码书签插件Bookmarks 1年以前  |  7118次阅读
 目录