微信号:FrontDev

介绍:分享 Web 前端相关的技术文章、工具资源、精选课程、热点资讯

CSS动画学习指南:原理与实例

2015-10-14 19:57 前端大全

(点击上方,可快速关注)


英文:Tom Waterhouse

译者:伯乐在线 - 段昕理

网址:http://web.jobbole.com/83549/


译者注:这篇文章比较古老了,大概成文于2011年。放在当今急速变化的web前端世界中似乎有些不合时宜。不过究其所写的内容-CSS动画的原理,则万变不离其宗,理解动画的基本原理非常重要,里面提到的12条基础动画原则,对创建高质量的动画效果有着极好的指导意义。当时支持CSS动画属性的浏览器很少,如今几乎所有主流浏览器基本都支持了(别跟我提IE哦)。文章中的代码示例和我们今天写的CSS3动画基本是一致,放在现在的浏览器跑也没有兼容性问题。


现如今 Firefox 和 基于Webkit引擎的浏览器都支持CSS动画了,择日不如撞日,何不尝试一下。抛去技术形态,不管是传统动画、电脑3D动画、Flash或CSS,遵循的动画原理都是相通的。


我们将在文章中初步了解CSS动画,并按照指导原则创建CSS动画。然后将通过实例,使用传统动画原理创建CSS动画。最后,展示一些真实世界里的用例。



CSS 动画属性


在深入之前,我们先写点基础的CSS:


Animation 是CSS的新属性,允许我们不需要借助Javascript或Flash就能为HTML元素(如:div、h1 和 span)创建动画。现在支持这个属性的浏览器有 包含Webkit 引擎的浏览器,如:Safari 4+、Safari for iOS (iOS 2+)、Chrome 1+和Firefox 5。 不支持该属性的浏览器则会忽略动画代码,此时要确保你的页面不完全依赖这个属性。


由于这个技术相对来说较新,需要添加浏览器厂商的前缀。到目前为止,每个浏览器的语法规则都是一样,只是用前缀区分。下面的代码例子中,我们用的是 -webkit 前缀语法。


要为元素添加动画,你只需要将CSS 动画关联到该元素就可以了:


/* This is the animation code. */

@-webkit-keyframes example {

from { transform: scale(2.0); }

to { transform: scale(1.0); }

}

/* This is the element that we apply the animation to. */

div {

-webkit-animation-name: example;

-webkit-animation-duration: 1s;

-webkit-animation-timing-function: ease; /* ease is the default */

-webkit-animation-delay: 1s; /* 0 is the default */

-webkit-animation-iteration-count: 2; /* 1 is the default */

-webkit-animation-direction: alternate; /* normal is the default */

}


首先,我们创建动画代码。这段代码可以出现在CSS文件中的任何位置,只要元素能找到相应动画的名字(animation-name)就可以了。


还有一种更简便的方法为元素添加动画:


div {

-webkit-animation: example 1s ease 1s 2 alternate;

}


这段代码做了一定简化,并没有把所有属性值都写上。如果某些值没有写,浏览器会回退使用默认值。


这些是最基础的。下面我们将展示更多的代码。


使用传统动画原理


在我看来,传统动画的鼻祖迪斯尼,早期在著名的图书《Illusion of Life》里创立了传统动画的12条原则。这些基础原则可以应用到所有类型动画,不过你并不需要像动画专家一样遵循。我们将这12条原则运用到CSS动画实例上,把一个基础动画转变成更加可信的视觉幻象。


虽然只是蹦蹦跳跳的小球,但你可以看出两个版本中的不同世界。


这个例子展示了CSS动画特性。下面的代码中,我们用一些空div元素来展示如何运作;我们都知道这代码不够语义化,但重点在于它将页面变得生动起来,这在以前的浏览器中是绝对做不到的。


挤压和拉伸



这个弹跳球为压扁和拉伸做了很好的展示。如果弹球高速下落并撞击地面,你可以观察到它被挤扁然后在弹回的过程中被拉伸。


在基本常识层面,这个例子让我们的动画有了重量和伸缩的感觉。如果扔一个保龄球,我们不会期待它有任何拉伸,很可能只是会撞坏地面。


可以通过CSS3的属性 transform 来产生压扁和拉伸的效果。


