CSS3的Transition
PUBLISHED
简介
由于动画的产生,网站和Web应用程序变得更具互动性和生动。 静态网站的时代已经过去了。 动画菜单,幻灯片,交互式的图表是现在大多数应用程序的组成部分。 引入CSS的第三个版本之前,为了制作动画,我们不得不使用外部库像jQuery或script.aculo.us。 现在我们有两个强大的功能,它们是transition和keyframe。 本文重点讲transition。
实例程序已经在Tizen SDK 2.1.0上测试通过。
什么是CSS3的transition?
Transition在CSS的第三个版本中被引入。 由于transition的存在,我们可以随时操纵一个元素的特定属性。 Transition由Tizen’s WebKit引擎提供支持。 我们能控制这些属性,如位置,大小,旋转,颜色,透明度,字体设置,页边距,填充或者更多。 去这个地址http://www.w3.org/TR/css3-transitions/#animation-of-property-types - 你可以检查什么属性类型可以设置动画。 唯一的要求是,它必须是可以计算要改变的属性的中间值。 例如,你不能为font-family属性设置动画,因为它的值是一个立即操作数。
Transition属性
我们可以通过四个属性来控制transition。 第一个是 transition-property
这个属性可以选择为宽度,透明度,颜色等CSS属性设置动画。 第二个是 transition-duration
用来控制动画的持续时间(以秒或毫秒的形式)。 下一个是 transition-timing-function
这个属性可以操作属性值的随时间变化的方式,比如指数级上升。 这将在后面详细描述。 最后一个是 transition-delay
它延迟了动画的执行时间(以秒或毫秒的形式)。 下面的代码显示了transition的用法的例子。
transition-property: width; transition-duration: 1s; /* in seconds */ transition-timing-function: ease-in; /* slow at the beginning, fast at the end */ transition-delay: 250ms; /* in milliseconds */
所有的代码都可以写到一行里面,因为 transition
有可以简写的特性。 属性需要按照下面的次序排放: property
, duration
, timing function
, delay
。 最后两个是可选的,且他们的缺省值是 ease
和 0
。
transition: width 1s ease-in 250ms;
如果要对多个属性设置动画,可以用逗号来隔开,参考下面的代码。
/* long version */ /* animate width for 1 second and opacity for 2 seconds */ transition-property: width, opacity; transition-duration: 1s, 2s; /* short version */ transition: width 1s, opacity 2s;
timing功能需要重点关注一下。 timing可以是下面一些预定义的值: linear
(线性的) ease
(默认值;开始的瞬间加速,结束的慢慢减速), ease-in
(加速), ease-out
(减速), ease-in-out
(开始的时候加速,结束的时候减速)。 每个值是三次Bezier曲线。 要了解更多,请参考:http://en.wikipedia.org/wiki/B%C3%A9zier_curve. 简单的说,这是一个曲线,其形状由控制点操作。 在CSS中,我们使用4点(立方)曲线。 默认的两个点的位置分别是<0,0>和<1,1>,所以我们还要定义两个中间点。 下图显示CSS3中预定义的不同的贝塞尔曲线。 你可以看到如何值随时间变化的快慢。 X轴是时间轴(向右增长),Y轴是表示值的轴(向上增长)。
图1:CSS3中预定义的贝塞尔曲线。
您可以通过给立方贝塞尔函数值来定义自己的 transition-timing-function
属性曲线。 它需要4个参数:X1,Y1,X2,Y2,这四个参数用来指示两个中间点的X轴和Y轴的位置。 你可以试着用以下的例子网站创建自己的曲线: http://cubic-bezier.com, http://matthewlein.com/ceaser/. 下面的代码给出了贝塞尔函数的用法的例子。
执行动画
现在,我们开始做动画。 我们可以通过多种方式来为元素属性设置动画。 我们可以直接通过JavaScript或通过添加/删除类来改变属性值,修改元素的样式属性。 还有一个办法。 你可以使用CSS的伪类,比如: :hover
, :active
, :focus
等。 你只需要改变一个属性的值,动画就会开始 - 就这么简单。 下面是示例的代码。
HTML 代码:
<html> <head> <meta charset="utf-8" /> <meta name="viewport" content="user-scalable=no, width=720, height=1280"> <style type="text/css">/* CSS code here */</style> <script type="text/javascript">/* JS code here */</script> </head> <body> <textarea id="pseudo-class-test">Pseudo class test</textarea> <textarea id="js-test">JavaScript style and class manipulation</textarea> </body> </html>
CSS代码:
#pseudo-class-test, #js-test { display: block; width: 200px; height: 100px; background-color: green; /* Animate width and opacity properties */ -webkit-transition: width 0.5s ease-in-out, opacity 0.5s ease-in; transition: width 0.5s ease-in-out, opacity 0.5s ease-in; } #pseudo-class-test:focus { width: 300px; opacity: 0.5; } .width300px { width: 300px !important; }
JavaScript代码:
window.onload = function() { var jsTest = document.getElementById('js-test'); jsTest.onfocus = function() { jsTest.className = 'width300px'; jsTest.style.opacity = 0.5; }; jsTest.onblur = function() { jsTest.className = ''; jsTest.style.opacity = 1; } };
它实际上做的是改变textarea的字段的宽度和不透明度。 当它们获得到焦点时,两个元素的动画就会被触发。 当它们丢失焦点时,属性回来到原来的状态。
如果在动画运行的同时改变动画属性的值,此时将会发生什么现象呢?这是由CSS的层叠和继承规则来决定的。 所以为设置为 style
的属性总是要比在类中设置的属性更加有意义。 !important
的属性会决定元素的格式。 当一个属性的值发生变化,动画会立即停止,刷新新的属性值,并重新开始执行动画。
跨平台/浏览器的兼容性
从2009年12月1日开始,Tizen WebKit引擎就是使用基于W3C草案的transition来实现的。 它不需要前缀,但你的应用程序是跨平台/浏览器兼容的,你需要以-webkit,-moz,-o形式来将它们写成通用的web引擎。 要使其工作,需要编写大量的代码。 幸好有Rico Sta创建的Transit.js插件。 整个任务就是几行JavaScript代码。 这样做的缺陷就是,我们需要将动画逻辑从CSS文件移植成JavaScript代码。 然而,对于大多数人来说,这不是一个问题,因为他们已经习惯使用jQuery。 animate
函数。
要是用Transit.js,我们首先要包含jQuery库(1.4以上版本),然后在transition插件头部中也要包含jQuery库。 你可以从这个网站下载。 要为属性设置动画,我们就要是用“transition”函数,它的语法和jQuery类似。 animate
函数:
// Default syntax $("...").transition(properties [,duration] [,easing] [,callback]); // Default $("...").transition({ opacity: 0.1, scale: 0.3 }); // Specific duration $("...").transition({ opacity: 0.1, scale: 0.3 }, 500); // With duration and easing $("...").transition({ opacity: 0.1, scale: 0.3 }, 500, 'in'); // With callback $("...").transition({ opacity: 0.1, scale: 0.3 }, function () { ... }); // With everything $("...").transition({ opacity: 0.1, scale: 0.3 }, 500, 'in', function () { ... }); // Alternate syntax $("...").transition({ opacity: 0.1, duration: 200, delay: 40, easing: 'in', /* equivalent of ease-in */ complete: function () { /* ... */ } });
正如你所看到的,有几个选项,可帮助您控制动画的持续时间,延迟,缓解函数和回调函数会在动画完成后执行。
那个 properties
函数的参数是需要设置动画的CSS属性列表。 Transit.js可以帮我们省去写供应商的麻烦。 它会检查在什么浏览器中执行代码并自行加上适当的前缀。
duration
和 delay
两个参数的单位是毫秒,当然也可以是字符串(“fast”或者“slow”),这些字符串是jQuery的 animate
函数能识别的。 它们的作用和CSS3的transition是完全相同的。
该 easing
参数是一个字符串,用来指示动画随时间变化的速度。 和CSS3不同的是,CSS3中,每个函数有不同的名称。 下面的代码显示了这些差异。 不幸的是,你不能将自己的贝塞尔曲线作为transition函数的参数,但你有许多预定义的选择。 然而,你可以用自己的easing函数来给 $.cssEase
对象添加新的属性,如下面的代码所示。
$.cssEase = { '_default': 'ease', 'in': 'ease-in', 'out': 'ease-out', 'in-out': 'ease-in-out', 'snap': 'cubic-bezier(0,1,.5,1)', 'easeOutCubic': 'cubic-bezier(.215,.61,.355,1)', 'easeInOutCubic': 'cubic-bezier(.645,.045,.355,1)', 'easeInCirc': 'cubic-bezier(.6,.04,.98,.335)', 'easeOutCirc': 'cubic-bezier(.075,.82,.165,1)', 'easeInOutCirc': 'cubic-bezier(.785,.135,.15,.86)', 'easeInExpo': 'cubic-bezier(.95,.05,.795,.035)', 'easeOutExpo': 'cubic-bezier(.19,1,.22,1)', 'easeInOutExpo': 'cubic-bezier(1,0,0,1)', 'easeInQuad': 'cubic-bezier(.55,.085,.68,.53)', 'easeOutQuad': 'cubic-bezier(.25,.46,.45,.94)', 'easeInOutQuad': 'cubic-bezier(.455,.03,.515,.955)', 'easeInQuart': 'cubic-bezier(.895,.03,.685,.22)', 'easeOutQuart': 'cubic-bezier(.165,.84,.44,1)', 'easeInOutQuart': 'cubic-bezier(.77,0,.175,1)', 'easeInQuint': 'cubic-bezier(.755,.05,.855,.06)', 'easeOutQuint': 'cubic-bezier(.23,1,.32,1)', 'easeInOutQuint': 'cubic-bezier(.86,0,.07,1)', 'easeInSine': 'cubic-bezier(.47,0,.745,.715)', 'easeOutSine': 'cubic-bezier(.39,.575,.565,1)', 'easeInOutSine': 'cubic-bezier(.445,.05,.55,.95)', 'easeInBack': 'cubic-bezier(.6,-.28,.735,.045)', 'easeOutBack': 'cubic-bezier(.175, .885,.32,1.275)', 'easeInOutBack': 'cubic-bezier(.68,-.55,.265,1.55)' }; /* Adding custom easing function. Put this line at the beginning of your code. */ $.cssEase['myEasingFunction'] = 'cubic-bazier(0,1,0,1)';
complete
函数是一个回调函数,该函数会在动画结束是被触发。 它就像调用函数一样简单。 如果我们想要用CSS的transition做同样的事情,我们就需要给该对象添加一个时间监听器。
element.addEventListener('transitionend', callbackFunction);
前缀还是有问题。 我们需要监听5种不同的事件: transitionend
, transitionEnd
, webkitTransitionEnd
, msTransitionEnd
和 oTransitionEnd
。 在这种情况下,使用Transit.js是一个好的选择,因为我们不需要写所有的监听器。
示例应用程序
现在,我将演示如何在Tizen应用中使用CSS3的Transition。 “Transitions”是一个示例应用程序,该应用显示了transition的行为。 下图显示了该应用程序的外观。 用户可以更改下列选项:transition属性,easing函数,动画持续时间和延迟时间。 动画是用过各种方式来启动的,
图2:应用程序截图
该应用程序使用jQuery Mobile的库来显示用户界面,使用jQuery的transi.js插件来执行transition。 所有库都包括在头部分。
<head> <link rel="stylesheet" type="text/css" href="./libs/jquery/jquery.mobile-1.3.0.css"/> <script type="text/javascript" src="./libs/jquery/jquery-1.9.1.min.js"></script> <script type="text/javascript" src="./libs/jquery/jquery.mobile-1.3.0.js"></script> <script type="text/javascript" src="./libs/jquery/jquery.transit.min.js"></script> </head>
应用程序的主要逻辑被放置在./js/main.js文件中。 它包含一个 app
对象定义,这个对象定义了5中公共的方法: init
, setProperty
, setEasing
, setDuration
, setDelay
。 第一种方法被绑定到 onload
事件上。
return { init : _init, setProperty : _setProperty, setEasing : _setEasing, setDuration : _setDuration, setDelay : _setDelay }; }()); window.onload = app.init;
在“init”函数中,我们定义了位段的列表和公共的 onchange
事件监听器。 监听器获取点击区域的ID,并尝试去为 app
对象设置新的值。 这些值会在稍后被一个私有的 _transition
函数用到。
_transition
函数需要特别注意。 该函数将transition从默认值到最终值,再从最终值到默认值反复变化。 它使用delay参数来延迟动画的执行,在 transition in
和 transition out
这两个步骤中。 为了让transition一个接一个的执行,我们用一个回调函数作为 transition
函数的第四个参数。
/* Prepare options to transition out. */ options = { easing : easing, duration : duration, delay: delay, complete : transitionOutComplete } options = jQuery.extend(options, _defaultValues[property]); _$box.transition(options); /* ... */ /* Prepare options for transition in. */ options = { easing : easing, duration : duration, delay: delay, complete : transitionInComplete }; options = jQuery.extend(options, _transitionValues[property]); _animated = true; _$box.transition(options);
_transition
函数在有动画运行时执行其他的动画,这个功能由 _animated
标志来实现。
/* Don't perform transition if another one is already taking place. */ if (_animated) return;
Transition代码是由一个匿名函数调用封装,以确保更改任何transition选项将不会影响已经在运行的动画。 如果忽略这一点,将会发生不可预见的行为。
/* Wrap animation execution with function to make sure that transition * options does not change over time. */ (function (property, easing, duration, delay) { /* Save _transition function code here ... */ }(_property, _easing, _duration, _delay));
总结
在这篇文章中我讲述了CSS3 transition和jQuery的transit.js插件的使用。 我希望这有助于了解什么是transition,以及如何创建Tizen应用与美丽的动画。