整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

10 个优质的 CSS 与 JS LOGO 动画示例

10 个优质的 CSS 与 JS LOGO 动画示例

用 HTML 和 CSS 制作 LOGO 动画要比以前更容易,通过使用最新的 JavaScript 库也能够使网页动画制作的更加精良。

在本文中,我们将与大家分享 10 个让人印象深刻的世界知名品牌与未知实体的自定义 LOGO 动画示例。一起来 Enjoy 吧!

1. Flowers SVG

SVG 动画作为网上最热门的动画趋势之一,备受大家的关注。而这个花的 LOGO 动画便是一个很好的 SVG 动画示例。

我们可以看到,此 LOGO 的图标和文字在<svg>标签内编写,通过 CSS 来控制动画,并可以自动的完成页面的加载。当然,需要一些 SVG 特定的 CSS 属性支持,例如stroke-dashoffset(译者:表示虚线的起始偏移),它会按顺序来推动轮廓的运动,进而实现了精美的动画效果。

项目地址:https://codepen.io/flwrs/pen/gLrygN

2. Carbon LDP

Carbon LDP 的 LOGO 动画相当的复杂。但是开发者 David McFeders 通过 CSS/Compass 实现了 Carbon 的 LOGO 动画,从而也提升了它的逼格。

无论是 LOGO 的大小,还是动画的速度都很容易设置。它由纯 CSS 实现,并保持着无限的循环。虽然,LOGO 的字母是一张 PNG 图片,但你也可以随时利用自己设计的字体进行逆向工程。

项目地址:https://codepen.io/MiguelAraCo/pen/QbZqoQ

3. Binary Lab

Binary Lab 的 LOGO 动画同样是本文中比较复杂的动画效果之一。我们可以看到它的效果:从烧瓶里拉出的数字,在 LOGO 的上方不断的消失。

动画效果是由 CSS 控制的。同时,这个作品依赖了 TweenMax 库来添加重复的数字,并完成自定义的 alpha 转换。作者很有创意的利用 CSS 与 JS 实现了这个酷炫的 Web 动画效果。

项目地址:https://codepen.io/iconjunkie/pen/vLEaNZ

4. Pure CSS3 Stack Overflow

Stack Overflow 的 LOGO 是我最喜欢的 LOGO 之一,因为它的设计不仅简单,而且易识别。而这个作品仅用 CSS3 将 Stack Overflow 的 LOGO 进行了动画效果的实现。

这是迄今为止我看到的最令人印象深刻的纯 CSS 动画之一。最终的展现也与官方的 LOGO 很搭,同时在主流浏览器中动画都可以流畅的运行。相信,任何喜欢 CSS / SCSS 动画的朋友都会喜欢上这个作品。

项目地址:https://codepen.io/lindell/pen/mEVgJP

5. Monster Energy Logos

这个作品是由 Tim Pietrusky 利用 SVG 和均匀的 CSS 转换实现的怪物能量 LOGO 系列动画。如果你也打算在 LOGO 上实现淡入淡出的特效,就可以复制他的代码来学习。

它是一款纯 CSS 实现的动画,所有的动画时间都是由 SCSS 直接进行调控。同时,你也可以通过更改变量来调节动画的速度,淡化颜色。

项目地址:https://codepen.io/TimPietrusky/pen/vKuja

6. Subvisual

Subvisual 团队拥有非常独特的 LOGO,而开发者 Miguel Palhas 则赋予了它酷炫的动画效果。你会发现构成它的动画效果有两个因素,即 LOGO 的文字和“ S ”形图标。

作品是基于 SVG 元素构成的,也使操纵更简单。虽然作品中的大多数动画都是基于 CSS 编写的,但它也依赖 JavaScript 库:TweenLite。同时,这个作品可以根据用户的操作来重复或触发动画效果。(悬停、点击等)

项目地址:https://codepen.io/naps62/pen/eNMvpQ

7. Pixel Logo Animation

通过使用免费的像素字体,任何开发人员都可以制作出自定义的像素动画。而这个作品就是由 CodePen 的用户 Khaosmuhaha 所制作的。

他通过 HTML Canvas 元素进行纯文本的操作,动画效果则是由 CSS3 的 animation 属性进行驱动,而 jQuery 则控制了全部。所以,我们所见的连续像素动画就这样实现了。

显然,这是一个利用 Canvas 元素与 webfont 构成的炫酷的作品。

项目地址:https://codepen.io/Khaosmuhaha/pen/MYzRGz

8. Alex Aloia LOGO