@-webkit-keyframes example {

0% { -webkit-transform: scaleY(1.0); }

50% { -webkit-transform: scaleY(1.2); }

100% { -webkit-transform: scaleY(1.0); }

}


这段代码会将物体纵向(y轴,上下)的比例改变为原始比例的1.2倍,然后回复到原始尺寸。


我们还为这个动画使用了稍微复杂一点的定时器。对于基础动画只需要起始(from)和结束(to)就可以了。但你也可以通过白分比的方式为每个时间点设置动画,就像代码所展示的那样。


挤压效果已经实现了。现在我们利用转换(translate)来移动物体。我们可以它将形变放在一起。


50% {

-webkit-transform: translateY(-300px) scaleY(1.2);

}


转换属性允许我们在不改变基础属性(如 位置、宽度、高度)的前提下操作物体,这就使其非常适合CSS动画。这个特别的转换属性让小球在动画的中间点从地面弹起。


(请注意:要查看这个动画,你需要最新版的Firefox、Chrome或Safari。笔者书写这段文字的时候,Safari浏览器提供了最佳视觉体验。)


(译者注:现如今主流的浏览器都已经能很好的实现动画效果了)


查看挤压和拉伸的效果:http://sandywalker.github.io/examples/css-animation/p1.html


没错,小球看起来还是很糙,不过这个小小的调整是让动画变得逼真的第一步。


预备


预备在主要动作发生之前增加了悬念或力量感。举个例子,在你起跳之前腿部的弯曲有助于观察者预判你下一步会做什么。在我们的弹球例子中,事前增加一个简单的影子表示有东西将要从上面掉下。


查看预备效果:http://sandywalker.github.io/examples/css-animation/p2.html


我们添加了另一个 div 元素代表影子,这样我们可以单独的为其设置动画。


要在这里增加预期,我们需要让小球快速掉入场景中。通过适配各百分比的时间点来实现,小球在开始点和第一个动作之间没有移动。


@-webkit-keyframes example {

0% { -webkit-transform: translateY(-300px) scaleY(1.2); }

35% { -webkit-transform: translateY(-300px) scaleY(1.2); } /* Same position as 0% */

65% { -webkit-transform: translateY(0px) scaleY(1.2); } /* Starts moving after 35% to this position */

67% { -webkit-transform: translateY(10px) scaleY(0.8); }

85% { -webkit-transform: translateY(-100px) scaleY(1.2); }

100% { -webkit-transform: translateY(0px); }

}


在动画的35%的时间点前,小球在场景中的位置没有发生变化,没有移动。然后在 35% 到 65%,小球忽然出现在舞台上,剩下的动画紧接着跟上。


也可以使用动画延迟(animation-delay)来实现预备:


div {

-webkit-animation-delay: 1s;

}


舞台



现在试试把舞台添加到场景中,将动画放入环境中。回顾一下迪士尼的电影,如果去掉了奇妙的背景会变成什么样?这是魔法的半壁江山。


舞台也是吸引注意的关键元素。与剧院的舞台一样,光线总是照射到最重要的区域。舞台应该加入到视野中。除了弹球,我为弹球的降落添加了一个简单的背景。这样看客就知道舞台的中央会出现动画,场景也就可以从一片大白雪(白色区域)中脱颖而出了。


逐帧 VS 状态到状态


在传统动画中,可以选择如何构成自己的动画。逐帧意味着需要画出序列的每一帧。状态到状态意味着创建序列的少数关键帧,然后填充中间的间隔。填充间隔在被称作渐变(“in-betweening”或“tweening”),这是制作Flash动画的术语。


在CSS动画中,我们通常使用第二种方式,状态到状态。就是说,我们将为动作添加关键帧,之后浏览器将会自动在这些关键帧直接做渐变平滑处理。当然,我们同样也能向逐帧技术学习。浏览器只提供有限的动画效果;有时候,你为达到某种的效果时,必须采用更困难的方式为多种动画做拼接。


惯性和重叠


和物理世界一样!惯性和重叠常用在人物的身体移动中,例如人物胳膊的摇摆或头发的下落。想象一个人顶着大肚腩快速的转身:他们的身体先转过来,然后肚腩迅速跟上。


