Tween缓动动画
当我们搞事的产品经理要求做一个抛物线运动的效果,参考网上的资料与实际需要,就自己写了一套通用实现。垂直和水平的移动不用多做介绍,重点是曲线运动。有个著名的曲线叫贝塞尔曲线,运用相关数学公式,可以写出比较满意的效果。除此以外,后期做了运动对象的兼容,让文字、位图文本、图片和逐帧动画都可以作相应的运动。
预先设定好相关结构体ITween_D1
2
3
4
5
6
7
8
9
10
11
12export interface ITween_D {//自定义运动参数接口
"o_type": string;//当前运动对象类型,label,blabel,image,mc
"o_param": any;//当前运动对象携带参数,如文本,图片资源名,mc的id。
"t_type": string;//运动类型,bse,zx(拼音首字母)
"t_param": {//运动参数。
"ex": number;//结束点x坐标
"ey"?: number;//结束点y坐标
"ax"?: number;//运动锚点x坐标
"ay"?: number;//运动锚点y坐标
};
"c_time"?: number;//运动时间,默认为500(逻辑帧整数倍)。
}
按照结构的数据格式传入即可
代码实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139 /**
* Tween动画
**/
export class mxTweenObj extends egret.DisplayObjectContainer
{
//目標组件类型,label:普通文本,blabel:位图文本,image:图片,mc:动画
private o_type : string;
private o_param : any;//目标携带参数
//Tween类型,bse:贝塞尔曲线,zx:直线
private t_type : string;
private t_param : any;//tween参数
private c_obj : any;//需要進行tween操作的物体。
private c_tween : any;//tween实例
private c_time : any;
private bse_ex : any;//终点
private bse_ey : any;
private bse_ax : any;//参照点
private bse_ay : any;
public constructor(mx : ITween_D){
super();
for(let i in mx){
this[i] = mx[i];
}
this.init_param();
}
private init_param():void{
//运动轨迹
switch(this.t_type){
case "bse"://贝塞尔曲线,需要终点和参照点
this.bse_ex = this.t_param.ex;//>0
this.bse_ey = this.t_param.ey || 0;
this.bse_ax = this.t_param.ax || this.t_param.ex * 0.5;
if(this.t_param.ay){
this.bse_ay = this.t_param.ay
}else{
this.bse_ay = 0 - Math.abs(this.bse_ex);
}
break;
case "vertical":
this.bse_ex = this.t_param.ex;//>0
this.bse_ey = this.t_param.ey || 0;
this.bse_ax = this.t_param.ax || this.t_param.ex * 0.5;
if(this.t_param.ay){
this.bse_ay = this.t_param.ay
}else{
this.bse_ay = 0 - Math.abs(this.bse_ex);
}
break;
case "zx":
this.bse_ex = this.t_param.ex || 0;//>0
this.bse_ey = this.t_param.ey || 0;
break;
default:
break;
}
//运动的对象,可以是文字,位图文本,图像,动画
let c_t, str, font= "";
switch(this.o_type){
case "label":
str = "+" + this.o_param;
font = "add_ybi_fnt";
c_t = new eui.BitmapLabel(str);
c_t.font = font;
break;
case "blabel":
if(this.o_param < 0){
str = "" + this.o_param;
font = "sub_blood_fnt";
}else{
str = "+" + this.o_param;
font = "add_blood_fnt";
}
c_t = new eui.BitmapLabel(str);
c_t.font = font;
break;
case "image":
c_t = new eui.Image(this.o_param + "_png");
break;
case "mc":
c_t = new GeneralEffect(this.o_param);
c_t.play_by_times(-1);
break;
default:
break;
}
c_t.addEventListener(egret.Event.ADDED_TO_STAGE, this.onAddToStage, this);
this.c_obj = c_t;
this.addChild(c_t);
}
private onAddToStage(event:egret.Event) {
//加载到舞台
this.c_obj.removeEventListener(egret.Event.ADDED_TO_STAGE, this.onAddToStage, this);
this.c_tween = egret.Tween.get(this).to({mx:1}, this.c_time);
this.c_tween.call(this.on_remove, this);
}
public set mx(v:number){
switch(this.t_type){
case "bse"://贝塞尔运动,抛物线
this.c_obj.x = 2 * v * (1 - v) * this.bse_ax + v * v * this.bse_ex;
this.c_obj.y = 2 * v * (1 - v) * this.bse_ay + v * v * this.bse_ey;
let tan = 0 - (this.bse_ay - 2 * this.bse_ay * v + this.bse_ey * v) /
(this.bse_ax - 2 * this.bse_ax * v + this.bse_ex * v);
let c_r = 0 - Math.atan(tan) / Math.PI * 180;
this.c_obj.rotation = c_r;
break;
case "vertical"://垂直
this.c_obj.x = 2 * v * (1 - v) * this.bse_ax + v * v * this.bse_ex;
this.c_obj.y = 4 * v * (1 - v) * this.bse_ay + v * v * this.bse_ey;
break;
case "zx"://水平直线
this.c_obj.x = v * this.bse_ex;
this.c_obj.y = v * this.bse_ey;
break;
default:
break;
}
}
public get mx():number{
return 0;
}
//记得释放
public on_remove():void{
egret.Tween.removeTweens(this);
this.c_tween = null;
if(this.c_obj){
this.c_obj.removeEventListener(egret.Event.ADDED_TO_STAGE, this.onAddToStage, this);
this.c_obj = null;
}
this.removeChildren();
if(this.parent){
this.parent.removeChild(this);
}
}
}
使用的时候如下1
2
3
4
5
6
7let mxd = {
/*按需求自行填写参数*/
}
let mxto = new mxTweenObj(mxd);
mxto.x = 0;//自行指定坐标
mxto.y = 0;//自行指定坐标
stage.addChild(mxto);