如果你正在寻找一个真正复杂的 LOGO 动画,可以看看开发者 Alex Aloia 制作的这个示例。在作品中,作者使用了他的名字作为品牌名称,并将一系列复杂的 SVG 形状通过绘图的动画效果展现出来。

作品的整体效果只通过 CSS 来实现是不太可能的,还需要一些 JS 库 (DrawSVG 和更流行的 D3.js)的支持。但是,利用开源库来实现这种独一无二的动画,还是非常有趣的。

项目地址:https://codepen.io/tripl3inf/pen/QwrEMY

9. Bayleys

Bayleys 的 LOGO 动画的选择,有些令人费解。但 LOGO 厚实的边缘使重制变得易如反掌。开发者 Rafael Contreras 仅通过 38 行代码便实现了动画效果。

LOGO 是基于 SVG 标签制作的,动画效果则是操纵相应的标签来实现。而在不同的方向移动的众多 LOGO 元素,使动画令人着迷。

项目地址:https://codepen.io/rafita/pen/aNyRgv

10. Nintendo Switch

这是来自任天堂最新款游戏机的一个 LOGO 动画。而开发者 Koto Furumiya 在 CodePen 上实现了它们广告片中的动画效果。

Koto 使用 SVG 重制了任天堂 Switch 的 LOGO,并用 CSS 实现了它的动画效果。你会相信这个动画只需要 50 行的 CSS 代码吗?

另外,不得不提这个动画效果确实很逼真。强有力的下推与反弹回升效果,确实与任天堂 Switch 的开机动画相吻合。

项目地址:https://codepen.io/kotofurumiya/pen/VPmNrR

最后

今天分享的所有示例都是免费与开源的,希望你能将它们应用在你自己的项目上。同时,也希望你能喜欢这些 Demos。如果你正在寻找更多关于 CSS 动画的示例,也可以了解下这个合辑。


感谢你的阅读。

注:

  1. 本文版权归原作者所有,仅用于学习与交流。

  2. 如需转载译文,烦请按下方注明出处信息,谢谢!

英文原文:10 Amazing Examples of CSS & JavaScript Animated Logos

作者:Jake Rocheleau

译者:IT程序狮

译文地址:http://www.jianshu.com/p/b204e854a942

文作者:HelloGitHub-kalifun

图表库千万个今天 HelloGitHub 给大家推荐个很有“特色”的图表库:一个手绘风格的 JS 图表库 —— Chart.xkcd,快收起你紧绷、严肃的面容让我们一起看看用手绘风格展示数据的效果。

一、介绍

项目地址:https://github.com/timqian/chart.xkcd

Chart.xkcd 是一个图表库,可绘制“非精细”、“卡通”或“手绘”样式的图表。



效果是不是很可爱?那下面就跟着 HelloGitHub 发起的《讲解开源项目》[1]的教程一起学习、上手使用起来吧!

二、快速入手

使用 Chart.xkcd 很容易,只需页面中包含库的引用和一个用于显示图表的 <svg> 节点即可。

2.1 代码示例

先用一段简短的代码,让大家了解下基本的参数和代码的样子,后面会有可运行的代码示例片段供大家学习和使用 。

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <title>Title</title>
</head>
<body>
<!--将 SVG 元素直接嵌入 HTML 页面中-->
<svg class="line-chart"></svg>
<!--引入 JS 库-->
<script src="https://cdn.jsdelivr.net/npm/chart.xkcd@1.1/dist/chart.xkcd.min.js"></script>
<script>
 //关键代码块
 const svg=document.querySelector('.line-chart')
 new chartXkcd.Line(svg, {
 title: '',
 xLabel: '',
 yLabel: '',
 data: {...},
 options: {},
 });
</script>
</body>
</html>

2.2 参数说明

  • title:图表的标题
  • xLabel:图表的 x 标签
  • yLabel:图表的 y 标签
  • data:需要可视化的数据
  • options:自定义设置

三、图表类型

Chart.xkcd 支持多样的图表类型,下面将逐一讲解和实现:折线图、XY 图、条形图、圆饼/甜甜圈图、雷达图,实现的示例代码完整可运行、注释完整、包含参数说明。

tips:下文中的示例代码均可直接运行,保存为 html 文件便可在本机查看效果。

3.1 折线图

折线图以折线形式显示一系列数据点,它可以用于显示趋势数据或不同数据集的比较。

