如果你经常跟动画打交道,特别经常要做一些广告宣传动画,你会发现有很多的动画效果是重复出现的。
这种情形,我们就可以使用GreenSock这个高性能的动画库把一些重复出现的动画效果封装起来,这样可以在遇到同样的动画效果时,不需要写很多重复的代码,直接调用相关封装好的方法就可以实现了。
下面我们就以一个小的banner动画为实例,来讲述如何使用GreenSock高效的编写动画效果。
HTML如下:
<div id="skyscrapper"></div>
接下来是添加实现动画效果所需要的元素:
<div id="skyscrapper">
<div id="box1" class="box"></div>
<div id="box2" class="box"></div>
<div id="box3" box="box"></div>
</div>
写一些简单的样式:
#sckyscrapper {
border: 1px solid black;
height: 118px;
width: 598px;
overflow: hidden;
}
.box {
background-color: black;
height: 50px;
width: 50px;
margin: 10px auto;
}
得到如下图所示的效果:
代码地址。
接下来添加一点点代码,让它动起来。
当然,动画效果还使用GreenSock来实现,GSAP Tweening library。
// We are using the Max flavour of the timeline in order to have the {repeat, yoyo, repeatDelay} options available
var tl = new TimelineMax({repeat:-1, yoyo:true, repeatDelay:1});
tl.from(["#box1,#box3"], 0.3, {x:"-=55%"});
tl.from("#box2", 0.3, {x:"+=55%"});
这里有什么问题么?当然没有。但是你想用多次的话,只能不停的复制粘贴这段代码,不断的重复这个动作。
那有什么办法可以高效点呢?下面就来重构下我们的代码,主要是用对象的方式来重构下代码。先声明一个Animation的对象,并且有一个els的参数,主要是用来传入需要运动的元素,从而实现动画效果。
// Create the animation that will be reused
var Animation = function(els) {
// Local Globals
var dur = 0.3,
amount = "55%",
tl = new TimelineMax({repeat:-1, yoyo:true, repeatDelay:1});
tl.add(fromLeft([els[0],els[2]]))
.add(fromRight(els[1]));
function fromLeft(el) {
return TweenMax.from(el, dur, {x:"-="+amount, autoAlpha:0});
}
function fromRight(el) {
return TweenMax.from(el, dur, {x:"+="+amount, autoAlpha:0});
}
}
// Then you instatiate the new class, normally from a separate JS file in order to be able to make the most of the modular approach of classes
var anim = new Animation(["#box1", "#box2", "#box3"]);
效果如下:
上面的代码,我们把动画封装在一个Animation对象里,遇到同类的动画的时候只需要调用一下这个方法,把需要运动的元素作为参数传入进去就可以了。
但是,这样就够了么?如果同时要运动5个元素呢?或者是每个元素需要运动的距离不一样呢?而我们封装好的对象并没有封装这个单独控制移动距离的功能。
利用JavaScript对象的特性来可以很好的解决这个问题,可以去这里更多的关于JavaScript面向对象编程的一些信息。
在js文件中,声明一个基本的对象:
var skyObj = {
leftAnimated: [box1,box3],
rightAnimated: box2,
amount: "55%"
}
然后再回到先前创建的Animation这个对象:
删除amount = "+=55%",修改一下我们的代码:
tl.add(fromLeft([els[0],els[2]]))
.add(fromRight(els[1]));
改为:
tl.add(fromLeft(els.leftAnimated, els.amount))
.add(fromRight(els.rightAnimated, els.amount));
上面对代码小小的进行一下改动,都改动了些什么呢?GreenSock提供了非常强大的功能,比如,可以单独针对每一个元素的属性定义不同的值从而实现不同的运动效果,所以我们上面改动添加了一个运动距离的参数,这样可以分别定义元素运动的方向和距离。
最后代码如下所示:
// Create the animation that will be reused
var Animation = function(els) {
// Local Globals
var dur = 0.3,
tl = new TimelineMax({repeat:-1, yoyo:true, repeatDelay:1});
tl.add(fromLeft(els.leftAnimated, els.amount))
.add(fromRight(els.rightAnimated, els.amount));
function fromLeft(el, amount) {
return TweenMax.from(el, dur, {x:"-="+amount, autoAlpha:0});
}
function fromRight(el, amount) {
return TweenMax.from(el, dur, {x:"+="+amount, autoAlpha:0});
}
}
// Create the objects that will contain the info for the animations
var skyObj = {
leftAnimated: [box1,box3],
rightAnimated: box2,
amount: "55%"
};
// Intantiate the different animations
var animSky = new Animation(skyObj);
改造之后就可以定义不同元素的动画,只需要传入需要的参数就可以了,比如我们需要两个元素从左边进入,另外一个元素从右边进入,就可以这样做:
// Create the objects that will contain the info for the animations
var skyObj = {
leftAnimated: [box1,box3],
rightAnimated: box2,
amount: "55%"
};
// Intantiate the different animations
var animSky = new Animation(skyObj);
本文主要是从Conditional animations with GreenSock and Objects这篇文章整理而来,有删减,有疏漏或者理解不到位的地方,还请多多指教!