对我们来说,这意味着当球掉落时需要使其符合物理定律。上面的例子中小球掉落很不自然,就跟没有受到重力的影响一样。我们希望小球掉落,然后弹起。不过得讲完下一原则才能实现。


慢进慢出


这是与加速或减速有关。想象一个超速的汽车需要停下来。如果它瞬间就停下来,肯定没人信。我们知道汽车需要时间来减速,所以要先让汽车刹车并缓慢停止。


还有一个和重力相关的效果。想象儿童荡秋千。当他们达到最高点时会减速,当返回到最低点时又会加速。最快的速度出现在弧面的底部。然后上升到相反的方向,如此反复。



回到我们的例子,调整进和出的速度可以让小球的运动(最终)更加可信。


当球撞击地面,碰撞会使起迅速弹回。当抵达最高点,它会减速。这样看起来小球像是真正的掉落。


在 CSS 中,我们可以控制 animation-timing-function 属性:


-webkit-animation-timing-function: ease-out;


这些属性包含以下这些值:


  • ease-in 开始时缓慢,然后加速。

  • ease-out 开始时快速,然后减速直到停止。

  • ease-in-out 开始缓慢,一直加速到中段,然后减速直到停止。

  • linear 一直保持匀速。


你还可以使用贝塞尔曲线来创建自定义的缓动速度。


查看慢进慢出效果:http://sandywalker.github.io/examples/css-animation/p6.html


弧线



与遵循物理定律类似,弧线遵循的基本原则叫做“上升的东西必然落下”。弧线在思考物体运动轨迹时非常有用。


这个动画用 CSS 来实现稍微繁琐一点。我们想让小球上下运动的同时往边上移动。所以,我们让小球从左边平滑进入的同时保持弹跳动画。与其把所有的动作都放到一个动画中,不如做两个独立的动画更简单。在这个例子里,我们将小球用另一个 div 元素包裹,然后单独添加动画。


HTML


<div class="ball-arc">

<div class="ball"></div>

</div>


CSS


.ball-arc {

-webkit-animation: ball-x 2.5s cubic-bezier(0, 0, 0.35, 1);

}

/* cubic-bezier here is to adjust the animation-timing speed.

This example makes the ball take longer to slow down. */

/* 这的贝塞尔曲线用作调整动画的速度。

这个例子使小球的减速时间更长了*/

@-webkit-keyframes ball-x {

0% { -webkit-transform: translateX(-275px); }

100% { -webkit-transform: translateX(0px); }

}


这样,我们通过一个动画移动小球的侧方向(ball-x),另一个动画控制小球的弹跳(ball-y)。 这个方法唯一不好的地方在于,如果你想做的事情很复杂,最终会让你陷入一堆缺乏语义的代码堆砌之中。


查看弧线效果:http://sandywalker.github.io/examples/css-animation/p7.html


辅助动画


辅助动画是让动画显得更加真实的微妙之处。辅助动画致力于细节。打个比方,如果有一个留着长发的人行走,主动作是行走,辅助动作是头发的摆动,或者也可能是衣服的褶皱随风变化。


我们的例子和这个非常相似。为了增加小球的更多细节,我们制作小球纹理的辅助动画。这样就造成了小球是被扔进来的错觉。


这次不再为这个动画添加另一个div元素,我们添加一个 img 图像元素充当小球的纹理。


.ball img {

-webkit-animation: spin 2.5s;

}

@-webkit-keyframes spin {

0% { -webkit-transform: rotate(-180deg); }

100% { -webkit-transform: rotate(360deg); }

}


查看辅助动画:http://sandywalker.github.io/examples/css-animation/p8.html


定时



这条原则只针对动画定时。如果动画的定时控制得越好,就越接近真实世界。


小球的例子完美的阐释了这个观点。例子中的小球很轻,设定这个速度合适的。如果是一个保龄球,我们会希望它下落的速度更快。而如果动画比现在更慢,则看起来像是在太空中打网球。选择合适的时间点会让你的动画看起来更真实。


可以很方便地通过 animation-duration 来调整时长,也可以通过动画的百分比设置单独的时长。


夸张


卡通片以夸张或难以置信的物理特性著称。一个卡通人物可以变形成任何形状然后在恢复正常。在很多应用场景中,通过夸张来突出,让动画富有活力。否则看起来会很平淡。


