用视频软件AE + bodymovin制作网页动画

我们知道,做动画有多种形式,可以用CSS的animation,也可以用Canvas,或者是用JS控制CSS的属性形成动画。我们经常使用CSS做一些比较简单的动画,像过度、加载的动画,对于一些比较复杂的,可能会做成gif,或者是用Canvas,使用Canvas的控制粒度可以很细,同时工作量相对也比较大。做动画还有其它的方式,那就是使用After Effect(AE)/Flash/Premiere(Pr)/会声会影等视频软件,这种可视化的制作方式相对于直接写代码来说,会更容易简单自然。做动画本身应该使用工具进行制作,但是这种视频软件做出来的动画最后都是生成视频文件,并且通常体积还很大,没有办法直接移植到网页上去。

然而好消息是,现在我们可以使用AE做动画,然后使用bodymovin插件导出成html文件进行播放。AE是Adobe推出的一个很出名的视频后期处理软件,有些电影就是用AE做的,如变形金刚,还有人把AE当成加强版PS使用。也就是说假如我们可以AE做出一些电影级别的效果,然后用html播放,那是一件多么酷炫的事情。

1. 安装bodymovin

bodymovin是一个AE的一个开源的第三方扩展,github地址。上面可以下载这个插件。然后再安装一个ZXPInstaller来安装这个文件,然后重启AE就可以了,当然前提是你要安装一个AE。它支持AE CC版本:
After EffectsCC 2017, CC 2015.3, CC 2015, CC 2014
安装完之后,点击AE的菜单Window -> Extensions -> Bodymovin就会弹出一个窗口:

2. 使用AE制作动画

我相信很多人都没有玩过AE,所以这里我简单地介绍一下。首先新建一个工程(project),然后新建一个合成(composition),选择1080p/29fps,时长为10s,它就会创建一个10s的合成。如下时间轴面板的显示:

这个时间轴将会是频繁操作的地方。点击文字工具,在上方的预览窗口选中一个位置点击创建文字,然后把它拖到窗口外面,因为我们准备做一个文字从外面进来的动画,所以刚开始它是在外面的。把上图右边的蓝色竖线表示的时间线拖到0s的位置,然后在左边的文字图层的Position属性打一个关键帧,如下图所示:

然后把时间线挪到3s的位置,改变文字的Position,把它挪到窗口的中间,这个时候AE会自动在时间线的位置打一个关键帧,如下图所示:

然后按一下空格键进行预览,预览窗口就会播放起了我们刚刚设定的动画:

你会发现,这个过程不是和CSS的keyframe动画一样的么?没错!动画的原理都是一样,通过设定关键帧制作动画。现在来比较一下用AE和用CSS/Canvas做这个动画的区别。

3. 关键帧动画

现在用CSS做这个动画,如下代码所示:

<style>
.text{
    animation: move 3s linear infinite;
}

@keyframes move{
    from{
        transform: translateX(-320px);
    }
    to{
        transform: translateX(100px);
    }
}
</style>
<div class="container">
    <p class="text">Hello, frontend</p>
</div>

我们给animation添加一个动画,这个动画有两个关键帧,分别在0%和100%的位置,需要变化的是transform的属性。这段代码在浏览器运行,就会有刚刚用AE做的动画的效果了。如果用Canvas呢,应该怎么实现呢?

如下代码所示:

<canvas id="text-move" width="600" height="400"></canvas>
<script>
!function(){
    window.requestAnimationFrame(draw);
    var canvas = document.querySelector("#text-move"),
        ctx = canvas.getContext("2d");
    function draw(){
        //计算文字position
        var textPosition = getPosition();
        drawText();
        window.requestAnimationFrame(draw);
    }    
}();

这个是canvas动画的基本框架,先注册requestAnimationFrame的draw函数,使得浏览器在重新绘制屏幕时会先调一下这个函数,理想情况下1s会绘制60幅图片,也就是说1s为60帧/60fps。

