参考
cocos学习笔记 cc.tween
Cocos 3.0 缓动系统
一、基本用法
cc.tween 在调用 start 时会将之前生成的 action 队列重新组合生成一个 cc.sequence 队列,依次执行。
- to改变到某个值
- by 变化值
cc.tween(this.node)
//to,在第一秒的时候放大为2倍,位置为(100,100),角度变化到120
.to(1,{scale:2,position:cc.v2(100,100),rotation:120})
//by,在第二秒时,缩放变化1.5倍,即最终放大为原始大小的3倍,位置变化了(100,100),即现在位置为(200,200)
.by(1,{scale:1.5,position:cc.v2(100,100)})
//在第三秒时缩放为原来的大小,位置设置为(0,0),然后加了一个缓动效果backOut
.to(1,{scale:1,position:cc.v2(0,0)},{easing:"backOut"})
.start();
cc.tween还可以缓动任意对象的任意属性,如
var obj = { a: 0 }
cc.tween(obj)
.to(1, { a: 100 })
.start()
二、可选属性
以to为例,参考cc.d.ts
/**
* @en
* Add an action which calculate with absolute value.
* @zh
* 添加一个对属性进行绝对值计算的 action。
* @method to
* @param {number} duration 缓动时间,单位为秒
* @param {Object} props 缓动的属性列表
* @param {Object} [opts] 可选的缓动功能
* @param {Function} [opts.progress]
* @param {Function|String} [opts.easing]
*/
to(duration: number, props: __private.cocos_tween_tween_ConstructorType<T>, opts?: ITweenOption): Tween<T>;
可选属性定义如下:
interface ITweenOption {
easing?: TweenEasing | ((k: number) => number);
progress?: (start: number, end: number, current: number, ratio: number) => number;
onStart?: (target: object) => {};
onUpdate?: (target: object, ratio: number) => {};
onComplete?: (target: object) => {};
}
与 Creator v2.x 不同的是新增了 onStart、onUpdate、onComplete 等属性,这些属性是回调函数,调用时会传入缓动的目标。
另外,onUpdate 调用时还会多传入一个目前缓动的进行值,范围为 (0-1]。
以 onUpdate 为例,以下代码缓动一个位置,然后在 onUpdate 中将其设置到多个对象上,这样就像是缓动的合批。
import { Node, tween, Vec3 } from 'cc';
const nodeArray: Node[] = []; // 此处替换成你的节点数组
const tweenTargetVec3 = new Vec3();
tween(tweenTargetVec3)
.by(1, new Vec3(1, 1, 1), {
'onUpdate': (target: Vec3, ratio: number) => {
for (let i = 0; i < nodeArray.length; i++)
nodeArray[i].worldPosition = target;
}
}).start();
三、示例
具体的使用方法,详情请参考范例 Tween(GitHub | Gitee)。
1.repeat和repeatForever
* 添加一个重复 action,这个 action 会将前一个动作作为他的参数。
* @param {number} repeatTimes 重复次数
* @param {Tween<T>} embedTween 可选,嵌入 Tween
*/
repeat(repeatTimes: number, embedTween?: Tween<T>): Tween<T>;
* 添加一个永久重复 action,这个 action 会将前一个动作作为他的参数。
* @method repeatForever
* @param {Tween<T>} embedTween 可选,嵌入 Tween
*/
repeatForever(embedTween?: Tween<T>): Tween<T>;
下面两种写法效果一样的:
onLoad () {
this.tweenRepeat = tween(this.node)
.by(1, { scale: new Vec3(2, 2, 2) })
// 对前一个 by 重复执行 3次
.repeat(3)
.call(() => { console.log('All tweens finished.') })
//另外一种写法,repeat 重复的是嵌入的 Tween
this.tweenRepeat = tween(this.node)
.repeat(3, tween().by(1, { scale: new Vec3(2, 2, 2) }))
// 一直重复执行下去
this.tweenRF = tween(this.node)
.by(1, { scale: new Vec3(2, 2, 2) })
.repeatForever()
}
onEnable () {
this.tweenRepeat.start();
}
onDisable () {
this.tweenRepeat.stop();
}
2.delay
效果:方块会变大两次,第二次会等待1秒再变大
this.tweenDelay = tween(this.node)
// 延迟 1s
.delay(1)
.to(1, { scale: new Vec3(2, 2, 2) })
// 再延迟 1s
.delay(1)
.to(1, { scale: new Vec3(3, 3, 3) })
效果:方块在一秒后消失
/**
* 注意 target 需要是 Node 的,才可以使用 removeSelf
*/
this.tweenRemoveSelf = tween(this.node)
.delay(1)
.removeSelf()
效果:方块会不断的显示和隐藏
/**
* 注意 target 需要是 Node 的,才可以使用 show 和 hide
*/
this.tweenSH = tween(this.node)
.delay(0.1)
.hide()
.delay(0.1)
.show()
.union()
.repeatForever()
注:
* 将之前所有的 action 整合为一个 action。
*/
union(): Tween<T>;
3.parallel
this.tweenParallel = tween(this.node)
// 同时执行两个 Tween
.parallel(
tween().to(2, { scale: new Vec3(1, 2, 3) }),
tween().to(2, { position: new Vec3(3, 0, 3) })
)
.call(() => {
console.log('All tweens finished.')
})
也可以传一个数组,参考:
* 添加一个并行 action。
*/
parallel(...args: Tween<T>[]): Tween<T>;
4.then
效果:方块会先缩放,再旋转,再移动
let scale = tween().to(1, { scale: new Vec3(2, 2, 2) })
let rotate = tween().to(1, { eulerAngles: new Vec3(45, 45, 45) })
let move = tween().to(1, { position: new Vec3(0, 5, 0) })
// 先缩放,再旋转,再移动
this.tweenThen = tween(this.node)
.then(scale)
.then(rotate)
.then(move)
5.stop
效果:方块缩放后,就会停止运动
let scale = tween().to(1, { scale: new Vec3(3, 3, 3) })
let rotate = tween().to(1, { rotation: new Quat(Math.sin(60), Math.sin(60), Math.sin(60), Math.cos(60)) })
this.tweenStop = tween(this.node)
.then(scale)
.call(() => {
// 停止缓动
this.tweenStop.stop();
})
.then(rotate)
注:还有其它停止方法
* 停止所有缓动
*/
static stopAll(): void;
/**
* @zh
* 停止所有指定标签的缓动
*/
static stopAllByTag(tag: number, target?: object): void;
/**
* @zh
* 停止所有指定对象的缓动
*/
static stopAllByTarget(target?: object): void;
6.progress
相对于 easing,自定义 progress 函数可以更自由的控制缓动的过程。
效果:方块会移动,然后瞬间变大,再变小
// 对所有属性自定义 progress
const scaleTween = tween(this.node)
.to(2, { scale: new Vec3(3, 2, 1) }, {
progress: (start: number, end: number, current: number, ratio: number) => {
return start + (end - start) * ratio;
}
})
// 对单个属性自定义 progress
this.tweenCP = tween(this.node)
.to(2, { position: new Vec3(2, 2, -2) }, {
progress: (start: number, end: number, current: number, ratio: number) => {
return start + (end - start) * ratio * ratio * ratio;
}
}).reverseTime(scaleTween)
7.回调
效果:方块会变大,一秒后会瞬移,
接着继续变大,然后瞬间旋转
private tween!: Tween<Vec3>;
private _scale = new Vec3(1, 1, 1);
onLoad () {
const that = this;
let times = 0;
this.tween = tween(this._scale)
// 延迟 1s
.delay(1)
.by(1, new Vec3(1, 1, 1), {
'onStart': () => {
// 第二遍开始的时候,移动node
if (times == 1) that.node.translate(new Vec3(0, 10, 0));
},
'onUpdate': () => {
that.node.scale = that._scale;
},
'onComplete': () => {
// 第三遍完成的时候, 旋转Node
if (times == 2) that.node.rotate(Quat.fromEuler(new Quat(), 0, 45, 0));
times++;
}
})
.repeat(3)
}
8.clone
* 克隆当前 tween。
*/
clone(target: T): Tween<T>;
效果:两个方块会变大,然后停止
private tweenClone0!: Tween<{}>;
private tweenClone1!: Tween<{}>;
onLoad () {
// 先创建一个缓动作为模板
let tweenTemplate = tween({}).to(4, { scale: new Vec3(3, 3, 3) })
// 复制 tween,并使用节点 cocos 作为 target
this.tweenClone0 = tweenTemplate.clone(find('TweenClone/cocos')!);
// 复制 tween,并使用节点 cocos2 作为 target
this.tweenClone1 = tweenTemplate.clone(find('TweenClone/cocos2')!);
}
onEnable () {
this.tweenClone0.start()
this.tweenClone1.start()
}
onDisable () {
this.tweenClone0.stop()
this.tweenClone1.stop()
}