动效
内容纲要
项目需要用到很多动效,但是很多开源动画效果没有很好的移植过来,这里做个记录,使用Typescript,其他ECMAScript实现都一样,游戏引擎Layabox、Egret、Cocos等也都一样。
动画类型
基本包含了常用的动画类型:
var arr: Array = [
"Linear",
"QuadEaseOut", "QuadEaseIn", "QuadEaseInOut", "QuadEaseOutIn",
"ExpoEaseOut", "ExpoEaseIn", "ExpoEaseInOut", "ExpoEaseOutIn",
"CubicEaseOut", "CubicEaseIn", "CubicEaseInOut", "CubicEaseOutIn",
"QuartEaseOut", "QuartEaseIn", "QuartEaseInOut", "QuartEaseOutIn",
"QuintEaseOut", "QuintEaseIn", "QuintEaseInOut", "QuintEaseOutIn",
"CircEaseOut", "CircEaseIn", "CircEaseInOut", "CircEaseOutIn",
"SineEaseOut", "SineEaseIn", "SineEaseInOut", "SineEaseOutIn",
"ElasticEaseOut", "ElasticEaseIn", "ElasticEaseInOut", "ElasticEaseOutIn",
"BounceEaseOut", "BounceEaseIn", "BounceEaseInOut", "BounceEaseOutIn",
"BackEaseOut", "BackEaseIn", "BackEaseInOut", "BackEaseOutIn"
];
然后就是实现:
enum ITweenType
{
Linear,
QuadEaseOut, QuadEaseIn, QuadEaseInOut, QuadEaseOutIn,
ExpoEaseOut, ExpoEaseIn, ExpoEaseInOut, ExpoEaseOutIn,
CubicEaseOut, CubicEaseIn, CubicEaseInOut, CubicEaseOutIn,
QuartEaseOut, QuartEaseIn, QuartEaseInOut, QuartEaseOutIn,
QuintEaseOut, QuintEaseIn, QuintEaseInOut, QuintEaseOutIn,
CircEaseOut, CircEaseIn, CircEaseInOut, CircEaseOutIn,
SineEaseOut, SineEaseIn, SineEaseInOut, SineEaseOutIn,
ElasticEaseOut, ElasticEaseIn, ElasticEaseInOut, ElasticEaseOutIn,
BounceEaseOut, BounceEaseIn, BounceEaseInOut, BounceEaseOutIn,
BackEaseOut, BackEaseIn, BackEaseInOut, BackEaseOutIn
}
class ITweener
{
public stepBackups = [];
public step = [];
public target : any;
public loop : number;
public index : number = 0;
public get(target : any, loop : number = 0)
{
this.target = target;
this.loop = loop;
return this;
}
public to(params : any, time : number, ease : ITweenType = ITweenType.Linear)
{
var obj : any = {};
obj.type = "to";
obj.startVals = Utils.Copy(params);
obj.endVals = params;
obj.endT = time;
obj.curT = 0;
obj.ease = ease;
obj.index = this.index++;
if(obj.index == 0)
{
for(var key in obj.startVals)
{
obj.startVals[key] = this.target[key];
}
}
this.step.push(obj);
if(this.loop != 0 && this.loop != 1)
this.stepBackups.push(Utils.Copy(obj));
return this;
}
public call(func)
{
var obj : any = {};
obj.type = "call";
obj.func = func;
this.step.push(obj);
if(this.loop != 0 && this.loop != 1)
this.stepBackups.push(Utils.Copy(obj));
return this;
}
public wait(time : number)
{
var obj : any = {};
obj.type = "wait";
obj.endT = time;
obj.curT = 0;
this.step.push(obj);
if(this.loop != 0 && this.loop != 1)
this.stepBackups.push(Utils.Copy(obj));
return this;
}
}
class ITween
{
private static tweenTable : Array<ITweener> = new Array();
public static Init()
{
egret.startTick(this.Update,this);
}
public static Play(wTweener : ITweener)
{
this.tweenTable.push(wTweener);
return wTweener;
}
public static Stop(wTweener : ITweener)
{
var index = -1;
for(var i = 0; i < this.tweenTable.length; i++)
{
if(this.tweenTable[i] == wTweener)
{
index = i;
break;
}
}
if(index != -1)
this.tweenTable.splice(index, 1);
}
private static timeOnEnterFrame:number = 0;
private static Update(timeStamp:number)
{
var now = timeStamp;
var time = this.timeOnEnterFrame;
var pass = now - time;
this.timeOnEnterFrame = now;
for(var i = 0; i < this.tweenTable.length; i++)
{
switch(this.tweenTable[i].step[0]["type"])
{
case "to":
if(this.tweenTable[i].step[0]["curT"] == 0)
{
if(this.tweenTable[i].step[0]["index"] != 0)
{
for(var key in this.tweenTable[i].step[0]["startVals"])
{
this.tweenTable[i].step[0]["startVals"][key] = this.tweenTable[i].target[key];
this.tweenTable[i].stepBackups.forEach((value,index,array)=>{
if(value["index"] != null && value["index"] == this.tweenTable[i].step[0]["index"])
this.tweenTable[i].stepBackups[index]["startVals"][key] = this.tweenTable[i].target[key];
})
}
}
}
if(this.tweenTable[i].step[0]["curT"] + pass < this.tweenTable[i].step[0]["endT"])
{
this.tweenTable[i].step[0]["curT"] += pass;
this.RunTween(this.tweenTable[i].target, this.tweenTable[i].step[0])
}
else
{
for(var key in this.tweenTable[i].step[0]["endVals"])
this.tweenTable[i].target[key] = this.tweenTable[i].step[0]["endVals"][key];
this.tweenTable[i].step.shift();
}
break;
case "call":
if(this.tweenTable[i].step[0]["func"] != null)
this.tweenTable[i].step[0]["func"].call();
this.tweenTable[i].step.shift();
break;
case "wait":
if(this.tweenTable[i].step[0]["curT"] < this.tweenTable[i].step[0]["endT"])
this.tweenTable[i].step[0]["curT"] += pass;
else
this.tweenTable[i].step.shift();
break;
}
if(this.tweenTable[i].step.length == 0)
{
if(this.tweenTable[i].loop > 1 || this.tweenTable[i].loop == -1)
{
if(this.tweenTable[i].loop > 1)
this.tweenTable[i].loop--;
this.tweenTable[i].step = Utils.Copy(this.tweenTable[i].stepBackups);
for(var j = 0; j < this.tweenTable[i].stepBackups.length; j++)
{
if(this.tweenTable[i].stepBackups[j]["type"] == "to")
{
for(var key in this.tweenTable[i].stepBackups[j]["startVals"])
{
this.tweenTable[i].target[key] = this.tweenTable[i].stepBackups[j]["startVals"][key];
}
break;
}
}
}
else
this.Stop(this.tweenTable[i]);
}
}
return true;
}
private static RunTween(target : any, obj : any)
{
for(var key in obj["endVals"])
{
var currentValue = 0;
switch(obj["ease"])
{
case ITweenType.Linear:
currentValue = this.Linear(obj["curT"], 0, obj["endVals"][key] - obj["startVals"][key], obj["endT"]);
break;
case ITweenType.BackEaseIn:
currentValue = this.BackEaseIn(obj["curT"], 0, obj["endVals"][key] - obj["startVals"][key], obj["endT"]);
break;
case ITweenType.BackEaseInOut:
currentValue = this.BackEaseInOut(obj["curT"], 0, obj["endVals"][key] - obj["startVals"][key], obj["endT"]);
break;
case ITweenType.BackEaseOut:
currentValue = this.BackEaseOut(obj["curT"], 0, obj["endVals"][key] - obj["startVals"][key], obj["endT"]);
break;
case ITweenType.BackEaseOutIn:
currentValue = this.BackEaseOutIn(obj["curT"], 0, obj["endVals"][key] - obj["startVals"][key], obj["endT"]);
break;
case ITweenType.BounceEaseIn:
currentValue = this.BounceEaseIn(obj["curT"], 0, obj["endVals"][key] - obj["startVals"][key], obj["endT"]);
break;
case ITweenType.BounceEaseInOut:
currentValue = this.BounceEaseInOut(obj["curT"], 0, obj["endVals"][key] - obj["startVals"][key], obj["endT"]);
break;
case ITweenType.BounceEaseOut:
currentValue = this.BounceEaseOut(obj["curT"], 0, obj["endVals"][key] - obj["startVals"][key], obj["endT"]);
break;
case ITweenType.BounceEaseOutIn:
currentValue = this.BounceEaseOutIn(obj["curT"], 0, obj["endVals"][key] - obj["startVals"][key], obj["endT"]);
break;
case ITweenType.CircEaseIn:
currentValue = this.CircEaseIn(obj["curT"], 0, obj["endVals"][key] - obj["startVals"][key], obj["endT"]);
break;
case ITweenType.CircEaseInOut:
currentValue = this.CircEaseInOut(obj["curT"], 0, obj["endVals"][key] - obj["startVals"][key], obj["endT"]);
break;
case ITweenType.CircEaseOut:
currentValue = this.CircEaseOut(obj["curT"], 0, obj["endVals"][key] - obj["startVals"][key], obj["endT"]);
break;
case ITweenType.CircEaseOutIn:
currentValue = this.CircEaseOutIn(obj["curT"], 0, obj["endVals"][key] - obj["startVals"][key], obj["endT"]);
break;
case ITweenType.CubicEaseIn:
currentValue = this.CubicEaseIn(obj["curT"], 0, obj["endVals"][key] - obj["startVals"][key], obj["endT"]);
break;
case ITweenType.CubicEaseInOut:
currentValue = this.CubicEaseInOut(obj["curT"], 0, obj["endVals"][key] - obj["startVals"][key], obj["endT"]);
break;
case ITweenType.CubicEaseOut:
currentValue = this.CubicEaseOut(obj["curT"], 0, obj["endVals"][key] - obj["startVals"][key], obj["endT"]);
break;
case ITweenType.CubicEaseOutIn:
currentValue = this.CubicEaseOutIn(obj["curT"], 0, obj["endVals"][key] - obj["startVals"][key], obj["endT"]);
break;
case ITweenType.ElasticEaseIn:
currentValue = this.ElasticEaseIn(obj["curT"], 0, obj["endVals"][key] - obj["startVals"][key], obj["endT"]);
break;
case ITweenType.ElasticEaseInOut:
currentValue = this.ElasticEaseInOut(obj["curT"], 0, obj["endVals"][key] - obj["startVals"][key], obj["endT"]);
break;
case ITweenType.ElasticEaseOut:
currentValue = this.ElasticEaseOut(obj["curT"], 0, obj["endVals"][key] - obj["startVals"][key], obj["endT"]);
break;
case ITweenType.ElasticEaseOutIn:
currentValue = this.ElasticEaseOutIn(obj["curT"], 0, obj["endVals"][key] - obj["startVals"][key], obj["endT"]);
break;
case ITweenType.ExpoEaseIn:
currentValue = this.ExpoEaseIn(obj["curT"], 0, obj["endVals"][key] - obj["startVals"][key], obj["endT"]);
break;
case ITweenType.ExpoEaseInOut:
currentValue = this.ExpoEaseInOut(obj["curT"], 0, obj["endVals"][key] - obj["startVals"][key], obj["endT"]);
break;
case ITweenType.ExpoEaseOut:
currentValue = this.ExpoEaseOut(obj["curT"], 0, obj["endVals"][key] - obj["startVals"][key], obj["endT"]);
break;
case ITweenType.ExpoEaseOutIn:
currentValue = this.ExpoEaseOutIn(obj["curT"], 0, obj["endVals"][key] - obj["startVals"][key], obj["endT"]);
break;
case ITweenType.QuadEaseIn:
currentValue = this.QuadEaseIn(obj["curT"], 0, obj["endVals"][key] - obj["startVals"][key], obj["endT"]);
break;
case ITweenType.QuadEaseInOut:
currentValue = this.QuadEaseInOut(obj["curT"], 0, obj["endVals"][key] - obj["startVals"][key], obj["endT"]);
break;
case ITweenType.QuadEaseOut:
currentValue = this.QuadEaseOut(obj["curT"], 0, obj["endVals"][key] - obj["startVals"][key], obj["endT"]);
break;
case ITweenType.QuadEaseOutIn:
currentValue = this.QuadEaseOutIn(obj["curT"], 0, obj["endVals"][key] - obj["startVals"][key], obj["endT"]);
break;
case ITweenType.QuartEaseIn:
currentValue = this.QuartEaseIn(obj["curT"], 0, obj["endVals"][key] - obj["startVals"][key], obj["endT"]);
break;
case ITweenType.QuartEaseInOut:
currentValue = this.QuartEaseInOut(obj["curT"], 0, obj["endVals"][key] - obj["startVals"][key], obj["endT"]);
break;
case ITweenType.QuartEaseOut:
currentValue = this.QuartEaseOut(obj["curT"], 0, obj["endVals"][key] - obj["startVals"][key], obj["endT"]);
break;
case ITweenType.QuartEaseOutIn:
currentValue = this.QuartEaseOutIn(obj["curT"], 0, obj["endVals"][key] - obj["startVals"][key], obj["endT"]);
break;
case ITweenType.QuintEaseIn:
currentValue = this.QuintEaseIn(obj["curT"], 0, obj["endVals"][key] - obj["startVals"][key], obj["endT"]);
break;
case ITweenType.QuintEaseInOut:
currentValue = this.QuintEaseInOut(obj["curT"], 0, obj["endVals"][key] - obj["startVals"][key], obj["endT"]);
break;
case ITweenType.QuintEaseOut:
currentValue = this.QuintEaseOut(obj["curT"], 0, obj["endVals"][key] - obj["startVals"][key], obj["endT"]);
break;
case ITweenType.QuintEaseOutIn:
currentValue = this.QuintEaseOutIn(obj["curT"], 0, obj["endVals"][key] - obj["startVals"][key], obj["endT"]);
break;
case ITweenType.SineEaseIn:
currentValue = this.SineEaseIn(obj["curT"], 0, obj["endVals"][key] - obj["startVals"][key], obj["endT"]);
break;
case ITweenType.SineEaseInOut:
currentValue = this.SineEaseInOut(obj["curT"], 0, obj["endVals"][key] - obj["startVals"][key], obj["endT"]);
break;
case ITweenType.SineEaseOut:
currentValue = this.SineEaseOut(obj["curT"], 0, obj["endVals"][key] - obj["startVals"][key], obj["endT"]);
break;
case ITweenType.SineEaseOutIn:
currentValue = this.SineEaseOutIn(obj["curT"], 0, obj["endVals"][key] - obj["startVals"][key], obj["endT"]);
break;
default:
currentValue = this.Linear(obj["curT"], 0, obj["endVals"][key] - obj["startVals"][key], obj["endT"]);
break;
}
target[key] = currentValue + obj["startVals"][key];
}
}
public static Linear(t : number, b : number, c : number, d : number)
{
return c * t / d + b;
}
public static ExpoEaseOut(t : number, b : number, c : number, d : number)
{
return (t == d) ? b + c : c * (-Math.pow(2, -10 * t / d) + 1) + b;
}
public static ExpoEaseIn(t : number, b : number, c : number, d : number)
{
return (t == 0) ? b : c * Math.pow(2, 10 * (t / d - 1)) + b;
}
public static ExpoEaseInOut(t : number, b : number, c : number, d : number)
{
if (t == 0)
return b;
if (t == d)
return b + c;
if ((t /= d / 2) < 1)
return c / 2 * Math.pow(2, 10 * (t - 1)) + b;
return c / 2 * (-Math.pow(2, -10 * --t) + 2) + b;
}
public static ExpoEaseOutIn(t : number, b : number, c : number, d : number)
{
if (t < d / 2)
return this.ExpoEaseOut(t * 2, b, c / 2, d);
return this.ExpoEaseIn((t * 2) - d, b + c / 2, c / 2, d);
}
public static CircEaseOut(t : number, b : number, c : number, d : number)
{
return c * Math.sqrt(1 - (t = t / d - 1) * t) + b;
}
public static CircEaseIn(t : number, b : number, c : number, d : number)
{
return -c * (Math.sqrt(1 - (t /= d) * t) - 1) + b;
}
public static CircEaseInOut(t : number, b : number, c : number, d : number)
{
if ((t /= d / 2) < 1)
return -c / 2 * (Math.sqrt(1 - t * t) - 1) + b;
return c / 2 * (Math.sqrt(1 - (t -= 2) * t) + 1) + b;
}
public static CircEaseOutIn(t : number, b : number, c : number, d : number)
{
if (t < d / 2)
return this.CircEaseOut(t * 2, b, c / 2, d);
return this.CircEaseIn((t * 2) - d, b + c / 2, c / 2, d);
}
public static QuadEaseOut(t : number, b : number, c : number, d : number)
{
return -c * (t /= d) * (t - 2) + b;
}
public static QuadEaseIn(t : number, b : number, c : number, d : number)
{
return c * (t /= d) * t + b;
}
public static QuadEaseInOut(t : number, b : number, c : number, d : number)
{
if ((t /= d / 2) < 1)
return c / 2 * t * t + b;
return -c / 2 * ((--t) * (t - 2) - 1) + b;
}
public static QuadEaseOutIn(t : number, b : number, c : number, d : number)
{
if (t < d / 2)
return this.QuadEaseOut(t * 2, b, c / 2, d);
return this.QuadEaseIn((t * 2) - d, b + c / 2, c / 2, d);
}
public static SineEaseOut(t : number, b : number, c : number, d : number)
{
return c * Math.sin(t / d * (Math.PI / 2)) + b;
}
public static SineEaseIn(t : number, b : number, c : number, d : number)
{
return -c * Math.cos(t / d * (Math.PI / 2)) + c + b;
}
public static SineEaseInOut(t : number, b : number, c : number, d : number)
{
if ((t /= d / 2) < 1)
return c / 2 * (Math.sin(Math.PI * t / 2)) + b;
return -c / 2 * (Math.cos(Math.PI * --t / 2) - 2) + b;
}
public static SineEaseOutIn(t : number, b : number, c : number, d : number)
{
if (t < d / 2)
return this.SineEaseOut(t * 2, b, c / 2, d);
return this.SineEaseIn((t * 2) - d, b + c / 2, c / 2, d);
}
public static CubicEaseOut(t : number, b : number, c : number, d : number)
{
return c * ((t = t / d - 1) * t * t + 1) + b;
}
public static CubicEaseIn(t : number, b : number, c : number, d : number)
{
return c * (t /= d) * t * t + b;
}
public static CubicEaseInOut(t : number, b : number, c : number, d : number)
{
if ((t /= d / 2) < 1)
return c / 2 * t * t * t + b;
return c / 2 * ((t -= 2) * t * t + 2) + b;
}
public static CubicEaseOutIn(t : number, b : number, c : number, d : number)
{
if (t < d / 2)
return this.CubicEaseOut(t * 2, b, c / 2, d);
return this.CubicEaseIn((t * 2) - d, b + c / 2, c / 2, d);
}
public static QuartEaseOut(t : number, b : number, c : number, d : number)
{
return -c * ((t = t / d - 1) * t * t * t - 1) + b;
}
public static QuartEaseIn(t : number, b : number, c : number, d : number)
{
return c * (t /= d) * t * t * t + b;
}
public static QuartEaseInOut(t : number, b : number, c : number, d : number)
{
if ((t /= d / 2) < 1)
return c / 2 * t * t * t * t + b;
return -c / 2 * ((t -= 2) * t * t * t - 2) + b;
}
public static QuartEaseOutIn(t : number, b : number, c : number, d : number)
{
if (t < d / 2)
return this.QuartEaseOut(t * 2, b, c / 2, d);
return this.QuartEaseIn((t * 2) - d, b + c / 2, c / 2, d);
}
public static QuintEaseOut(t : number, b : number, c : number, d : number)
{
return c * ((t = t / d - 1) * t * t * t * t + 1) + b;
}
public static QuintEaseIn(t : number, b : number, c : number, d : number)
{
return c * (t /= d) * t * t * t * t + b;
}
public static QuintEaseInOut(t : number, b : number, c : number, d : number)
{
if ((t /= d / 2) < 1)
return c / 2 * t * t * t * t * t + b;
return c / 2 * ((t -= 2) * t * t * t * t + 2) + b;
}
public static QuintEaseOutIn(t : number, b : number, c : number, d : number)
{
if (t < d / 2)
return this.QuintEaseOut(t * 2, b, c / 2, d);
return this.QuintEaseIn((t * 2) - d, b + c / 2, c / 2, d);
}
public static ElasticEaseOut(t : number, b : number, c : number, d : number)
{
if ((t /= d) == 1)
return b + c;
var p = d * 0.3;
var s = p / 4;
return (c * Math.pow(2, -10 * t) * Math.sin((t * d - s) * (2 * Math.PI) / p) + c + b);
}
public static ElasticEaseIn(t : number, b : number, c : number, d : number)
{
if ((t /= d) == 1)
return b + c;
var p = d * 0.3;
var s = p / 4;
return -(c * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p)) + b;
}
public static ElasticEaseInOut(t : number, b : number, c : number, d : number)
{
if ((t /= d / 2) == 2)
return b + c;
var p = d * (0.3 * 1.5);
var s = p / 4;
if (t < 1)
return -0.5 * (c * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p)) + b;
return c * Math.pow(2, -10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p) * 0.5 + c + b;
}
public static ElasticEaseOutIn(t : number, b : number, c : number, d : number)
{
if (t < d / 2)
return this.ElasticEaseOut(t * 2, b, c / 2, d);
return this.ElasticEaseIn((t * 2) - d, b + c / 2, c / 2, d);
}
public static BounceEaseOut(t : number, b : number, c : number, d : number)
{
if ((t /= d) < (1 / 2.75))
return c * (7.5625 * t * t) + b;
else if (t < (2 / 2.75))
return c * (7.5625 * (t -= (1.5 / 2.75)) * t + 0.75) + b;
else if (t < (2.5 / 2.75))
return c * (7.5625 * (t -= (2.25 / 2.75)) * t + 0.9375) + b;
else
return c * (7.5625 * (t -= (2.625 / 2.75)) * t + .984375) + b;
}
public static BounceEaseIn(t : number, b : number, c : number, d : number)
{
return c - this.BounceEaseOut(d - t, 0, c, d) + b;
}
public static BounceEaseInOut(t : number, b : number, c : number, d : number)
{
if (t < d / 2)
return this.BounceEaseIn(t * 2, 0, c, d) * 0.5 + b;
else
return this.BounceEaseOut(t * 2 - d, 0, c, d) * 0.5 + c * 0.5 + b;
}
public static BounceEaseOutIn(t : number, b : number, c : number, d : number)
{
if (t < d / 2)
return this.BounceEaseOut(t * 2, b, c / 2, d);
return this.BounceEaseIn((t * 2) - d, b + c / 2, c / 2, d);
}
public static BackEaseOut(t : number, b : number, c : number, d : number)
{
return c * ((t = t / d - 1) * t * ((1.70158 + 1) * t + 1.70158) + 1) + b;
}
public static BackEaseIn(t : number, b : number, c : number, d : number)
{
return c * (t /= d) * t * ((1.70158 + 1) * t - 1.70158) + b;
}
public static BackEaseInOut(t : number, b : number, c : number, d : number)
{
var s = 1.70158;
if ((t /= d / 2) < 1)
return c / 2 * (t * t * (((s *= (1.525)) + 1) * t - s)) + b;
return c / 2 * ((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2) + b;
}
public static BackEaseOutIn(t : number, b : number, c : number, d : number)
{
if (t < d / 2)
return this.BackEaseOut(t * 2, b, c / 2, d);
return this.BackEaseIn((t * 2) - d, b + c / 2, c / 2, d);
}
}
然后是utils:
class Utils{
public static Copy (o) {
if (o instanceof Array)
{
var a = [];
for (var i = 0; i < o.length; ++i) {
a[i] = Utils.Copy(o[i]);
}
return a;
}
else if (o instanceof Function)
{
var b = o;
return b;
}
else if (o instanceof Object)
{
var c = {}
for (var j in o) {
c[j] = Utils.Copy(o[j]);
}
return c;
}
else
{
return o;
}
}
}
测试,以Egret引擎为例:
class Main extends eui.UILayer {
protected createChildren(): void {
super.createChildren();
WTween.Init();
}
//...
protected gameScene(): void {
for(var i = 0; i < 3; i++)
{
let icon: egret.Bitmap = this.createBitmapByName("test_png");
this.addChild(icon);
icon.x = 0 + i * 120;
icon.y = 0;
ITween.Play(new WTweener()
.get(icon, -1)
.to({y:400, alpha:0.5}, 3000, ITweenType.Linear)
.call(()=>{
})
.wait(1500)
.call(()=>{
}));
}
}
}
就这样吧。
code enjoy!🤩🤩🤩
作者:indeex
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。