逐帧动画实现的四种方式

2016-05-20 H5案例分享 H5案例分享
逐帧动画实现的四种方式

逐帧动画实现CSS3 or JavaScript


我们经常会在H5页面中看到一段序列帧动画,最近小编对此实现方法非常感兴趣,就总结了实现逐帧动画常用的几种实现方法。比如,现在需要实现这个小动画


一、GIF动图

打开PS6,点击窗口→时间轴,在时间轴窗口中有6张不同的图片,通过一帧一帧的播放来实现这个动画。

GIF动画优缺点:
好处:实现简单、可维护性高、工作成本低
缺点:只适合简单的动画效果,不能动态控制动画

在实际的项目中,我们往往根据需求而需要把动画做的更加灵活,那就不是gif动图所能完成的了。下面,我们先探讨有哪些技术可以实现我所说的功能~~~


二、使用CSS3动画

(1)通过切换6张图片的方式来实现,具体代码实现参考如下(篇幅考虑仅列出webkit的写法):

#anim{width:120px; height:120px; position: absolute; top: 50%; left: 50%; margin-top: -60px; margin-left: -60px; -webkit-animation: auto-circle 0.5s step-end infinite; display: none;} @-webkit-keyframes auto-circle{ 0%{background-image:url(images/anim-01.png);} 20%{background-image:url(images/anim-02.png);} 40%{background-image:url(images/anim-03.png);} 60%{background-image:url(images/anim-04.png);} 80%{background-image:url(images/anim-05.png);} 100%{background-image:url(images/anim-06.png);} }

演示demo链接


6张图片合成1张,通过切换背景图片位置来实现,具体代码实现参考如下(篇幅考虑仅列出webkit的写法):

#anim{ background-image: url(images/anim.png); width:120px; height:120px; position: absolute; top: 50%; left: 50%; margin-top: -60px; margin-left: -60px; -webkit-animation: auto-circle 0.5s steps(5) infinite; } @-webkit-keyframes auto-circle{ 100%{background-position-x: 600px;} }

演示demo链接


当然,用雪碧图+CSS3实现还有一些其他的方法:

#anim{ background-image: url(images/anim.png); width:120px; height:120px; position: absolute; top: 50%; left: 50%; margin-top: -60px; margin-left: -60px; -webkit-animation: auto-circle 0.5s step-end infinite; } @-webkit-keyframes auto-circle{ 0%{background-position-x: 0;} 20%{background-position-x: 120px;} 40%{background-position-x: 240px;} 60%{ background-position-x: 360px;} 80%{background-position-x: 480px;} 100%{background-position-x: 600px;} }

演示demo链接


#animbg{ width:120px; height:120px; position: absolute; top: 50%; left: 50%; margin-top: -60px; margin-left: -60px; overflow: hidden; } #anim{-webkit-animation: auto-circle 0.5s step-end infinite;;} @-webkit-keyframes auto-circle{ 0%{-webkit-transform:translate3d(0,0,0);} 20%{-webkit-transform:translate3d(-120px,0,0);} 40%{-webkit-transform:translate3d(-240px,0,0);} 60%{-webkit-transform:translate3d(-360px,0,0);} 80%{-webkit-transform:translate3d(-480px,0,0);} 100%{-webkit-transform:translate3d(-600px,0,0);} }

演示demo链接


分析使用6张图片和1张雪碧图这两种方式

方式一:

实现起来会比较简单,但带来额外的5个请求数

6张图片总大小为:56.5k

加载时间:


方式二:

需要设计雪碧图,并量取背景位置,请求数少

雪碧图大小为:44.9k

加载时间:


由上面的分析可以看出,多张图片合成的雪碧图比6张图片还少 11.6k 外,还可以减少5个HTTP请求,并且加载时间也会大大减少,当然加载时间有时也会根据用户当前所处的网络环境而有所不同,综上所述,还是使用切换背景位置方式是比较好的。


三:使用JavaScript操作CSS属性

(1)采用6张图片依次显隐的方式,具体代码实现参考如下:

$(function(){ var animImg = 1; var animImages = setInterval(function () { animImg++; if (animImg >= 7) { animImg = 1; } $(".animImg").hide(); $(".animImg" + animImg).show(); }, 100); });

演示demo链接


(2)采用雪碧图,通过javascript不断的改变帧图片的background-position,具体代码实现参考如下:

