Creator | tween 常用方法及扩展暂停/恢复/跳转指定时间等

​更舒适的阅读体验,请扫码关注公众号:
[image]​

01

常用方法

· 基本方法

to:对属性进行绝对值计算,最终的运行结果即是设置的属性值,即改变到某个值

by:对属性进行相对值计算,最终的运行结果是设置的属性值加上开始运行时节点的属性值,即变化值

cc.tween(this.node)
    .to(1, { position: cc.v2(100, 100), angle: -90 })
    .by(1, { scale: 2 })
    .start();

贝塞尔曲线:

cc.tween(this.node)
    .bezierTo(3, cc.v2(0, cc.winSize.height / 2), cc.v2(300, -cc.winSize.height / 2), cc.v2(300, 100))
    .start();

· 支持缓动任意对象的任意属性

let obj = { a: 0 }
cc.tween(obj)
    .to(1, { a: 100 })
    .start();

· 变速 easing

cc.tween(this.node)
    .to(1, { scale: 2, position: cc.v2(100, 100), angle: -90 }, cc.easeIn(3.0))
    .start();

· 自定义 progress

// 对所有属性自定义 progress
cc.tween().to(1, { scale: 2, rotation: 90 }, {
    progress: (start, end, current, ratio) => {
        return start + (end - start) * ratio;
    }
})
// 对单个属性自定义 progress
cc.tween().to(1, {
    scale: 2,
    position: {
        value: cc.v3(),
        progress: (start, end, current, t) => {
            // 注意,传入的属性为 cc.Vec3,所以需要使用 Vec3.lerp 进行插值计算
            return start.lerp(end, t, current);
        }
    }
})

· 插入其他的缓动到队列中

let scale = cc.tween().to(1, { scale: 2 });
let rotate = cc.tween().to(1, { angle: -90 });
let move = cc.tween().to(1, { position: cc.v3(100, 100, 100) });
// 先缩放再旋转
cc.tween(this.node).then(scale).then(rotate);
// 先缩放再移动
cc.tween(this.node).then(scale).then(move);

then 不仅可以插入 tween,还可以插入 action,比如跳跃(jumpTo)等

let jumpTo = cc.jumpTo(2, cc.v2(300, 300), 50, 4);
cc.tween(this.node)
    .then(jumpTo)
    .start();

· 并行执行缓动

let t = cc.tween;
t(this.node)
    // 同时执行两个 cc.tween
    .parallel(
        t().to(1, { scale: 2 }),
        t().to(2, { position: cc.v2(100, 100) })
    )
    .call(() => {
        console.log('All tweens finished.');
    })
    .start();

· 回调

cc.tween(this.node)
    .to(2, { angle: -90 })
    .to(1, { scale: 2 })
    // 当前面的动作都执行完毕后才会调用这个回调函数
    .call(() => { cc.log('This is a callback'); })
    .start();

· 重复执行

repeat:重复指定次数

cc.tween(this.node)
    .by(1, { scale: 1 })
    // 对前一个 by 重复执行 10次
    .repeat(10)
    // 最后 node.scale === 11
    .start();

repeatForever:无限重复

cc.tween(this.node)
    .by(1, { scale: 1 })
    .repeatForever()
    .start();

union:

repeat/repeatForever 函数只会将前一个 action 作为作用对象,如果希望重复多个 action 话,可是使用 union(将之前所有的 action 整合为一个 action)

cc.tween(this.node)
    .by(2, { angle: -90 })
    .by(1, { scale: 2 })
    .union()
    .repeat(10)
    .start();

· 延迟执行

cc.tween(this.node)
    // 延迟 1s
    .delay(1)
    .to(1, { scale: 2 })
    // 再延迟 1s
    .delay(1)
    .to(1, { scale: 3 })
    .start();

· 暂停/恢复/停止

暂停本节点上所有正在运行的动作

this.node.pauseAllActions();

[image]

恢复运行本节点上所有暂停的动作

this.node.resumeAllActions();

[image]

停止当前 tween

tween.stop();

[image]

停止所有指定对象的缓动

cc.Tween.stopAllByTarget(this.node);

[image]

停止所有指定标签的缓动

cc.Tween.stopAllByTag(100);

[image]

02

扩展方法