示例代码

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <title>Title</title>
</head>
<body>
<!--将 SVG 元素直接嵌入 HTML 页面中-->
<svg class="line-chart"></svg>
<!--引入 JS 库-->
<script src="https://cdn.jsdelivr.net/npm/chart.xkcd@1.1/dist/chart.xkcd.min.js"></script>
<script>
 // querySelector() 方法返回文档中匹配指定 CSS 选择器的一个元素。获取文档中 class=".line-chart" 的元素。
 const svg=document.querySelector('.line-chart');
 // chartXkcd.Line 创建一个折线图
 const lineChart=new chartXkcd.Line(svg, {
 //图表的标题
 title: 'Monthly income of an indie developer',
 // 图表的 x 标签
 xLabel: 'Month',
 // 图表的 y 标签
 yLabel: '$ Dollors',
 // 需要可视化的数据
 data: {
 // x 轴数据
 labels: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10'],
 // y 轴数据
 datasets: [{
 // 第一组数据
 label: 'Plan',
 data: [30, 70, 200, 300, 500, 800, 1500, 2900, 5000, 8000],
 }, {
 // 第二组数据
 label: 'Reality',
 data: [0, 1, 30, 70, 80, 100, 50, 80, 40, 150],
 }],
 },
 // 可选配置以自定义图表的外观
 options: {
 // 自定义要在 y 轴上看到的刻度号(默认为 3)
 yTickCount: 3,
 // 指定要放置图例的位置
 legendPosition: chartXkcd.config.positionType.upLeft
 }
 });
</script>
</body>
</html>

参数说明

  • yTickCount:自定义要在y轴上看到的刻度号(默认为 3)
  • legendPosition:指定要放置图例的位置(默认为 chartXkcd.config.positionType.upLeft)。
  • 左上位置:chartXkcd.config.positionType.upLeft
  • 顶右上位置:chartXkcd.config.positionType.upRight
  • 左下位置:chartXkcd.config.positionType.downLeft
  • 右下位置:chartXkcd.config.positionType.downRight
  • dataColors:不同颜色的数据集数组
  • fontFamily:定制图表中使用的字体系列
  • unxkcdify:禁用 xkcd 效果(默认为 false)

效果展示



3.2 XY 图

XY 图表用于通过指定点的 XY 坐标来绘制点,您也可以通过连接这些点来绘制 XY 折线图。

示例代码

<script>
 // querySelector() 方法返回文档中匹配指定 CSS 选择器的一个元素。获取文档中 class=".xy-chart" 的元素。
 const svg=document.querySelector('.xy-chart');
 //chartXkcd.XY 创建一个XY图
 new chartXkcd.XY(svg, {
 //图表的标题
 title: 'Pokemon farms',
 // 图表的 x 标签
 xLabel: 'Coodinate',
 // 图表的 y 标签
 yLabel: 'Count',
 // 需要可视化的数据
 data: {
 datasets: [{
 // 第一组数据
 label: 'Pikachu',
 data: [{ x: 3, y: 10 }, { x: 4, y: 122 }, { x: 10, y: 100 }, { x: 1, y: 2 }, { x: 2, y: 4 }],
 }, {
 // 第二组数据
 label: 'Squirtle',
 data: [{ x: 3, y: 122 }, { x: 4, y: 212 }, { x: -3, y: 100 }, { x: 1, y: 1 }, { x: 1.5, y: 12 }],
 }],
 },
 options: {
 // 自定义要在 x 轴上看到的刻度号(默认为 3)
 xTickCount: 5,
 // 自定义要在 y 轴上看到的刻度号(默认为 3)
 yTickCount: 5,
 // 指定要放置图例的位置
 legendPosition: chartXkcd.config.positionType.upRight,
 // 用线连接点(默认 false)
 showLine: false,
 // 指定时间格式
 timeFormat: undefined,
 // 更改点的大小(默认为 1)
 dotSize: 1,
 },
 });
</script>

参数说明

  • xTickCount:自定义要在x轴上看到的刻度号(默认为 3)
  • yTickCount:自定义要在y轴上看到的刻度号(默认为 3)
  • legendPosition:指定要放置图例的位置
  • showLine: 点连接成线。
  • timeFormat:指定时间格式
  • dotSize:更改点的大小(默认为 1)
  • dataColors:不同颜色的数据集数组
  • fontFamily:定制图表中使用的字体系列
  • unxkcdify:禁用 xkcd 效果(默认为 false)

效果展示



如果你想将这些点连接起来,让数据对比更加明显的话。请修改 showLine:true 再刷新页面你就可以看到连线的效果了。

3.3 条形图

