聊天室里见到这样一个效果,有一行图块,中间放大的时候,周围图块要进行避让,并且降低透明度,当中间图块缩小时,周围图块要聚拢过来。
原来的代码中通过 Timer 类来控制时间间隔,用 TweenLite 来实现缓动的过程,其中还使用了外置的三个类,用来记录原始位置及位置点的运算,中间的一个核心算法函数更是复杂,代码如下:
function fadeIn(e:TimerEvent){
for(var i:int=0;i<icons.length;i++){
var ico:Icon=icons[i];
if(i!=2){
TweenLite.to(ico,.8,{x:ico.originPoint.x,alpha:1,ease:Back.easeOut});
}else{
TweenLite.to(ico,.8,{scaleX:ico.originScale.x,scaleY:ico.originScale.y,ease:Back.easeOut,onComplete:function(){
for(var i:int=0;i<icons.length;i++){
var ico:Icon=icons[i];
if(i==0){
ico.originPoint.x-=ico.width+span;
pico=new Icon(ico.frameId);
pico.originScale=new Scale(.5,.5);
pico.scaleX=.5;
pico.scaleY=.5;
pico.x=icons[icons.length-1].x+ico.width+span;
pico.y=ico.y;
pico.originPoint=new Point(icons[icons.length-1].x,ico.y);
addChild(pico);
}else{
ico.originPoint.x=icons[i-1].x;
}
TweenLite.to(ico,.8,{x:ico.originPoint.x,ease:Back.easeOut});
}
TweenLite.to(pico,.8,{x:pico.originPoint.x,ease:Back.easeOut,onComplete:function(){
var ico:Icon=icons.shift();
removeChild(ico);
icons.push(pico);
timer1.start();
}});
}});
}
}
}
这段函数中对 TweenLite 进行了三层嵌套使用,因此,不能自动套用格式,系统会报错,多一个花括号或是少一个也是不可以的。该动画效果引起了我的注意,并且发现 TweenLite 是一个可以替代 Tween 类的一个好东西。于是详细的翻译了TweenLite 的参数说明,并且对 TweenLite 有了更深入的了解。
当我对 TweenLite 了解更多之后,我发现
1.这个效果的核心是中间图块的缓动,其它图块只是根据中间的来进行相对运动,位置是可以简单计算的,因此不需要对所有图块都进行位置上的缓动处理。
2. TweenLite 提供有延迟处理参数 delay ,因此,在一个缓动完成后,我们可以通过参数指定下一次缓动开始的时间,从而避免使用 Timer 类来控制时间间隔。
3. TweenLite 在缓动开始、进行中、结束时均提供了调用函数的功能,这为我们提供了一个良好的代码流程结构,因此,不需要嵌套来写函数,我们的目的只是一个缓动结束后进行下一个缓动,那么在缓动结束时调用的函数中,加入下次缓动的代码就行了,阅读代码时会方便许多,而不会像上面显示的那样,难于调试,更不要说去扩充或是修改了。
总结以上三个问题之后,再来考虑这个效果,我们可以先将单独的图片加载到 mc 中,再将mc 统一放到一个数组中去,(图片较少时,也可以不用数组),每次只对中间的图块进行缓动,其它的图块做相应的位置调整,从而得到整体的运动效果。
import gs.TweenLite;
import gs.easing.*;
//因为 TweenLite 中提供有延迟缓动的参数 delay ,因此不需要使用定时器 timer 类,并且,缓动的开始、中间、结束位置
//均可以指定相关的处理函数,所以 timer 更加的不需要。
//第一步,将图块摆放到舞台上。原始图片较大,故采用 scalX = 0.47 ,图块间相隔15像素,图块的注册点在几何中心。
var pic_arr:Array = new Array();
pic_arr.push( new Pic1());
pic_arr.push( new Pic2());
pic_arr.push( new Pic3());
pic_arr.push( new Pic4());
pic_arr.push( new Pic5());
pic_arr.push( new Pic6());
var originScaleX:Number = 0.47; //最初的缩放比
var originWidth:Number = pic_arr[0].width * originScaleX;//最初的图片宽度
var dist = originWidth + 15;//图片间的坐标间隔
for (var i:int = 0; i<pic_arr.length; i++) {
//指定所有图块的大小及位置
pic_arr[i].scaleX = pic_arr[i].scaleY = originScaleX;
pic_arr[i].x = i * dist + 0.5 * originWidth + 15;
pic_arr[i].y = 200;
addChild( pic_arr[i] );
}
//第二步,建立位置移动函数,用来在中心图块放大或缩小时,调整其它图块的位置。
function pushAside( ){
//根据中心图块的大小变化,让周边图块发生移动
var step = pic_arr[2].width/2 + 0.5 * originWidth + 15;
pic_arr[0].x = pic_arr[2].x - step - dist;
pic_arr[1].x = pic_arr[2].x - step;
pic_arr[3].x = pic_arr[2].x + step;
pic_arr[4].x = pic_arr[2].x + step + dist;
pic_arr[5].x = pic_arr[2].x + step + 2 * dist;
}
//第三步,对中心图块进行缓动,这三个缓动效果是依次进行的,所以在onComplete 中指定的就是下次要执行的函数。
function enLargeMotion(){
//中心图块放大的效果
TweenLite.to(pic_arr[2], 0.8, {scaleX:0.8, scaleY:0.8, ease:Back.easeOut,delay:2,onStart:fadePic,onUpdate:pushAside,onComplete:toSmallMotion});
}
function toSmallMotion(){
//中心图块缩小的效果
TweenLite.to(pic_arr[2], 0.8, {scaleX:originScaleX, scaleY:originScaleX, ease:Back.easeOut,delay:1,onStart:lightPic,onUpdate:pushAside,onComplete:toLeftMotion});
}
function toLeftMotion(){
//中心图块向左移动的效果
var mc:MovieClip = pic_arr[2];
TweenLite.to(mc, 0.8, {x:mc.x - dist , ease:Back.easeOut,delay:1,onUpdate:pushAside,onComplete:rePlay});
}
//第四步,通过观察原来的效果,当中心图块放大时,其它的图块有一个变淡的效果,通过设置 onStart ,可以进行同步处理,这里需要添加两个函数,用来控制透明度的。
function fadePic(){
//降低透明度
TweenLite.to(pic_arr[0], 1, {alpha:0.5, ease:Back.easeOut});
TweenLite.to(pic_arr[1], 1, {alpha:0.5, ease:Back.easeOut});
TweenLite.to(pic_arr[3], 1, {alpha:0.5, ease:Back.easeOut});
TweenLite.to(pic_arr[4], 1, {alpha:0.5, ease:Back.easeOut});
TweenLite.to(pic_arr[5], 1, {alpha:0.5, ease:Back.easeOut});
}
function lightPic(){
//增大透明度
TweenLite.to(pic_arr[0], 1, {alpha:1, ease:Back.easeOut});
TweenLite.to(pic_arr[1], 1, {alpha:1, ease:Back.easeOut});
TweenLite.to(pic_arr[3], 1, {alpha:1, ease:Back.easeOut});
TweenLite.to(pic_arr[4], 1, {alpha:1, ease:Back.easeOut});
TweenLite.to(pic_arr[5], 1, {alpha:1, ease:Back.easeOut});
}
//第五步,三个缓动函数执行完后,需要再 rePlay(再来一遍),但是重来之前需要对数组内容进行调整,将第一个元素搬到最后去,其它依次向前动,数组的 shift 方法可以帮我们做到这一点,这样,始终都可以方便的找到中心图块 pic_arr[2] 。
function rePlay(){
//将数组中的首个图块搬到最后一个位置,同时将该块从舞台左侧移动到舞台右侧
var mc = pic_arr.shift();
pic_arr.push( mc );
mc.x = pic_arr[4].x + originWidth + 15;
//重新启动缓动效果
enLargeMotion();
}
//第六步,前面的函数依次调用关系建立之后,可以来观看我们的效果了,不要忘了用下面的代码让一切动起来, 一旦运动起来之后,函数之间的相互调用,会让缓动效果一直持续下去,如果担心时间的累积,会让图块产生漂移,可以在 rePlay 函数中用数字直接指定具体的位置,从而减少误差的累积。
//首次启缓动效果
enLargeMotion();
源文件下载
相关文章:
TweenFilterLite 参数说明 中文翻译
http://blog.5d.cn/user12/dzxz/200809/500545.html
TweenMax 参数说明 中文翻译
http://blog.5d.cn/user12/dzxz/200809/500547.html
TweenLite 参数说明 中文翻译
http://blog.5d.cn/user12/dzxz/200808/497831.html
一个Flash 网页导航效果
http://blog.5d.cn/user12/dzxz/200811/506117.html
个性签名 时钟版
http://blog.5d.cn/user12/dzxz/200810/504465.html