Cocos 3.x Tween 缓动

参考
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();
三、示例

具体的使用方法,详情请参考范例 TweenGitHub | 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()
}
9.cc.tween,我想要缓动cc.blink,闪烁动作,可是cc.blick并没有to和by缓动属性,请问下该怎么设置
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,425评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,058评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,186评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,848评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,249评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,554评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,830评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,536评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,239评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,505评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,004评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,346评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,999评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,060评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,821评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,574评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,480评论 2 267

推荐阅读更多精彩内容