条形图提供了一种显示以竖条表示的数据值的方式。

示例代码

<script>
 // querySelector() 方法返回文档中匹配指定 CSS 选择器的一个元素。获取文档中 class=".bar-chart" 的元素。
 const svg=document.querySelector('.bar-chart');
 // chartXkcd.Bar 创建一个条形图
 const barChart=new chartXkcd.Bar(svg, {
 // 图表的标题
 title: 'github stars VS patron number',
 // xLabel: '', // optional
 // yLabel: '', // optional
 // 图表数据
 data: {
 labels: ['github stars', 'patrons'],
 datasets: [{
 data: [100, 2],
 }],
 },
 options: {
 // 自定义要在 y 轴上看到的刻度号(默认为 3)
 yTickCount: 2,
 },
 });
</script>

参数说明

  • yTickCount:自定义要在y轴上看到的刻度号(默认为 3)
  • dataColors:不同颜色的数据集数组
  • fontFamily:定制图表中使用的字体系列
  • unxkcdify:禁用xkcd效果(默认为 false)

效果展示



3.4 圆饼/甜甜圈图

饼图广泛得应用在各个领域,用于表示不同分类的占比情况,通过弧度大小来对比各种分类。饼图通过将一个圆饼按照分类的占比划分成多个区块,整个圆饼代表数据的总量,每个区块(圆弧)表示该分类占总体的比例大小,所有区块(圆弧)的加和等于 100%。

示例代码

<script>
 // querySelector() 方法返回文档中匹配指定 CSS 选择器的一个元素。获取文档中 class=".pie-chart" 的元素。
 const svg=document.querySelector('.pie-chart');
 // chartXkcd.Pie 创建一个圆饼图
 const pieChart=new chartXkcd.Pie(svg, {
 // 图表的标题
 title: 'What Tim made of',
 // 需要可视化的数据
 data: {
 labels: ['a', 'b', 'e', 'f', 'g'],
 datasets: [{
 data: [500, 200, 80, 90, 100],
 }],
 },
 options: {
 // 指定空的饼图半径
 innerRadius: 0.5,
 // 指定要放置图例的位置
 legendPosition: chartXkcd.config.positionType.upRight,
 },
 });
</script>

参数说明

  • innerRadius:指定空的饼图半径(默认值:0.5)
  • 需要饼图吗?将 innerRadius 设置为 0
  • legendPosition:指定要放置图例的位置
  • dataColors:不同颜色的数据集数组
  • fontFamily:定制图表中使用的字体系列
  • unxkcdify:禁用 xkcd 效果(默认为 false)

效果展示



3.5 雷达图

雷达图(Radar Chart)又被叫做蜘蛛网图,适用于显示三个或更多的维度的变量。雷达图是以在同一点开始的轴上显示的三个或更多个变量的二维图表的形式来显示多元数据的方法,其中轴的相对位置和角度通常是无意义的。

示例代码

<script>
 // querySelector() 方法返回文档中匹配指定 CSS 选择器的一个元素。获取文档中 class=".radar-chart" 的元素。
 const svg=document.querySelector('.radar-chart');
 // chartXkcd.Radar 创建一个雷达图
 const radarChart=new chartXkcd.Radar(svg, {
 // 图表的标题
 title: 'Letters in random words',
 // 需要可视化的数据
 data: {
 labels: ['c', 'h', 'a', 'r', 't'],
 datasets: [{
 label: 'ccharrrt',
 data: [2, 1, 1, 3, 1],
 }, {
 label: 'chhaart',
 data: [1, 2, 2, 1, 1],
 }],
 },
 options: {
 // 在图表中显示图例
 showLegend: true,
 // 点的大小
 dotSize: 0.8,
 // 在每行附近显示标签
 showLabels: true,
 // 指定要放置图例的位置
 legendPosition: chartXkcd.config.positionType.upRight,
 // unxkcdify: true,
 },
 });
</script>

参数说明

  • showLabels:在每行附近显示标签(默认为 false)
  • ticksCount:自定义要在主行上看到的刻度号(默认为 3)
  • dotSize:更改点的大小(默认为 1)
  • showLegend:在图表附近显示图例(默认为 false)
  • legendPosition:指定要放置图例的位置
  • dataColors:不同颜色的数据集数组
  • fontFamily:定制图表中使用的字体系列
  • unxkcdify:禁用 xkcd 效果(默认为 false)

效果展示



四、最后

以上就是讲解的全部内容,相信教程至此 Chart.xkcd 库的基本用法你已经基本掌握,后面就可以用来今天学到的东西,提高自己项目的颜值了。

