最新消息:

[刘欢]HTML5动画与动效之三逐帧动画[前端入门系列]

HTML/CSS William 1576浏览

【前端入门系列】HTML5动画与动效(之三)

在本系列的前两篇文章中我们分别对transition和animation动画有了基础的了解,这两种动画基本都是基于某种“属性参数变化”的动画。而当我们需要制作一些通过属性变化无法实现的动画效果时,就需要使用逐帧动画。在本篇教程中我们将介绍简单的逐帧动画做法,通过制作一段简单的跑步动画来演示HTML5中以图片序列来实现逐帧动画效果的方法。

逐帧图片绘制

首先,在Illustrator之类的矢量绘图软件中绘制好跑步动作的每一个环节。

创建逐帧动画时,最方便的是使得每一帧的动画都有着相同的大小,我们可以在PhotoShop中完成这一尺寸调整。在此我们将每一帧的内容都设置为300*372像素的宽高。

将以上图像存为PNG图片,命名为run.png。现在,逐帧图片就制作完成了。

由于其中包含了12帧动画,每一帧为300*372像素,则该run.png文件尺寸为3600*372像素。

CSS样式制作

接下来,我们回到HTML文件,为跑步动画准备一个DOM容器,代码如下:

<div class="run"></div>

然后,设置run类的CSS样式,将run.png作为背景,且不重复平铺,设定好容器的宽度和高度,使得在该大小范围内正好能够显示出一帧动画。代码如下:

.run {
	width: 300px;
	height: 372px;
	background: url(run.png) no-repeat;
}

测试页面,现在我们只能看到第一帧的动画内容。

添加animation动画

逐帧动画的基本思路就是通过移动背景图片的位置,来实现图片的切换,进而呈现出动画效果。由于我们的动画一共有12帧,加上动画开头和结尾是同样的两个节点,因此一共需要有13个节点,将100%平均分为13份,则可以得到每个节点的百分比值依次为0%、8.3%、16.7%...100%。在每个节点中,我们只需设置background-position属性,使图片依次向左移动300像素即可。代码如下:

@keyframes run {
	0%, 100% {
		background-position:0 0;
	}
	8.3% {
		background-position:-300px 0;
	}
	16.7% {
		background-position:-600px 0;
	}
	25% {
		background-position:-900px 0;
	}
	33.3% {
		background-position:-1200px 0;
	}
	41.7% {
		background-position:-1500px 0;
	}
	50% {
		background-position:-1800px 0;
	}
	58.3% {
		background-position:-2100px 0;
	}
	66.7% {
		background-position:-2400px 0;
	}
	75% {
		background-position:-2700px 0;
	}
	83.3% {
		background-position:-3000px 0;
	}
	91.7% {
		background-position:-3300px 0;
	}
}

为了精简篇幅,以上代码中我们略去了-webkit-的兼容性写法。接下来,我们为run类设置animation属性,将动画时长设置为900毫秒,并无限循环,代码如下:

.run {
	-webkit-animation: run 900ms infinite;
	animation: run 900ms infinite;
}

测试页面,我们并没有得到预想中的逐帧动画效果,而是背景图片一直向右快速移动的效果。

让动画平滑起来

我们也很容易理解这一效果的产生原因,animation默认背景图片位置在水平方向上发生了位移,因此整个动画过程是以平滑的形式呈现的。我们要使其“一格一格”地显示,则可以使用animation动画的steps方法,使得每一个动画关键帧都以“台阶”而非“线性”的形式显示,代码如下:

.run {
	-webkit-animation: run 900ms steps(1) infinite;
	animation: run 900ms steps(1) infinite;
}

现在再次测试页面,我们就能够看到流畅的逐帧动画了。

逐帧的另一种制作思路

除以上的背景位置切换方式外,我们也可以用多张图片交替呈现的方式制作逐帧动画。

首先,我们要将每一帧单独保存为一个文件,在此可以使用PhotoShop中的切片工具来快速完成该操作。

当完成切片后,我们可以将图片以HTML和图像的形式保存,PhotoShop会自动生成单张且序列化命名的图片文件。

接下来,我们要准备12个div元素,每个div元素用于放置一张图片,其id属性名依次为frame1至frame12,代码如下:

<div class="run">
  <div id="frame1" class="run-pic"></div>
  <div id="frame2" class="run-pic"></div>
  ...
  <div id="frame11" class="run-pic"></div>
  <div id="frame12" class="run-pic"></div>
</div>

接着,使每一个div都以绝对定位的方式显示在run容器的左上角,并为这些div分别设置背景图片。

.run {
	width:300px;
	height:372px;
	position:relative;
}
.run-pic{
	position:absolute;
	width:300px;
	height:372px;
	display:block;
	top:0;
	left:0;
}
#frame1{
	background:url(images/run_01.png);
}
#frame2{
	background:url(images/run_02.png);
}
/*省略其它代码*/
#frame12{
	background:url(images/run_12.png);
}

最后,我们使用jQuery来实现动画效果。我们的制作思路是首先将12张图片全部隐藏,然后将第一张图片显示,停留0.1秒后隐藏,第二张图片则延迟0.1秒显示,刚好接上第一张图片隐藏,第三张图片延迟0.2秒,以此类推。所有12张图片全部显示完毕后,第一张图片再次显示,因此两次动画轮回间需要延迟的时间是其余11张图片的显示时间,即1.1秒。我们可以创建一个loop函数供反复调用,以生成这一动画轮回,而在动画最开始时,则需要通过遍历div元素,为每个元素设置初始的延迟值。代码如下:

<script type="text/javascript">
	$(document).ready(function() {
		$('.run-pic').each(function(index){
			$(this).hide(0).delay(index*100).show(0,loop);
		});
	});
	function loop(){
		$(this).delay(100).hide(0).delay(1100).show(0,loop);
	}
</script>

在以上代码中,每张图片都立即调用hide(0)方法,马上隐藏起来,继而通过delay()方法实现延迟,延迟的时间等于索引值乘以100,因此第一张图片延迟0毫秒,第二张图片延迟100毫秒,第三张图片延迟200毫秒...在经过了延迟时间后,该图片再通过调用show()方法来显示,此时也调用了loop函数,使图片开始进入动画的轮回。测试页面,我们将得到与之前的CSS动画完全相同的逐帧动画效果。

小结

与CSS动画相比,使用JavaScript创建逐帧动画有利也有弊,其弊端是制作过程更加复杂一些,其有利之处在于它对动画的控制能力更强,同时能够呈现更加复杂的动画效果。在实战开发中我们应该根据实际情况灵活地选择动画的实现方式。

此外,除以上两种方式外,我们还可以使用Canvas画布来绘制逐帧动画,在后续文章中将详细介绍具体实现方法。

本例源文件:cloud.ecnu.edu.cn/p/DUD

THE END


via://zhuanlan.zhihu.com/p/27141575

转载请注明:AspxHtml学习分享网 » [刘欢]HTML5动画与动效之三逐帧动画[前端入门系列]