CSS3 帧动画(Sprite,直译叫雪碧图)

时间:2022-11-21 23:31:55

CSS雪碧

CSS雪碧 即CSS Sprite,也有人叫它CSS精灵,是一种CSS图像合并技术,该方法是将小图标和背景图像合并到一张图片上,然后利用css的背景定位来显示需要显示的图片部分。

原理

CSS雪碧的基本原理是把你的网站上用到的一些图片整合到一张单独的图片中,从而减少你的网站的HTTP请求数量。该图片使用CSS background和background-position属性渲染,这也就意味着你的标签变得更加复杂了,图片是在CSS中定义,而非<img>标签。

优点

减少加载网页图片时对服务器的请求次数

可以合并多数背景图片和小图标,方便在任何位置使用,这样不同位置的请求只需要调用一个图片,从而减少对服务器的请求次数,降低服务器压力,同时提高了页面的加载速度,节约服务器的流量。

提高页面的加载速度

sprite 技术的其中一个好处是图片的加载时间(在有许多 sprite 时,单张图片的加载时间)。由所需图片拼成的一张 GIF 图片的尺寸会明显小于所有图片拼合前的大小。单张的 GIF 只有相关的一个色表,而单独分割的每一张 GIF 都有自己的一个色表,这就增加了总体的大小。因此,单独的一张 JPEG 或者 PNG sprite 在大小上非常可能比把一张图分成多张得来的图片总尺寸小。

不足

CSS雪碧的最大问题是内存使用

除非这个雪碧图片是被非常小心的组织,你就会最终使用大量的无用的空白。一个例子是来自于WHIT TV的网站。注意这是一个1299×15,000像素的PNG图片。它也被压缩的很好——实际下载大小只有大概26K — 但是浏览器并不会渲染压缩后的图片数据。当这个图片被下载并被解压缩之后,它将占用差不多75MB的内存 (1299 * 15000 * 4)。如果这个图片并没有使用alpha透明,它将会被优化至1299 * 15000 * 3,但是要在损失渲染速度的情况下。即使那样,我们也会讨论55MB。这张图片的大部分其实就是空白,那里什么都没有,没没有任何有用的内容。只是加载 WHIT主页 就会导致你的浏览器的内存占用上升到至少75+MB,仅仅是因为那一张图片。(PS:遗憾的是,该网站最近已经改版,文中提到的图片已经不存在了)

错误得使用 Sprites 影响可访问性

一些刚入门的开发人员会为了节省 HTTP 请求数(这是使用 CSS Sprite 一直强调的好处)而把所有的图片都当背景图片来处理 – 甚至是那些传达重要信息的图片。结果会导致一个缺乏可访问性的网站,也会降低 HTML 中 title 和 alt 的潜在益处。

CSS3 animation 图解

CSS3 帧动画(Sprite,直译叫雪碧图)

代码实战

<html>
<head>
<style>
.imageStyle {
width: 240px;
height: 180px;
border-radius: 20px;
border: 1px solid black;
box-shadow: 5px 5px 5px #888;
margin: 5px;
}

.imageBg {
background-image: url("frameAnim.png");
}

#frameAnimImg1 {
animation: frameAnim1 10s infinite;
}

#frameAnimImg2 {
animation: frameAnim1 steps(1, start) 1s infinite;
}

#frameAnimImg3 {
animation: frameAnim2 10s infinite;
}

#frameAnimImg4 {
animation: frameAnim3 10s infinite;
}

#frameAnimImg5 {
animation: frameAnim4 1s infinite;
}

#animDiv {
overflow: hidden;
display: inline-block;
}

#frameAnimImg6 {
animation: frameAnim5 10s infinite;
}

#frameAnimImg7 {
animation: frameAnim5 steps(1, start) 1s infinite;
}