有了 Chart.xkcd 让数据可爱地展示出来并不难,快动手自己实现一个吧~

参考资料

[1]《讲解开源项目》: https://github.com/HelloGitHub-Team/Article

[2]CHART.XKCD 官方文档: https://timqian.com/chart.xkcd/

[3]CHART.XKCD 项目地址: https://github.com/timqian/chart.xkcd


『讲解开源项目系列』——让对开源项目感兴趣的人不再畏惧、让开源项目的发起者不再孤单。跟着我们的文章,你会发现编程的乐趣、使用和发现参与开源项目如此简单。欢迎留言联系我们、加入我们,让更多人爱上开源、贡献开源~

接:https://juejin.im/book/5b936540f265da0a9624b04b

《高性能网站建设指南》的作者 Steve Souders 曾在一篇博客中提到:

我的大部分性能优化工作都集中在 JavaScript 和 CSS 上,从早期的 Move Scripts to the Bottom 和 Put Stylesheets at the Top 规则。为了强调这些规则的重要性,我甚至说过,“JS 和 CSS 是页面上最重要的部分”。

几个月后,我意识到这是错误的。图片才是页面上最重要的部分。

我关注 JS 和 CSS 的重点也是如何能够更快地下载图片。图片是用户可以直观看到的。他们并不会关注 JS 和 CSS。确实,JS 和 CSS 会影响图片内容的展示,尤其是会影响图片的展示方式(比如图片轮播,CSS 背景图和媒体查询)。但是我认为 JS 和 CSS 只是展示图片的方式。在页面加载的过程中,应当先让图片和文字先展示,而不是试图保证 JS 和 CSS 更快下载完成。

这段话可谓字字珠玑。此外,雅虎军规和 Google 官方的最佳实践也都将图片优化列为前端性能优化必不可少的环节——图片优化的优先级可见一斑。

就图片这块来说,与其说我们是在做“优化”,不如说我们是在做“权衡”。因为我们要做的事情,就是去压缩图片的体积(或者一开始就选取体积较小的图片格式)。但这个优化操作,是以牺牲一部分成像质量为代价的。因此我们的主要任务,是尽可能地去寻求一个质量与性能之间的平衡点。

2019 年,图片依然很大

这里先给大家介绍 HTTP-Archive 这个网站,它会定期抓取 Web 上的站点,并记录资源的加载情况、Web API 的使用情况等页面的详细信息,并会对这些数据进行处理和分析以确定趋势。通过它我们可以实时地看到世界范围内的 Web 资源的统计结果。

截止到 2018 年 8 月,过去一年总的 web 资源的平均请求体积是这样的:

而具体到图片这一类的资源,平均请求体积是这样的:

当然,随着我们工程师在性能方面所做的努力越来越有成效,平均来说,不管是资源总量还是图片体积,都在往越来越轻量的方向演化。这是一种值得肯定的进步。

但同时我们不得不承认,如图所示的这个图片体积,依然是太大了。图片在所有资源中所占的比重,也足够“触目惊心”了。为了改变这个现状,我们必须把图片优化提上日程。

不同业务场景下的图片方案选型

时下应用较为广泛的 Web 图片格式有 JPEG/JPG、PNG、WebP、Base64、SVG 等,这些格式都是很有故事的,值得我们好好研究一把。此外,老生常谈的雪碧图(CSS Sprites)至今也仍在一线的前端应用中发光发热,我们也会有所提及。

不谈业务场景的选型都是耍流氓。下面我们就结合具体的业务场景,一起来解开图片选型的神秘面纱!

前置知识:二进制位数与色彩的关系

在计算机中,像素用二进制数来表示。不同的图片格式中像素与二进制位数之间的对应关系是不同的。一个像素对应的二进制位数越多,它可以表示的颜色种类就越多,成像效果也就越细腻,文件体积相应也会越大。

一个二进制位表示两种颜色(0|1 对应黑|白),如果一种图片格式对应的二进制位数有 n 个,那么它就可以呈现 2^n 种颜色。

JPEG/JPG

关键字:有损压缩、体积小、加载快、不支持透明

JPG 的优点

JPG 最大的特点是有损压缩。这种高效的压缩算法使它成为了一种非常轻巧的图片格式。另一方面,即使被称为“有损”压缩,JPG的压缩方式仍然是一种高质量的压缩方式:当我们把图片体积压缩至原有体积的 50% 以下时,JPG 仍然可以保持住 60% 的品质。此外,JPG 格式以 24 位存储单个图,可以呈现多达 1600 万种颜色,足以应对大多数场景下对色彩的要求,这一点决定了它压缩前后的质量损耗并不容易被我们人类的肉眼所察觉——前提是你用对了业务场景。

