CSS3的Transition

简介

由于动画的产生,网站和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, durationtiming functiondelay。 最后两个是可选的,且他们的缺省值是 ease0

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轴是表示值的轴(向上增长)。

CSS3中预定义的贝塞尔曲线

图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可以帮我们省去写供应商的麻烦。 它会检查在什么浏览器中执行代码并自行加上适当的前缀。

durationdelay 两个参数的单位是毫秒,当然也可以是字符串(“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种不同的事件: transitionendtransitionEndwebkitTransitionEndmsTransitionEndoTransitionEnd。 在这种情况下,使用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中公共的方法: initsetPropertysetEasingsetDurationsetDelay。 第一种方法被绑定到 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 intransition 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应用与美丽的动画。

 

文件附件: