Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add tween syntactic sugar #6327

Merged
merged 4 commits into from Mar 18, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
193 changes: 189 additions & 4 deletions cocos2d/actions/tween.js
@@ -1,3 +1,6 @@
import { bezier } from '../animation/bezier';

let _tweenID = 0;

let TweenAction = cc.Class({
name: 'cc.TweenAction',
Expand Down Expand Up @@ -164,7 +167,7 @@ let SetAction = cc.Class({
* .to(1, {scale: 2, position: cc.v3(100, 100, 100)})
* .call(() => { console.log('This is a callback'); })
* .by(1, {scale: 3, position: cc.v3(200, 200, 200)}, {easing: 'sineOutIn'})
* .run(cc.find('Canvas/cocos'));
* .start(cc.find('Canvas/cocos'));
*/
function Tween (target) {
this._actions = [];
Expand Down Expand Up @@ -215,15 +218,26 @@ Tween.prototype.target = function (target) {
* @return {Tween}
*/
Tween.prototype.start = function () {
if (!this._target) {
let target = this._target;
if (!target) {
cc.warn('Please set target to tween first');
return this;
}
if (target instanceof cc.Object && !target.isValid) {
return;
}

if (this._finalAction) {
cc.director.getActionManager().removeAction(this._finalAction);
}
this._finalAction = this._union();
cc.director.getActionManager().addAction(this._finalAction, this._target, false);

if (target._id === undefined) {
target._id = ++_tweenID;
}

cc.director.getActionManager().addAction(this._finalAction, target, false);

return this;
};

Expand Down Expand Up @@ -286,6 +300,177 @@ Tween.prototype._union = function () {
return actions;
};

Object.assign(Tween.prototype, {
/**
* !#en Sets target's position property according to the bezier curve.
* !#zh 按照贝塞尔路径设置目标的 position 属性。
* @method bezierTo
* @param {number} duration
* @param {[cc.Vec2, cc.Vec2, cc.Vec2]} controls
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这个数组解释下?为什么不拆分成三个参数?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

保持原有的接口。。

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

感觉拆开好像更清晰一些?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

那拆开吧

* @return {Tween}
*/
bezierTo (duration, controls) {
let c0x = controls[0].x, c0y = controls[0].y,
c1x = controls[1].x, c1y = controls[1].y;
opts = opts || Object.create(null);
opts.progress = function (start, end, current, t) {
current.x = bezier(start.x, c0x, c1x, end.x, t);
current.y = bezier(start.y, c0y, c1y, end.y, t);
return current;
}
return this.to(duration, { position: controls[2] }, opts);
},

/**
* !#en Sets target's position property according to the bezier curve.
* !#zh 按照贝塞尔路径设置目标的 position 属性。
* @method bezierBy
* @param {number} duration
* @param {[cc.Vec2, cc.Vec2, cc.Vec2]} controls
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这样写,d.ts能正常识别么,cc.Vec2[] 会不会好一点

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这么写是强制传 3 个 cc.Vec2 的 array, cc.Vec2[] 没有限制个数

* @return {Tween}
*/
bezierBy (duration, controls, opts) {
let c0x = controls[0].x, c0y = controls[0].y,
c1x = controls[1].x, c1y = controls[1].y;
opts = opts || Object.create(null);
opts.progress = function (start, end, current, t) {
let sx = start.x, sy = start.y;
current.x = bezier(sx, c0x + sx, c1x + sx, end.x, t);
current.y = bezier(sy, c0y + sy, c1y + sy, end.y, t);
return current;
}
return this.by(duration, { position: controls[2] }, opts);
},

/**
* !#en Flips target's scaleX
* !#zh 翻转目标的 scaleX 属性
* @method flipX
* @return {Tween}
*/
flipX () {
return this.call(() => { this._target.scaleX *= -1; }, this);
},
/**
* !#en Flips target's scaleY
* !#zh 翻转目标的 scaleY 属性
* @method flipY
* @return {Tween}
*/
flipY () {
return this.call(() => { this._target.scaleY *= -1; }, this);
},

/**
* !#en Blinks target by set target's opacity property
* !#zh 通过设置目标的 opacity 属性达到闪烁效果
* @method blink
* @param {number} duration
* @param {number} times
* @param {Object} [opts]
* @param {Function} [opts.progress]
* @param {Function|String} [opts.easing]
* @return {Tween}
*/
blink (duration, times, opts) {
var slice = 1.0 / times;
opts = opts || Object.create(null);
opts.progress = function (start, end, current, t) {
if (t >= 1) {
return start;
}
else {
var m = t % slice;
return (m > (slice / 2)) ? 255 : 0;
}
};
return this.to(duration, { opacity: 1 }, opts);
},

/**
* !#en Fade target's opacity property to the value.
* !#zh 修改目标的 opacity 属性到指定值。
* @method fadeTo
* @param {number} duration
* @param {number} opacity
* @param {Object} [opts]
* @param {Function} [opts.progress]
* @param {Function|String} [opts.easing]
* @return {Tween}
*/
fadeTo (duration, opacity, opts) {
return this.to(duration, { opacity }, opts);
},
/**
* !#en Fade target's opacity property to the value.
* !#zh 修改目标的 opacity 属性到指定值。
* @method fadeBy
* @param {number} duration
* @param {number} opacity
* @param {Object} [opts]
* @param {Function} [opts.progress]
* @param {Function|String} [opts.easing]
* @return {Tween}
*/
fadeBy (duration, opacity, opts) {
return this.by(duration, { opacity }, opts);
},
/**
* !#en Fade target's opacity property to 255.
* !#zh 修改目标的 opacity 属性到 255。
* @method fadeIn
* @param {number} duration
* @param {Object} [opts]
* @param {Function} [opts.progress]
* @param {Function|String} [opts.easing]
* @return {Tween}
*/
fadeIn (duration, opts) {
return this.to(duration, { opacity: 255 }, opts);
},
/**
* !#en Fade target's opacity property to 0.
* !#zh 修改目标的 opacity 属性到 0。
* @method fadeOut
* @param {number} duration
* @param {Object} [opts]
* @param {Function} [opts.progress]
* @param {Function|String} [opts.easing]
* @return {Tween}
*/
fadeOut (duration, opts) {
return this.to(duration, { opacity: 0 }, opts);
},
/**
* !#en Fade target's color property to the value.
* !#zh 修改目标的 color 属性到指定值。
* @method tintTo
* @param {number} duration
* @param {Color} color
* @param {Object} [opts]
* @param {Function} [opts.progress]
* @param {Function|String} [opts.easing]
* @return {Tween}
*/
tintTo (duration, color, opts) {
return this.to(duration, { color }, opts);
},
/**
* !#en Fade target's color property to the value.
* !#zh 修改目标的 color 属性到指定值。
* @method tintBy
* @param {number} duration
* @param {Color} color
* @param {Object} [opts]
* @param {Function} [opts.progress]
* @param {Function|String} [opts.easing]
* @return {Tween}
*/
tintBy (duration, color, opts) {
return this.by(duration, { color }, opts);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

flipX, Y,还有后面这些单行实现的封装感觉意义不大啊,他想要代码这么抽象的话自己封装一个小函数也行

Copy link
Contributor Author

@2youyou2 2youyou2 Mar 16, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

原 action 有的都可以有,已经有用户抱怨这些函数为什么没了

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这种就一行代码的,解释下吧,不然历史包袱都去不掉了

Copy link
Contributor Author

@2youyou2 2youyou2 Mar 16, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这些都是对 node 的扩展,要不加个 tween-extends-node.js,做个单独的扩展模块?
核心 tween 仍然是很干净的

})

let tmp_args = [];

function wrapAction (action) {
Expand Down Expand Up @@ -471,7 +656,7 @@ let keys = Object.keys(actions);
for (let i = 0; i < keys.length; i++) {
let key = keys[i];
Tween.prototype[key] = function () {
let action = actions[key].apply(actions, arguments);
let action = actions[key].apply(this, arguments);
this._actions.push(action);
return this;
};
Expand Down
6 changes: 6 additions & 0 deletions cocos2d/core/components/CCComponent.js
Expand Up @@ -31,6 +31,8 @@ var idGenerater = new (require('../platform/id-generater'))('Comp');
var IsOnEnableCalled = CCObject.Flags.IsOnEnableCalled;
var IsOnLoadCalled = CCObject.Flags.IsOnLoadCalled;

var ActionManagerExist = !!cc.ActionManager;

/**
* !#en
* Base class for everything attached to Node(Entity).<br/>
Expand Down Expand Up @@ -498,6 +500,10 @@ var Component = cc.Class({
},

_onPreDestroy () {
if (ActionManagerExist) {
cc.director.getActionManager().removeAllActionsFromTarget(this);
Copy link
Contributor Author

@2youyou2 2youyou2 Mar 13, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

节点已经在 _onPreDestroy 里停止 action 了。
我在考虑是不是需要在 CCObject 里面做,不过这样很多无关的也会去判断了。

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

只有组件和节点才需要吧……

}

// Schedules
this.unscheduleAllCallbacks();

Expand Down