使用场景

JPG 适用于呈现色彩丰富的图片,在我们日常开发中,JPG 图片经常作为大的背景图、轮播图或 Banner 图出现。

两大电商网站对大图的处理,是 JPG 图片应用场景的最佳写照:

打开淘宝首页,我们可以发现页面中最醒目、最庞大的图片,一定是以 .jpg 为后缀的:

京东首页也不例外:

使用 JPG 呈现大图,既可以保住图片的质量,又不会带来令人头疼的图片体积,是当下比较推崇的一种方案。

JPG 的缺陷

有损压缩在上文所展示的轮播图上确实很难露出马脚,但当它处理矢量图形Logo 等线条感较强、颜色对比强烈的图像时,人为压缩导致的图片模糊会相当明显。

此外,JPEG 图像不支持透明度处理,透明图片需要召唤 PNG 来呈现。

PNG-8 与 PNG-24

关键字:无损压缩、质量高、体积大、支持透明

PNG 的优点

PNG(可移植网络图形格式)是一种无损压缩的高保真的图片格式。8 和 24,这里都是二进制数的位数。按照我们前置知识里提到的对应关系,8 位的 PNG 最多支持 256 种颜色,而 24 位的可以呈现约 1600 万种颜色。

PNG 图片具有比 JPG 更强的色彩表现力,对线条的处理更加细腻,对透明度有良好的支持。它弥补了上文我们提到的 JPG 的局限性,唯一的 BUG 就是体积太大

PNG-8 与 PNG-24 的选择题

什么时候用 PNG-8,什么时候用 PNG-24,这是一个问题。

理论上来说,当你追求最佳的显示效果、并且不在意文件体积大小时,是推荐使用 PNG-24 的。

但实践当中,为了规避体积的问题,我们一般不用PNG去处理较复杂的图像。当我们遇到适合 PNG 的场景时,也会优先选择更为小巧的 PNG-8

如何确定一张图片是该用 PNG-8 还是 PNG-24 去呈现呢?好的做法是把图片先按照这两种格式分别输出,看 PNG-8 输出的结果是否会带来肉眼可见的质量损耗,并且确认这种损耗是否在我们(尤其是你的 UI 设计师)可接受的范围内,基于对比的结果去做判断。

应用场景

前面我们提到,复杂的、色彩层次丰富的图片,用 PNG 来处理的话,成本会比较高,我们一般会交给 JPG 去存储。

考虑到 PNG 在处理线条和颜色对比度方面的优势,我们主要用它来呈现小的 Logo、颜色简单且对比强烈的图片或背景等。

此时我们再次把目光转向性能方面堪称业界楷模的淘宝首页,我们会发现它页面上的 Logo,无论大小,还真的都是 PNG 格式:

主 Logo:

较小的 Logo:

颜色简单、对比度较强的透明小图也在 PNG 格式下有着良好的表现:

SVG

关键字:文本文件、体积小、不失真、兼容性好

SVG(可缩放矢量图形)是一种基于 XML 语法的图像格式。它和本文提及的其它图片种类有着本质的不同:SVG 对图像的处理不是基于像素点,而是是基于对图像的形状描述。

SVG 的特性

和性能关系最密切的一点就是:SVG 与 PNG 和 JPG 相比,文件体积更小,可压缩性更强

当然,作为矢量图,它最显著的优势还是在于图片可无限放大而不失真这一点上。这使得 SVG 即使是被放到视网膜屏幕上,也可以一如既往地展现出较好的成像品质——1 张 SVG 足以适配 n 种分辨率。

此外,SVG 是文本文件。我们既可以像写代码一样定义 SVG,把它写在 HTML 里、成为 DOM 的一部分,也可以把对图形的描述写入以 .svg 为后缀的独立文件(SVG 文件在使用上与普通图片文件无异)。这使得 SVG 文件可以被非常多的工具读取和修改,具有较强的灵活性

SVG 的局限性主要有两个方面,一方面是它的渲染成本比较高,这点对性能来说是很不利的。另一方面,SVG 存在着其它图片格式所没有的学习成本(它是可编程的)。

SVG 的使用方式与应用场景

SVG 是文本文件,我们既可以像写代码一样定义 SVG,把它写在 HTML 里、成为 DOM 的一部分,也可以把对图形的描述写入以 .svg 为后缀的独立文件(SVG 文件在使用上与普通图片文件无异)。

