记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图片格式

用支持十六进制的编辑器打开一张 GIF 图,就可以看到这样的一串数据。为方便分析,我用了一张 10*10 的小图,如下:

图片十六进制

文件头

文件头

GIF 有两个版本,分别是 87a 和 89a,区别如下:

  • GIF87a:是在 1987 年年制定的版本。
  • GIF89a:是在 1989 年年制定的版本。在这个版本中,为图像互换格式⽂文档扩充 了了图形控制区块、备注、说明、应⽤用程序接⼝口等四个区块,并提供了了对透明⾊色 和多帧动画的⽀支持。
  GIF87a GIF89a
LZW 压缩 Y Y
支持隔行扫描 Y Y
支持透明度 N Y
支持动画 N Y
无限循环 N Y

逻辑屏幕描述

逻辑屏幕描述

全局调色板

全局调色板

图形控制扩展

图形控制扩展 可以看到图形控制扩展块的第五位、第六位字节表示就是当前帧的延时时间。注意这里是十六进制数,需要转成十进制才是我们需要的时间。

图像描述

图像描述

图像数据

图像数据

文件尾

文件尾

GIF图十六进制字节解析

工具化

知道了格式后,工具的思路就很简单了,查找到各图片帧的延时时间,通过数量就知道有多少帧,再计算各帧的时间与总时间的比例,转换成百分比,输出 CSS 就可以了。

实现出来的界面大概是这样

getGifDelayTime

由于只是个临时工具,加上问题好像也很冷门,就没有对外开放了(差点源码都找不到了 😅 )。

更进一步的想法,就是读取 GIF 的每一帧图片,自动生成雪碧图1和 CSS 动画关键帧代码。不过这个功能用 air 不好实现,而且现有的前端工作流其实也支持类似的功能,像自动生成雪碧图等。搜了下,有个叫 ImageMagick 的图像处理库能很好解决这个问题,用法可以看这个《「CSS3」ImageMagick - 从 gif 建立雪碧图动画 - Sprite Sheet Animation》。至此,动画实现的效率有了明显提升,只希望项目能坚持得更长时间。

我的博客即将同步至腾讯云开发者社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=uakteiz4tcry

  1. 雪碧图是根据 CSS sprite 音译过来的,就是将很多很多的小图标放在一张图片上,就称之为雪碧图。 

讨论