(function(){ window.frameAnimation = { anims:(function(){ /* obj=>需要执行背景动画的对象; width:图片的总宽度 steps=>需要的帧数; eachtime=>一次完整动画需要的时间; times=>动画执行的次数 0表示无限反复 */ return function(obj,width,steps,eachtime,times, callback){ var runing = false; var handler = null; //obj,width,steps,eachtime,times定时器 var step = 0; //当前帧 var time = 0; //当前第几轮 var speed = eachtime*500/steps; //间隔时间 var oneStepWidth = width/steps; function _play(){ if(step >= steps){ step = 0; time++; } if(0 == times || time < times){ obj.css('background-position', -oneStepWidth * step + 'px 0px'); step++; }else{ control.stop(); callback && callback(); } } var control = { start:function(){ if(!runing){ runing = true; step = time = 0; handler = setInterval(_play, speed); } return this; } ,stop:function(restart){ if(runing){ runing = false; if(handler){ clearInterval(handler); handler = null; } if(restart){ obj.css('background-position', '0 0'); step = 0; time = 0; } } } ,dispose:function(){ this.stop(); //console.log('anim dispose'); } }; return control; } })() } })(window); function play(){ var anim = frameAnimation.anims($('#anim'),720,6,1,0); anim.start(); }

演示demo链接


四、使用Canvas

说到帧动画,很容易就联想到canvas,将图片绘制到canvas上面,不断重绘就能得到我们想要的效果。使用canvas的好处是,只要有一个基于canvas模拟帧动画的类库,就可以随意使用。操作JavaScript比操作css要灵活,可以传递各种参数实现不同的要求,还可以使用回调函数来设置动画结束时的操作。缺点是老式浏览器不兼容canvas,而且如果需求简单的话,使用canvas有些大材小用。一个最简单的循环动画类如下所示:

var loader; var img; var stage; var w; var h; window.onload=function(){ stage = new createjs.Stage('animCanvas');//创建舞台 w=stage.canvas.width; h=stage.canvas.height; $('#animCanvas').css({'height':120+'px','width':120+'px'});//适配用 manifest = [ {src: 'anim.png', id: 'img'}, ];//预加载 loader = new createjs.LoadQueue(false); loader.addEventListener('complete', handleComplete);//加载完成 调用handleComplete函数 loader.addEventListener('progress', handleFileProgress);//加载完成 调用handleFileProgress函数 loader.loadManifest(manifest, true, 'images/'); } function handleComplete(){//加载完成调用函数 var spriteSheet = new createjs.SpriteSheet({//创建精灵 framerate: 60, 'images': [loader.getResult('img')], 'frames': {'regX':0, 'height':120, 'count':6, 'regY': 0, 'width': 120}, 'animations': { 'anim': [0, 5, 'anim'], } }); img = new createjs.Sprite(spriteSheet, 'anim'); stage.addChild(img);//将img加载到舞台上 createjs.Ticker.addEventListener('tick', tick);//刷新 createjs.Ticker.setFPS(10); //每秒调用tick函数 3次 控制动画快慢 } function handleFileProgress(event){//加载中函数 console.log(loader.progress*100|0+'%'); } function tick(e){//tick函数 stage.update(event);//更新舞台 }

演示demo链接


总结:

综上所述,现在使用一个简单的表格来汇总逐帧动画常见的制作手法,希望读完本文的小伙伴们都可以在下次遇见这类动画效果时,第一时间挖掘出它背后的制作原理,好好运用这四种实现方法,(表格中所阐述的性能损耗和实现成本等仅作参考)。




上面表格看起来还是有些杂乱,还是弄一个简单的表吧,如下表所示:



四种方法各有优势和劣势。如果明确了浏览器的型号和版本支持css3时,推荐使用CSS3的方法。如果是为了广泛使用,推荐使用JavaScript的方法。当序列帧很简单的时候,不建议使用canvas来实现功能。当需要实现复杂动画或者做游戏开发的时候,使用canvas较好,可以灵活的对动画进行操作设置。




以上为“H5案例分享”团队原创文章,转载请注明出处!

标签

分享:
海报
案列链接
下载截图
收藏案例
已收藏
分享到微信朋友圈
打开微信,点击底部的“发现”,
使用“扫一扫”即可将网页分享至朋友圈。

相关推荐:

html5新增的input类型

旋屏提示

关注微信号:h5-share,获取更多创意H5案例分享!也可访问H5案例分享网站www.h5anli.com,搜索查阅~

阅读原文

微信扫一扫
关注该公众号

收藏

微信极速登录/注册

对汉语支持不错,别对小五说英文

微信公众号

提交案例

请pc端输入网址

"h5anli.com"

下载截图压缩包~

标签已提交成功

小编正在审核

请等待一下下啦

哎呀

标签已存在

换个新的呗~