将 SVG 写入 HTML:

将 SVG 写入独立文件后引入 HTML:

<img src="文件名.svg" alt="">

在实际开发中,我们更多用到的是后者。很多情况下设计师会给到我们 SVG 文件,就算没有设计师,我们还有非常好用的 在线矢量图形库。对于矢量图,我们无须深究过多,只需要对其核心特性有所掌握、日后在应用时做到有迹可循即可。

Base64

关键字:文本文件、依赖编码、小图标解决方案

Base64 并非一种图片格式,而是一种编码方式。Base64 和雪碧图一样,是作为小图标解决方案而存在的。在了解 Base64 之前,我们先来了解一下雪碧图。

前置知识:最经典的小图标解决方案——雪碧图(CSS Sprites)

雪碧图、CSS 精灵、CSS Sprites、图像精灵,说的都是这个东西——一种将小图标和背景图像合并到一张图片上,然后利用 CSS 的背景定位来显示其中的每一部分的技术。

MDN 对雪碧图的解释已经非常到位:

图像精灵(sprite,意为精灵),被运用于众多使用大量小图标的网页应用之上。它可取图像的一部分来使用,使得使用一个图像文件替代多个小文件成为可能。相较于一个小图标一个图像文件,单独一张图片所需的 HTTP 请求更少,对内存和带宽更加友好。

我们几乎可以在每一个有小图标出现的网站里找到雪碧图的影子(下图截取自京东首页):

和雪碧图一样,Base64 图片的出现,也是为了减少加载网页图片时对服务器的请求次数,从而提升网页性能。Base64 是作为雪碧图的补充而存在的。

理解 Base64

通过我们上文的演示,大家不难看出,每次加载图片,都是需要单独向服务器请求这个图片对应的资源的——这也就意味着一次 HTTP 请求的开销。

Base64 是一种用于传输 8Bit 字节码的编码方式,通过对图片进行 Base64 编码,我们可以直接将编码结果写入 HTML 或者写入 CSS,从而减少 HTTP 请求的次数。

我们来一起看一个实例,现在我有这么一个小小的放大镜 Logo:

它对应的链接如下:

https://user-gold-cdn.xitu.io/2018/9/15/165db7e94699824b?w=22&h=22&f=png&s=3680

按照一贯的思路,我们加载图片需要把图片链接写入 img 标签:

<img src="https://user-gold-cdn.xitu.io/2018/9/15/165db7e94699824b?w=22&h=22&f=png&s=3680">

浏览器就会针对我们的图片链接去发起一个资源请求。

但是如果我们对这个图片进行 Base64 编码,我们会得到一个很长很长的字符串,我们可以直接用这个字符串替换掉上文中的链接地址。你会发现浏览器原来是可以理解这个字符串的,它自动就将这个字符串解码为了一个图片,而不需再去发送 HTTP 请求。

Base64 的应用场景

上面这个实例,其实源自我们 掘金 网站 Header 部分的搜索栏 Logo:

既然 Base64 这么棒,我们何不把大图也换成 Base64 呢?

这是因为,Base64 编码后,图片大小会膨胀为原文件的 4/3(这是由 Base64 的编码原理决定的)。如果我们把大图也编码到 HTML 或 CSS 文件中,后者的体积会明显增加,即便我们减少了 HTTP 请求,也无法弥补这庞大的体积带来的性能开销,得不偿失。

在传输非常小的图片的时候,Base64 带来的文件体积膨胀、以及浏览器解析 Base64 的时间开销,与它节省掉的 HTTP 请求开销相比,可以忽略不计,这时候才能真正体现出它在性能方面的优势。

因此,Base64 并非万全之策,我们往往在一张图片满足以下条件时会对它应用 Base64 编码:

  1. 图片的实际尺寸很小(大家可以观察一下掘金页面的 Base64 图,几乎没有超过 2kb 的)
  2. 图片无法以雪碧图的形式与其它小图结合(合成雪碧图仍是主要的减少 HTTP 请求的途径,Base64 是雪碧图的补充)
  3. 图片的更新频率非常低(不需我们重复编码和修改文件内容,维护成本较低)

Base64 编码工具推荐

这里最推荐的是利用 webpack 来进行 Base64 的编码——webpack 的 url-loader 非常聪明,它除了具备基本的 Base64 转码能力,还可以结合文件大小,帮我们判断图片是否有必要进行 Base64 编码。