尽管如此,使用夸张效果时需要谨慎。迪士尼有一个符合现实原则的方法,但稍微推进了一步。想象一个角色朝墙里跑,它的身体会被压扁的特别夸张,用来强调碰撞的力量。


我们使用挤压和拉伸的夸张手法让小球对地面的撞击更加明显。我还为动画添加了更精致的摇晃。最后,我们在球的弹跳过程中拉伸小球来突出速度感。


就像之前添加动画的做法一样,我们再添加一个 div 元素,这个元素使小球撞击地面时同时产生摇晃。


@-webkit-keyframes wobble {

0%, 24%, 54%, 74%, 86%, 96%, 100% {

-webkit-transform: scaleX(1.0);

/* Make the ball a normal size at these points */

}

25%, 55%, 75% {

-webkit-transform: scaleX(1.3) scaleY(0.8) translateY(10px);

/* Points hitting the floor: squash effect */

}

30%, 60%, 80% {

-webkit-transform: scaleX(0.8) scaleY(1.2);

/* Wobble inwards after hitting the floor */

}

75%, 87% {

-webkit-transform: scaleX(1.2);

/* Subtler squash for the last few bounces */

}

97% -webkit-transform: scaleX(1.1);

/* Even subtler squash for last bounce */

}

}


这段代码看起来比之前复杂了不少。这是简单的试错。在找到合适的效果钱需要反复尝试。


查看夸张效果:http://sandywalker.github.io/examples/css-animation/p10.html


扎实绘图及角色魅力


能够教你就这么多了……至少在代码方面。最后这两条动画原则无法通过代码来体现。他们是你日后需要完善的技能,使你最终能制作真正迷人的动画。


当迪士尼开始制作白雪公主的动画时,他们的动画师被派回去重新学习写生和人体结构。这种对细节的关注在影片中可见一斑。这正好说明良好的动画需要扎实的绘画功底和声乐知识。


大多数的CSS动画和错综复杂的数字动画不大相同,但是基础原则是一致的。无论是透过正在打开的门显示内容,还是正在密封并发送一封“联系我们”的信封,动画都必须是可信的,不能像机器一样……除非你制作的就是机器动画。


每一个动画角色都有独特的魅力。就像迪士尼总给我们展示的,任何事物都可以有性格:一个茶壶、一棵树、甚至是勺子。但在CSS的世界里,需要考虑整体动画如何有助于设计,使整体的体验更令人满意。我们不想在此制作大眼怪的动画。


奔跑吧动画!


CSS的动画特性非常棒。和每一个CSS新特性一样,一开始容易被过度使用和错误的使用。甚至有点会重蹈Flash复杂动画页面覆辙的危险。尽管我有信心Web社区应该不会这么做。


CSS动画能让网站变得有生机。也许我们的小球动画不够简洁,但它向我们展示一种利用CSS让页面上任何元素变鲜活的可能。


CSS动画还可以让页面上的元素更容易互动,让页面更有意思。结合JavaScript,甚至能成为制作游戏动画的另一条路。将上面的12条原则应用在你的动画中,能使你的网站更有信服力、更诱人、更有趣,从而带来更好的完整体验。


译者推荐:


如果你和我一样懒,想制作CSS动画又不想写复杂的CSS3代码,这有两个非常不错的CSS3开源动画库推荐给你,Animate.css和CSS3 ANIMATION CHEAT SHEET。另外译者也编写了一个CSS3动画制作库H5Show,让你轻松的创建时下流行的Html5演示动画。当然想制作出高水准的动画,理解文章中的12条动画原则非常重要。




前端大全

微信号:FrontDev

打造东半球最好的 前端技术 微信号

--------------------------------------

商务合作QQ:2302462408

投稿网址:top.jobbole.com




 
前端大全 更多文章 5个典型的JavaScript面试题(上) Limu:JavaScript的那些书 Web开发:我希望得到的编程学习路线图 JavaScript基础工具清单 常用排序算法之JavaScript实现
猜您喜欢 Android系统字体规范与应用探索 模块智能手机:一种概念,还是一种颠覆? 让Lambda代码穿行于多个云端 梯度下降法求解线性回归之python实现 四招进击字体达人!