记GIF动画转CSS逐帧动画工具
由 Ghostzhang 发表于
翻到了 2018 年左右团队支持的一个项目,当时看重构同学不断的在和设计师来回沟通调动画细节,就在想能不能提升下这里的效率,于是了解了下当时的实现过程,大概是这样的:
设计师用 PS 或其他工具输出 gif 动画图或视频给到前端开发,前端开发再对照着用 CSS 动画实现。开发会用用工具(如 PS)把 gif 图中每一帧的时间取出来,由于显示精度的问题,往往取到的时间会比较粗(秒),这就导致最终效果与设计师给出的还是会有差异,就感觉不对,因此还需要再进一步调整代码,于是就出现了需要反复沟通的现象。
CSS 动画,简单的说就是用 CSS3 的animation
属性,设置@keyframes
关键帧来实现的帧动画。(示例可以看这里 https://www.jianshu.com/p/05c5a9b302d2 )看完应该大概有了个概念。
现在进入主题,平时我们对帧动画的印象,大多是同一时间间隔的,像上面示例中的例子:
@keyframes run {
0% {
background-position: 0 0
}
10%{
background-position: -100% 0
}
20%{
background-position: -200% 0
}
30%{
background-position: -300% 0
}
40%{
background-position: -400% 0
}
50%{
background-position: 0 -100%
}
60%{
background-position: -100% -100%
}
70%{
background-position: -200% -100%
}
80%{
background-position: -300% -100%
}
90%{
background-position: -400% -100%
}
100%{
background-position: 0 0
}
}
会发现每一帧的间隔都是一样的,大部分情况下效果也还不错。但如果遇到需要设置不同间隔的情况呢?
像周末摇摇乐这样的项目,界面上的动画是每一次活动运营的重点,对动画质量的要求会高很多,特别是在节假日时,会有专门的动画效果,为了让动画看起来更加的流畅,往往需要控制到每一帧的时长,这也让开发的实现难度有了增加。
那如何提高这个过程的效率呢?设想下,如果能读取 GIF 中每一帧的时间,是不是就能计算出来总的时长和每一帧所占的时间比。如果再自动给出相应的代码,嘿嘿……
GIF 图片解析
首先来找找 GIF 图中时间是在哪表示的,关于 GIF 图,在这里(What’s In A GIF)有很详细的说明
用支持十六进制的编辑器打开一张 GIF 图,就可以看到这样的一串数据。为方便分析,我用了一张 10*10 的小图,如下:
文件头
GIF 有两个版本,分别是 87a 和 89a,区别如下:
- GIF87a:是在 1987 年年制定的版本。
- GIF89a:是在 1989 年年制定的版本。在这个版本中,为图像互换格式⽂文档扩充 了了图形控制区块、备注、说明、应⽤用程序接⼝口等四个区块,并提供了了对透明⾊色 和多帧动画的⽀支持。
GIF87a | GIF89a | |
---|---|---|
LZW 压缩 | Y | Y |
支持隔行扫描 | Y | Y |
支持透明度 | N | Y |
支持动画 | N | Y |
无限循环 | N | Y |
逻辑屏幕描述
全局调色板
图形控制扩展
可以看到图形控制扩展块的第五位、第六位字节表示就是当前帧的延时时间。注意这里是十六进制数,需要转成十进制才是我们需要的时间。
图像描述
图像数据
文件尾
工具化
知道了格式后,工具的思路就很简单了,查找到各图片帧的延时时间,通过数量就知道有多少帧,再计算各帧的时间与总时间的比例,转换成百分比,输出 CSS 就可以了。
实现出来的界面大概是这样
由于只是个临时工具,加上问题好像也很冷门,就没有对外开放了(差点源码都找不到了 😅 )。
更进一步的想法,就是读取 GIF 的每一帧图片,自动生成雪碧图1和 CSS 动画关键帧代码。不过这个功能用 air 不好实现,而且现有的前端工作流其实也支持类似的功能,像自动生成雪碧图等。搜了下,有个叫 ImageMagick 的图像处理库能很好解决这个问题,用法可以看这个《「CSS3」ImageMagick - 从 gif 建立雪碧图动画 - Sprite Sheet Animation》。至此,动画实现的效率有了明显提升,只希望项目能坚持得更长时间。
我的博客即将同步至腾讯云开发者社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=uakteiz4tcry
-
雪碧图是根据 CSS sprite 音译过来的,就是将很多很多的小图标放在一张图片上,就称之为雪碧图。 ↩