除此之外,市面上免费的 Base64 编解码工具种类是非常多样化的,有很多网站都提供在线编解码的服务,大家选取自己认为顺手的工具就好。

WebP

关键字:年轻的全能型选手

WebP 是今天在座各类图片格式中最年轻的一位,它于 2010 年被提出, 是 Google 专为 Web 开发的一种旨在加快图片加载速度的图片格式,它支持有损压缩和无损压缩。

WebP 的优点

WebP 像 JPEG 一样对细节丰富的图片信手拈来,像 PNG 一样支持透明,像 GIF 一样可以显示动态图片——它集多种图片文件格式的优点于一身。

WebP 的官方介绍对这一点有着更权威的阐述:

与 PNG 相比,WebP 无损图像的尺寸缩小了 26%。在等效的 SSIM 质量指数下,WebP 有损图像比同类 JPEG 图像小 25-34%。 无损 WebP 支持透明度(也称为 alpha 通道),仅需 22% 的额外字节。对于有损 RGB 压缩可接受的情况,有损 WebP 也支持透明度,与 PNG 相比,通常提供 3 倍的文件大小。

我们开篇提到,图片优化是质量与性能的博弈,从这个角度看,WebP 无疑是真正的赢家。

WebP 的局限性

WebP 纵有千般好,但它毕竟太年轻。我们知道,任何新生事物,都逃不开兼容性的大坑。现在是 2018 年 9 月,WebP 的支持情况是这样的:

坦白地说,虽然没有特别惨(毕竟还有亲爹 Chrome 在撑腰),但也足够让人望而却步了。

此外,WebP 还会增加服务器的负担——和编码 JPG 文件相比,编码同样质量的 WebP 文件会占用更多的计算资源。

WebP 的应用场景

现在限制我们使用 WebP 的最大问题不是“这个图片是否适合用 WebP 呈现”的问题,而是“浏览器是否允许 WebP”的问题,即我们上文谈到的兼容性问题。具体来说,一旦我们选择了 WebP,就要考虑在 Safari 等浏览器下它无法显示的问题,也就是说我们需要准备 PlanB,准备降级方案。

目前真正把 WebP 格式落地到网页中的网站并不是很多,这其中淘宝首页对 WebP 兼容性问题的处理方式就非常有趣。我们可以打开 Chrome 的开发者工具搜索其源码里的 WebP 关键字:

我们会发现检索结果还是挺多的(单就图示的加载结果来看,足足有?200?多条),下面大家注意一下这些 WebP 图片的链接地址(以其中一个为例):

<img src="//img.alicdn.com/tps/i4/TB1CKSgIpXXXXccXXXX07tlTXXX-200-200.png_60x60.jpg_.webp" alt="手机app - 聚划算" class="app-icon">

.webp 前面,还跟了一个 .jpg 后缀!

我们现在先大胆地猜测,这个图片应该至少存在 jpg 和 webp 两种格式,程序会根据浏览器的型号、以及该型号是否支持 WebP 这些信息来决定当前浏览器显示的是 .webp 后缀还是 .jpg 后缀。带着这个预判,我们打开并不支持 WebP 格式的 Safari 来进入同样的页面,再次搜索 WebP 关键字:

Safari 提示我们找不到,这也是情理之中。我们定位到刚刚示例的 WebP 图片所在的元素,查看一下它在 Safari 里的图片链接:

<img src="//img.alicdn.com/tps/i4/TB1CKSgIpXXXXccXXXX07tlTXXX-200-200.png_60x60.jpg" alt="手机app - 聚划算" class="app-icon">

我们看到同样的一张图片,在 Safari 中的后缀从 .webp 变成了 .jpg!看来果然如此——站点确实是先进行了兼容性的预判,在浏览器环境支持 WebP 的情况下,优先使用 WebP 格式,否则就把图片降级为 JPG 格式(本质是对图片的链接地址作简单的字符串切割)。

此外,还有另一个维护性更强、更加灵活的方案——把判断工作交给后端,由服务器根据 HTTP 请求头部的 Accept 字段来决定返回什么格式的图片。当 Accept 字段包含 image/webp 时,就返回 WebP 格式的图片,否则返回原图。这种做法的好处是,当浏览器对 WebP 格式图片的兼容支持发生改变时,我们也不用再去更新自己的兼容判定代码,只需要服务端像往常一样对 Accept 字段进行检查即可。

由此也可以看出,我们 WebP 格式的局限性确实比较明显,如果决定使用 WebP,兼容性处理是必不可少的。