@keyframes frameAnim1 {
0% {background-position: 0px 0;}
14.286% {background-position: -241px 0;}
28.57% {background-position: -482px 0;}
42.9% {background-position: -723px 0;}
57.14% {background-position: -964px 0;}
71.43% {background-position: -1205px 0;}
85.71% {background-position: -1446px 0;}
100% {background-position: 0px 0;}
}
@keyframes frameAnim2 {
0%, 13% {background-position: 0px 0;}
14%, 27% {background-position: -241px 0;}
28%, 41% {background-position: -482px 0;}
42%, 56% {background-position: -723px 0;}
57%, 70% {background-position: -964px 0;}
71%, 84% {background-position: -1205px 0;}
85%, 100% {background-position: -1446px 0;}
}
@keyframes frameAnim3 {
0%, 13% {background-position: 0px 0;}
14%, 27% {background-position: -241px 0;}
28%, 41% {background-position: -482px 0;}
42%, 56% {background-position: -723px 0;}
57%, 70% {background-position: -964px 0;}
71%, 84% {background-position: -1205px 0;}
85%, 99% {background-position: -1446px 0;}
100% {background-position: 0px 0;}
}
@keyframes frameAnim4 {
0%, 14.286% {background-position: 0px 0;}
14.287%, 28.57% {background-position: -241px 0;}
28.571%, 42.9% {background-position: -482px 0;}
42.901%, 57.14% {background-position: -723px 0;}
57.141%, 71.43% {background-position: -964px 0;}
71.431%, 85.71% {background-position: -1205px 0;}
85.711%, 100% {background-position: -1446px 0;}
}
@keyframes frameAnim5 {
0% {transform:translate(0px, 0);}
14.286% {transform:translate(-241px, 0);}
28.57% {transform:translate(-482px, 0);}
42.9% {transform:translate(-723px,0);}
57.14% {transform:translate(-964px, 0);}
71.43% {transform:translate(-1205px, 0);}
85.71% {transform:translate(-1446px, 0);}
100% {transform:translate(0px, 0);}
}
</style>
</head>
<body>
<img id="frameAnimImg1" class="imageStyle imageBg ">
<img id="frameAnimImg2" class="imageStyle imageBg ">
<img id="frameAnimImg3" class="imageStyle imageBg ">
<img id="frameAnimImg4" class="imageStyle imageBg ">
<img id="frameAnimImg5" class="imageStyle imageBg ">
<div id="animDiv" class="imageStyle">
<img id="frameAnimImg6" src="frameAnim.png">
</div>
<div class="animDiv">
<!-- 注意:这里设置为background会无法显示 -->
<img id="frameAnimImg7" src="frameAnim.png">
</div>
</body>
</html>

CSS3 帧动画(Sprite,直译叫雪碧图)

CSS实现帧动画的方式有两种:

  • background-position: “x”px “y”px;
  • 父容器的overflow:hidden;配合上图像元素的transform:translate(x,y);

同样的 @keyframes,而左图的每帧都是滑动的,右图却是我们真正想要的帧动画,这是因为 CSS3 的 animation 默认会在每个关键帧之间插入补间动画,也就是使属性按 animation-timing-function 指定的函数改变到新的值。

解决办法有两个

  • 指定关键帧的”起始”和”终止”位置(百分数支持小数;百分比数值不能重叠,重叠的话,设置无效;帧之间的间隔要足够小,滑动才不会被肉眼可见)
@keyframes {
0%, 14.286% {background-position: 0px 0;}
14.287%, 28.57% {background-position: -241px 0;}
//在 14.286% 到 14.287% 之间,还是会按 animation-timing-function 所定义的方式滑动的,只是时间太短,肉眼分辨不出来而已。
......
}
  • 利用steps()实现帧之间的阶跃动画
    CSS3 帧动画(Sprite,直译叫雪碧图)
    steps(1,start):动画一开始就跳到 100% 直到这一帧(不是整个周期)结束
    steps(1,end):保持 0% 的样式直到这一帧(不是整个周期)结束
    另外也可以直接设置 animation-timing-function:step-start/step-end
    step-start效果等同于steps(1,start),step-end效果等同于steps(1,end)

素材

我是网上找了一张GIF图

CSS3 帧动画(Sprite,直译叫雪碧图)

然后用 GIFFrame.exe 解析出每一帧,并保存在相应的文件夹中

CSS3 帧动画(Sprite,直译叫雪碧图)

最后用 Window自带的“画图”,拼接成一幅长图

CSS3 帧动画(Sprite,直译叫雪碧图)

参考