上面代码最关键的地方是在于计算文字位置position,同样地,也是要先设定初始位置和终点位置还有动画时间,从而知道移动的速度v,即每1s多少距离,记录一个动画开始时间,然后在每次draw的时候用Date.now()获取当前时间减掉开始时间,就得到时间t,然后用v * t就可以得到位移。这就是用Cavans做动画的基本原理,我们看到,用Canvas需要自己实现一个关键帧系统。

从抽象级别来看的话,AE > CSS >> Canvas,使用AE我只需要拖一拖,然后打上几个关键帧,而使用CSS,我需要把我的操作写成代码,而使用Canvas我需要从0开始一点一点去控制,当然你可以使用一些动画和游戏的引擎提高效率。所以如果有一个可视化界面让你去完成一些复杂的操作,和让你一行一行去写代码的方式选择的话,我想大部分人应该会选择前者。当然这两者的区别不仅仅是操作上的简便性,使用AE借用插件还可以快速地制作出一些复杂的效果。

4. bodymovin小试牛刀

刚刚已经用AE做了一个最简单的动画,现在用bodywin把它导出来。打开bodymovin,选中合层,选择输出路径,如下图所示:

然后点击Render,完成它会输出一个json文件,打开这个导出的文件:

{"v":"4.10.1","fr":29.9700012207031,"ip":0,"op":95.0000038694293,"w":1920,"h":1080,"nm":"Comp 1","ddd":0,"assets":[],"fonts":{"list":[{"origin":0,"fPath":"","fClass":"","fFamily":"Myriad Pro","fWeight":"","fStyle":"Regular","fName":"MyriadPro-Regular","ascent":70.9991455078125}]},"layers":[{"ddd":0,"ind":1,"ty":5,"nm":"hello, frontend","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":0,"s":[-1017,692,0],"e":[458,692,0],"to":[245.83332824707,0,0],"ti":[-245.83332824707,0,0]},{"t":90.0000036657751}],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"t":{"d":{"k":[{"s":{"s":164,"f":"MyriadPro-Regular","t":"hello, frontend","j":0,"tr":0,"lh":196.8,"ls":0,"fc":[0,0.64,1]},"t":0}]},"p":{},"m":{"g":1,"a":{"a":0,"k":[0,0],"ix":2}},"a":[]},"ip":0,"op":300.00001221925,"st":0,"bm":0}]}

这个文件记录了所有动画的过程,如上加粗字体是我们刚刚打的两个关键帧的位置。然后安装一下bodymovin的引擎,可在github上面下载bodymovin.js或者是npm install一下:

npm install bodymovin

然后就可以使用bodymovin了,如下html:

<!DOCType html>
<html>
<head>
    <meta charset="utf-8">
</head>
<body>
    <div id="animation-container" style="width:100%"></div>
    <script src="node_modules/bodymovin/build/player/bodymovin.js"></script>
    <script src="index.js"></script>
</body>
</html>

index.js如下代码所示:

var animation = bodymovin.loadAnimation({
    container: document.getElementById('animation-container'),
    renderer: 'canvas', //svg、html
    loop: true,
    autoplay: true,
    path: 'data.json'
})

调用它的loadAnimation的API,传几个参数,它支持canvas/svg/html三种形式,也就是说它可以用canvas做动画,也可以用svg和html,其中canvas的性能最高,但是canvas有很多效果不支持。data.json的位置通过path告诉它。所有的动画就通过改变path指向的data.json文件区分,而其它的参数不用变。也就是说所有的动画内容和效果都是通过data.json控制的。

现在在浏览器上面运行一下,你会发现报了一个错:

后来发现这个错误是因为文字的原因,如果是用canvas的方式的时候要把文字导成svg的形式,而不是一个纯文本然后通过设置font-family,这个可以在bodymovin里面进行设置,如下图所示:

还可以直接导出一个完整的demo,直接打开html就可以运行,这个比较方便。效果如下(git需要点击查看原图才能播放):

并且我们发现,它的大小和位移都是相对于容器的,当你把窗口拉小,它也会跟着变小。当使用svg的时候,它是用JS控制svg path标签的transform:

