就像许多开发者确信的那样,在Web上使用CSS实现动画并不是唯一的方式,我们也可以使用JS来实现,并且JS还有一些CSS无法替代的优势。
然而抛开JS而选择CSS来实现动画,将以样式表内容膨胀,丧失对动画时间的控制为代价,并且无法灵活地实现基于物理运动模型的动画设计。
不要误导我! CSS动画在Web中扮演重要的角色-----独自的实现动画或是同JS协作实现。 特别的,CSS在一些简单基本的动画交互上表现的特别好,比如hover
和focus
等。(作者的意思是:客观的看待CSS动画和JS动画,他们各有优点)
然而,对于几乎所有事情,JS都是不错的选择,因为他的能力太强大了。
如果我说JS的动画性能比CSS出色,你可能不会相信我。可能你曾经有使用jQuery设计动画的糟糕经历,比如动画出现抖动、不平滑,然后草率地归咎于JS语言。
完全不对,不要混淆JS和jQuery这俩种不同的生物。
jQuery 是由许多原生JS写的函数组成的库,就像C++的标准库一样。jQuery原本不是以动画引擎为目标设计的,而是为了使烦人的DOM操作变得方便高效(效果确实令人惊讶).
幸运的是目前就有一些开源的动画库,使得你可以绕开jQuery去利用原生JS那令人惊叹的魔力。通过这些动画库,您可以建立一个可控的动画工作流,而且这一切都基于能大幅提升网站动画性能的特征层之上。
我将带领你快速地了解Velocity.js,以便于你设计炫目平滑并且易配置的动画。
What is Velocity.js?
Velocity专为动画而设计 ,简单易用,功能强大,广泛地被一些主流公司所使用(包括Tumblr, Microsoft and WhatsApp)。并且Velocity 是基于MIT许可协议的开源库。
Velocity模仿了jQuery的语法,可以完美地同jQuery协作,当然也能独立地使用,所以对你来说应该很容易学。由于jQuery使用普遍,我也将向你展示Velocity如何同它协作。
Note: 为了提高你所有动画的性能,只需要简单地将目前jQuery的
animate()
函数调用换成velocity()
,因为Velocity将原来jQueryanimate()
函数的语法和功能在velocity()
函数内部都做了解释映射,所以能兼容以前animate()
的使用方式(velocity()
还扩展了animate()
的功能)。但即使是这样的一个小改变,也能使你的网站有一个显著的性能提升。
Velocity还有许多需要了解的地方。在我们深入之前,让我们快速地了解一下他能干什么,以便让你明白他的价值。
下面是一些不可能用CSS简单实现的JS动画。
Page Scrolling
现在有一个流行的Web设计,即在一个长页面中有序放置所有内容,只需轻微滑动一下鼠标,窗口就会平滑地滚动到恰当的页面区域,而不是像传统一样导航到另一个不同的页面。这是JS动画最流行的一种应用,并且无法用CSS实现。
而在Velocity里,你只需在目标元素上调用velocity()
方法并传入"scroll"命令和过渡时间:
$element.velocity("scroll", 1000);
这个方法将使浏览器滚动到选定的元素(jQuery对象,$element),过渡时间为1000ms。仅使用jQuery实现这个功能也会很复杂,而且将用到多个函数操作。
对于这条代码不太明白也没有关系;我们将在了解velocity几个巧妙的功能之后慢慢弄懂他。
Animation Reversal
在jQuery中,想要使元素恢复成动画运行之前的状态,你必须手动的设置元素原来的属性值,比如:
$element.animate({ width: "100px" }, 400);
// 又使元素在400ms内回复成原来50px的宽度
$element.animate({ width: "50px" }, 400);
相较地,在Velocity里只是一个运行"reversr"命令:
// 先将宽度变到100px
$element.velocity({ width: "100px" }, 400);
//在400ms内回到原来的状态
$element.velocity("reverse");
$element.velocity("reverse");
这条命令将使$element
回到运行$element.velocity({ width: "100px" }, 400);
前的状态,而你不用手动的去设置目标 width (50px).
Physics-Based Motion
现实世界的运动模型既不是线性的也不是平滑的。它有快速的部分,有慢的部分,可能存在摩擦,甚至需要考虑重量。使用JS可以很好地模拟这些运动,并且看起来非常的自然。而线性的运动效果看起来则非常机械,不怎么中看。
为了方便模拟现实世界的运动,Velocity提供弹性动画功能(spring),以一个张弛度(默认500)和一个摩擦系数(默认值20)作为他的参数(参考Velocity的文档获取更多信息)
Example:
$element.velocity({ width: "100px"}, [ 1000, 40 ]);
较高的张弛度将提高整体速度和动画的反弹力度,较小的摩擦系数将提高动画结束时的速度。(较大的摩擦系数将使动画快速减速)。调整这些值会让每个动画独一无二,逼真并且有趣。(具体操作一下感觉更直观)
上面那个示例运行起来应该非常快,非常灵动(因为设置了较大的张弛度),并且将快速减速,在接近动画末尾的时候速度将变得很慢。(因为设置了较大的摩擦系数)。
PS:小编在这里解释一下,
spring
是动画选项中easing
的一个可选值,至于easing
是什么在后面有介绍。这里仅仅解释一下spring
到底是 什么玩意儿。准确的讲spring
对应一个JS函数,而这个函数描述的是一个运动模型,什么模型呢?答案是弹簧振子模型 ,想必大家初中的时候就做过这种物理题了。spring
的俩个参数---张弛度和摩擦系数,其实就对应弹簧的初始弹性势能和地面的摩擦系数。 大家自己都可以把这个模型写出来。
Okay great, so how do I use it?
已经听够他能做什么了!今天让我们来探究一下怎么去用它。就像我之前提到的一样,Velocity可以独立使用,也可以和jQuery一起使用以获得一个快速高效的结果(因为jQuery使得选择元素变得非常容易)。
第一步是下载Velocity.js,然后包含到你的页面中去(原文的叙述考虑到文档是否解析完毕的问题,特别提到应将它放到</body>
之前)
Example:
<script src="//code.jquery.com/jquery-2.1.1.min.js"></script>
<script src="//cdn.jsdelivr.net/velocity/1.1.0/velocity.min.js"></script>
Note: 如果你正在使用jQuery,确保载入jQuery的script标签出现在载入velocity的script标签之前,因为velocity需要根据是否使用jQuery来调整他的API。一旦使用了velocity,你可以在使用jQuery
animate
的地方使用它的基本功能。然而想要充分使用它的强大功能的话还有几个附加设置。比如animation reversals, transforms, spring physics, chaining, and color animations
(所有这些将在下面讲到)。但这还不是所有,查看文档获取更多的信息。
现在让我们看看velocity真正的语法到底是什么样的。(之前都是类jQuery的)
Arguments
Velocity 接收一个或更多的参数,只有第一个参数是是强制要求的,它可以是一个命令(就像上面例子中的”scroll”),或者是由CSS属性值组成的对象(这些值是动画的目标值):
$element.velocity({ opacity: "50%", left: "500px"});
第二个参数是由动画附加选项组成的对象,比如过渡时长,张弛度,延时还有回调函数。
Data Object
// 200ms之后在200ms的时间内,透明度变到50%
$element.velocity({ opacity: "50%" }, { delay: 200, duration :200 });
另外作为一种可选的快捷方式,你可以以任何顺序以逗号隔开的形式传递时长,张弛度(easing)和回调函数中的一个或多个参数,然而如果你想再传入其他动画选项的话必须使用数据对象的形式,而且这俩种方式不能混合使用。对于这里小编举几个例子说明:
//200ms的时长,easing是swing,最后加个回调函数
$element.velocity({left:”1000px”},200,”swing”,function(){console.log(“ok”)});
//等价于$element.velocity({left:”1000px”},{“duration”:200,”easing”:”swing”,”complete”:function(){console.log(“ok”);})
//下面这个用法是错的,俩种风格不能混用
$element.velocity({ left: "50px" }, 500, "ease-in-out", function () { alert("done") }, { delay: 200 });
//改为:
$element.velocity({left:”50px”},{“easing”:”ease-in-out”,”duration”:500,”complete”:function(){alert(“done”);}});
Note: 第二类参数是可选择的(原文是第二个参数,但从上面的例子可以看出可以是不止俩个参数,从参数分类上却恰好是俩类,所以小编这里将其译为第二类(
properties
和options
俩类,在其官方文档中可以看出来)),因为对于那些重要的属性都有默认值,比如easing
的默认值是swing
,duration
的默认值是400ms。所有其他的动画选项都是可选的。
同时你只能为每一个CSS属性设置一个值,所以 “padding:’10px 15px’”这样的设置是不合法的。替代做法是单独设置每一个分属性:{paddingLeft:”10px”,paddingTop:”15px”,….}
。这样不仅表达清晰,而且意味着你可以特别指定每一个css分属性的值,而不是只设置一个整体的,给予了你足够的空间定制动画。
Note: 有多个单词描述的CSS属性(比如
font-size
和padding-left
)必须使用骆驼拼写法表示(fontSize
&&paddingLeft
).
Property values
如果CSS属性值没有给定确切的单位,那么时间默认是:ms
,长度默认是 px
,角度默认是 deg
。为了表达清晰最好还是显示注明单位,那样以后再看代码时也容易理解。如果有一个值不仅仅由数字表示,那么必须加引号。比如:duration:500
(默认是500ms
)是合法的,但是duration:500ms
就不合法,必须加上引号:duration:”500ms”
.
JS动画运许传入简单的表达式作为CSS的属性值,但这些表达式只限于:+=
,-=
,*=
,/=
,表示目标值在其本来的值的基础上加多少,减多少,乘多少,除多少,任何其他的表达式是不允许的。实例:
$element.velocity({
width: "+= 50px", // Adds 50px to the current width value
eight: "/= 2" // divides the current height value by two
});
表示动画完成后width
比原值大50px
,height
变为原来的二分之一。
在Velocity动画引擎里使用这些快速功能保证了动画的逻辑可读性,使代码简洁清晰(消除了值的手工计算),而且向Velocity引擎提供更多有关于你动画意图的信息将有助于提高动画的性能。动画逻辑包含的越多,Velocity就能更好地提高代码的性能。
Chaining
Velocity的链式调用即在同一个元素上一个动画完成之后马上进入另一个动画,这样一个一个的执行下去:
$element
.velocity({ width: "500px", height: "300px"})
.velocity({ opacity: 0 });
等价于:
$element.velocity({ width: "500px", height: "300px"});
$element.velocity({ opacity: 0 });
就如之前提到的一样,这允许你不需要任何手动的计算,就能使那些复杂的、有时间限制的多级动画如当初计划的一样,一个接一个的执行。
Easing
我已经在文章里多次提到easing
这个词了,或许你一直想弄明白它究竟是什么意思。easing
是一些数学函数,他们决定了一个动画在不同阶段的速度(其实就是物理的运动模型)。比如:ease-in-out
表示先加速再减速。linear
表示匀速。
你可以在easing
选项里指定easing
的类型;
$element.velocity({ top: 100 }, { easing: "ease-in-out" });
easing
也是使用之前提到的弹性动画的一种方式。你可以只传入spring
来使用它(默认张弛度500,阻力系数:20),也可以像下面那样手动指定参数来使用:
$element.velocity({ width: 500 }, { easing: [ 250, 10 ] });
easing
还有很多复杂难懂的内容,因为文章篇幅的原因,也就只介绍到这里。更多的信息可以从官方文档中获取。
Color
Velocity 允许制作基于颜色变换的动画,比如:color
, backgroundColor
, borderColor
还有outlineColor
.所有这些颜色的值只允许是16进制的字符串(黑色:#000000 , 脸谱蓝:#3b5998(for Facebook blue) ).也许你想使用rgb格式的颜色设置,甚至指定颜色透明度(值介于0到1),只需简单地在CSS颜色名后面加上“Red”,“Green”,”Blue” 或者“Alpha”即可:
$element.velocity({
borderColor: "#f06d06",
backgroundColorAlpha: 0.8,//背景颜色透明度变到80%
colorBlue: 200//rgb 方式
});
Scrolling
如早些说过的一样 ,scroll
命令将促使页面滚动到指定元素的上边缘,你可以向其他动画一样传递同样的附加选项,并且同样支持链式调用。
$element
.velocity("scroll", { duration: 1000 })
.velocity({ opacity: 1 });
//默认的滚动沿y轴方向,想改到x轴方向的话可以使用axis选项:
$element.velocity("scroll", { axis: "x" });
Velocity允许你设置窗口滚动后元素上边缘距窗口上边缘的距离,你只需设置 offset
选项即可完成:
// 滚动之后窗口上边缘将位于元素上边缘之上100px的地方
$element.velocity("scroll", { duration: 1000, offset: "-100px" });
//滚动之后窗口上边缘将位于元素上边缘之下100px的地方
$element.velocity("scroll", { duration: 1000, offset: "100px" });
Transforms
想要结合CSS和JS设计动画? 设置一些CSS变换规则,允许你做一些2D或3D的动画,比如平移,扩大,旋转。注意这些变换不会影响元素在网页中的位置,也不会影响该元素周围 的元素在页面中的位置。 Velocity支持下面的变换:
-
translateX
: 从左向右沿x轴移动元素 -
translateY
: 从上到下沿y轴移动元素 -
rotateZ
: 关于z轴旋转元素 -
rotateX
: 关于x轴旋转元素(看起来由里向外) -
rotateY
: 关于y轴旋转元素(由左到右) -
scaleX
: 成倍数改变元素宽度 -
scaleY
: 成倍数改变元素高度
$element.velocity({
rotateZ: "90deg", // rotate clockwise 90 degrees
scaleX: 2.0 // double the width
});
Going Forward
动画使得静态页面更具交互性,更加栩栩如生,而JS动画则是最好的实现方式。 CSS动画可选的功能有限,更新慢;而对于JS动画,在开源世界则有一大堆库和插件,并且维护地很好。使用这些JS工具将使得你的动画设计更具有可能性。
除了在这里演示的外,Velocity还有很多其他的功能,小编强烈建议看看它的文档。现在就开始动手吧!:)
Bonus!
最后,额外的俩点:查看这个教程了解怎样使用Velocity的UI包来改善用户界面。还有您也可以查看这里的velocity 示例。