cocos 提供的暂停/恢复只能控制节点上所有的动作,所以这里通过对 tween 扩展,实现单个 tween 的控制

tween 在 start 后,会返回的是一个 _finalAction,通过对其属性的读写,可以实现一些想要的功能

[image]

下面的代码中扩展了 tween 的暂停、恢复、倍速播放、总时长、已进行时长、跳转到指定时间、根据标签暂停、恢复

cc.ActionInterval.prototype.step = function (dt) {
    if (this.paused) {
        return;
    }
    if (this._firstTick && !this._goto) {
        this._firstTick = false;
        this._elapsed = 0;
    } else {
        this._elapsed += dt;
    }
    let t = this._elapsed / (this._duration > 0.0000001192092896 ? this._duration : 0.0000001192092896);
    t = (1 > t ? t : 1);
    this.update(t > 0 ? t : 0);
    //Compatible with repeat class, Discard after can be deleted (this._repeatMethod)
    if (this._repeatMethod && this._timesForRepeat > 1 && this.isDone()) {
        if (!this._repeatForever) {
            this._timesForRepeat--;
        }
        this.startWithTarget(this.target);
        this.step(this._elapsed - this._duration);
    }
};
/**
 * 暂停
 * @example tween.pause();
 */
cc.Tween.prototype.pause = function () {
    this._finalAction.paused = true;
};
/**
 * 恢复
 * @example tween.resume();
 */
cc.Tween.prototype.resume = function () {
    this._finalAction.paused = false;
};
/**
 * 倍速播放
 * @param speed 倍速
 * @example tween.speed(2);
 */
cc.Tween.prototype.speed = function (speed) {
    this._finalAction._speedMethod = true;
    this._finalAction._speed = speed;
}
/**
 * 获取持续时间
 * @example let duration = tween.duration();
 */
cc.Tween.prototype.duration = function () {
    return this._finalAction._duration;
}
/**
 * 获取已经进行的时间
 * @example let elapsed = tween.elapsed();
 */
cc.Tween.prototype.elapsed = function () {
    return this._finalAction._elapsed;
}
/**
 * 跳转到指定时间
 * @param time 时间(秒)
 * @example tween.goto(2);
 */
cc.Tween.prototype.goto = function (time) {
    this._finalAction._goto = true;
    this._finalAction._elapsed = time;
}
cc.ActionManager.prototype.pauseByTag = function (tag, pause) {
    if (tag === cc.Action.TAG_INVALID) {
        cc.logID(1002);
    }
    let hashTargets = this._hashTargets;
    for (let name in hashTargets) {
        let element = hashTargets[name];
        for (let i = 0, l = element.actions.length; i < l; ++i) {
            let action = element.actions[i];
            if (action && action.getTag() === tag) {
                action.paused = pause;
                break;
            }
        }
    }
}
/**
 * 根据标签暂停动作
 * @param tag tween的标签
 * @example cc.Tween.pauseByTag(100);
 */
cc.Tween.pauseByTag = function (tag) {
    cc.director.getActionManager().pauseByTag(tag, true);
}
/**
 * 根据标签恢复动作
 * @param tag tween的标签
 * @example cc.Tween.resumeByTag(100);
 */
cc.Tween.resumeByTag = function (tag) {
    cc.director.getActionManager().pauseByTag(tag, false);
}

因为是自己扩展的方法,creator.d.ts 中没有相关声明,可以利用 vs code 来自动添加相关声明

[image]

[image]

git:

https://gitee.com/Valiancer/r-framework-open.git

23赞

大佬牛:cow::cow::cow::cow:

顶起顶起,鸦哥 :cow: :beer:

阔以,阔以,大佬强啊

3.3.0的贝塞尔缓动能做一个吗?

mark!!

学到了,学到了

3.0的贝塞尔缓动没了

markmark

:laughing: :laughing:真好,终于大概理解了tween的一些逻辑了,感谢大佬

简单实用~~~ :clap::clap::clap::clap::clap:

mark!

great job :smiling_face_with_three_hearts:

写的真好,赞

插个眼~~~~~~~

marklll

mark!!!

你看这个排版,你再看那些显示不出来的图片,哪点好了 :rofl:

3.6.3想要实现tween的暂停和恢复,请问这些扩展方法的代码应该放在哪里啊?