当使用html时,它是控制CSS的transform:

我们一个hello, world的工程已经可以跑起来,bodymovin能支持多复杂的动画呢?

5. AE的摄像机

用AE做动画的时候经常会用到AE的摄像机图层,所谓摄像机就是一个视角,默认情况下这台摄像机是从正前方中间拍过去的,我们可以改变这台摄像机的位置,如把摄像机往前推那么内容就会放大,把摄像机往左右移动,那么看到的内容就会发生倾斜,它有很多仿摄像机的参数可以控制:

摄像机属性都可以通过打关键帧做动画,现在我们加上摄像机做3d的动画。做完后,如果还用canvas的话,它会提示你不能使用canvas,因为它目测不支持WebGL转换,如下图所示:

提示说使用了一个3d camera,尝试使用html renderer,这里要改成html。最后的效果如下:

通过检查,可以看到摄像机也是用transform的matrix控制的。完整的dmo可见这个链接
然后我们再继续做复杂的动画

6. 复杂动画

在所有特效里面,笔者最喜欢的是粒子效果,这种效果也是电影里面经常用到的特效,如冰雪女王的冰雪魔法:

还有文字的粒子效果:

但是这种效果我试了一下没有办法导出来,这种效果本身就比较复杂,渲染起来比较耗时,在html实时播放也不太现实。

还有有时候会报一些奇怪的错误,最常报的一个错误是这个:

bodymovin.js:9249 Uncaught TypeError: this.addTo3dContainer is not a function

可能是使用了一些特定效果,触发了它的bug。

但是不要沮丧,我们还是可以导出一些复杂的效果的,做动画这种关键还是在于idea。

例如可以做一个装饰的小动画,如下所示:

一个完整的demo见这个网址
还可以做一个相册视频,效果如下:

完整的demo见这个网址
如果是做成一个1080p的视频,1.5分钟的mp4格式就算压得比较厉害也要100多MB,但是现在我只要加载一个90kb的json文件和一个240kB的库文件以及10Mb左右的图片就可以了。并且里面的文字和图形还是矢量的。
现在来看一下CPU消耗,可以看到这个相册视频svg动画还是很耗CPU的,但是你开一个视频播放器也同样挺消耗CPU资源的。

不管怎么样,bodymovin提供了另外一种做网页动画的全新方式,摆脱那种纯代码控制的黑暗,甚至你都不用学Canvas和WebGL,也可以做出很酷炫的动画。但是无疑这种方式存在一种弊端,那就是没办法添加参数控制,例如我做一个愤怒的小鸟,我得通过拉弓的方向和力度以及小鸟的重量去计算它的轨迹。但是用AE做的只能是纯动画。所以平时可以两者结合。

bodymovin还支持转成IOS/Android代码,我感觉这个东西发展还在初级阶段,网上也没有很多关于这个的介绍。但是随着这个的认可度提升,发展越来越好,说不定以后能够支持更多的特效,甚至可以提供参数支持。

原文: 用视频软件AE + bodymovin制作网页动画

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,457评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,837评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,696评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,183评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,057评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,105评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,520评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,211评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,482评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,574评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,353评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,897评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,489评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,683评论 2 335

推荐阅读更多精彩内容

  • 我的博客地址:www.viggoz.com这篇文章简单总结了一下网页和移动App中动画的实现方法,bodymovi...
    viggoz阅读 26,270评论 14 48
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,053评论 25 707
  • 在iOS中随处都可以看到绚丽的动画效果,实现这些动画的过程并不复杂,今天将带大家一窥iOS动画全貌。在这里你可以看...
    F麦子阅读 5,066评论 5 13
  • 一、工作区和工作流程 1.工作区和面板 保存、删除、重置工作区停靠、编组、浮动面板 2.首选项 常规、预览、导入、...
    朱细细阅读 7,367评论 0 53
  • 例:js特效第5天,注册登录案例
    请叫我吉先生阅读 190评论 0 0